From e43b737f2c1591fa03bbf126b4019645e0e13ac7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 08 2020 16:57:24 +0000
Subject: [PATCH 1/2232] Release 0.1.0


---

diff --git a/Cargo.toml b/Cargo.toml
index a6d34cc..d111367 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,9 +1,9 @@
 [package]
 name = "cxx"
-version = "0.0.0"
+version = "0.1.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge00"
+links = "cxxbridge01"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
@@ -18,7 +18,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
-cxxbridge-macro = { version = "0.0", path = "macro" }
+cxxbridge-macro = { version = "0.1", path = "macro" }
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
diff --git a/README.md b/README.md
index 5ea03ee..a978e96 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ using bindgen or cbindgen to generate unsafe C-style bindings.
 
 ```toml
 [dependencies]
-cxx = "0.0"
+cxx = "0.1"
 ```
 
 *Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
@@ -294,9 +294,9 @@ of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
 <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td></td><td></td><td></td></tr>
 </table>
 
diff --git a/build.rs b/build.rs
index 4d8292e..f16f265 100644
--- a/build.rs
+++ b/build.rs
@@ -2,7 +2,7 @@ fn main() {
     cc::Build::new()
         .file("src/cxxbridge.cc")
         .flag("-std=c++11")
-        .compile("cxxbridge00");
+        .compile("cxxbridge01");
     println!("cargo:rustc-flags=-l dylib=stdc++");
     println!("cargo:rerun-if-changed=src/cxxbridge.cc");
     println!("cargo:rerun-if-changed=include/cxxbridge.h");
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index b3f7719..0cfe883 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.0.0"
+version = "0.1.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/write.rs b/gen/write.rs
index fd92d50..81f26b8 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -124,10 +124,10 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
 
-    out.begin_block("namespace cxxbridge00");
+    out.begin_block("namespace cxxbridge01");
     if needs_rust_box {
         writeln!(out, "// #include \"cxxbridge.h\"");
-        for line in include::get("CXXBRIDGE00_RUST_BOX").lines() {
+        for line in include::get("CXXBRIDGE01_RUST_BOX").lines() {
             if !line.trim_start().starts_with("//") {
                 writeln!(out, "{}", line);
             }
@@ -146,7 +146,7 @@ fn write_namespace_alias(out: &mut OutFile, types: &Types) {
     }
 
     if needs_namespace_alias {
-        writeln!(out, "namespace cxxbridge = cxxbridge00;");
+        writeln!(out, "namespace cxxbridge = cxxbridge01;");
     }
 }
 
@@ -176,7 +176,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
-    write!(out, "cxxbridge00${}(", efn.ident);
+    write!(out, "cxxbridge01${}(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -244,7 +244,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
-    write!(out, "cxxbridge00${}(", efn.ident);
+    write!(out, "cxxbridge01${}(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -299,7 +299,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
         }
-        write!(out, "cxxbridge00${}(", efn.ident);
+        write!(out, "cxxbridge01${}(", efn.ident);
         for (i, arg) in efn.args.iter().enumerate() {
             if i > 0 {
                 write!(out, ", ");
@@ -435,7 +435,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     }
     out.end_block();
 
-    out.begin_block("namespace cxxbridge00");
+    out.begin_block("namespace cxxbridge01");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -455,34 +455,34 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE00_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE00_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE01_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge00$rust_box${}$uninit(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$uninit(cxxbridge::RustBox<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge00$rust_box${}$set_raw(cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$rust_box${}$set_raw(cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge00$rust_box${}$drop(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$drop(cxxbridge::RustBox<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge00$rust_box${}$deref(const cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$rust_box${}$deref(const cxxbridge::RustBox<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge00$rust_box${}$deref_mut(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$rust_box${}$deref_mut(cxxbridge::RustBox<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE00_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
@@ -498,7 +498,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "void RustBox<{}>::uninit() noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge00$rust_box${}$uninit(this);",
+        "  return cxxbridge01$rust_box${}$uninit(this);",
         instance
     );
     writeln!(out, "}}");
@@ -511,7 +511,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "  return cxxbridge00$rust_box${}$set_raw(this, raw);",
+        "  return cxxbridge01$rust_box${}$set_raw(this, raw);",
         instance
     );
     writeln!(out, "}}");
@@ -520,7 +520,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "void RustBox<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge00$rust_box${}$drop(this);",
+        "  return cxxbridge01$rust_box${}$drop(this);",
         instance
     );
     writeln!(out, "}}");
@@ -533,7 +533,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "  return cxxbridge00$rust_box${}$deref(this);",
+        "  return cxxbridge01$rust_box${}$deref(this);",
         instance
     );
     writeln!(out, "}}");
@@ -546,7 +546,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "  return cxxbridge00$rust_box${}$deref_mut(this);",
+        "  return cxxbridge01$rust_box${}$deref_mut(this);",
         instance
     );
     writeln!(out, "}}");
@@ -561,8 +561,8 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE00_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE00_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE01_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE01_UNIQUE_PTR_{}", instance);
     writeln!(
         out,
         "static_assert(sizeof(std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -575,14 +575,14 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "void cxxbridge00$unique_ptr${}$null(std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$null(std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge00$unique_ptr${}$new(std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$new(std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
         instance, inner, inner,
     );
     writeln!(
@@ -593,31 +593,31 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge00$unique_ptr${}$raw(std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$raw(std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge00$unique_ptr${}$get(const std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge01$unique_ptr${}$get(const std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge00$unique_ptr${}$release(std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge01$unique_ptr${}$release(std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge00$unique_ptr${}$drop(std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$drop(std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE00_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE01_UNIQUE_PTR_{}", instance);
 }
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 3135092..a0d9dbb 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -4,7 +4,7 @@
 #include <iostream>
 #include <string>
 
-namespace cxxbridge00 {
+namespace cxxbridge01 {
 
 class RustString final {
 public:
@@ -58,8 +58,8 @@ private:
   Repr repr;
 };
 
-#ifndef CXXBRIDGE00_RUST_BOX
-#define CXXBRIDGE00_RUST_BOX
+#ifndef CXXBRIDGE01_RUST_BOX
+#define CXXBRIDGE01_RUST_BOX
 template <typename T> class RustBox final {
 public:
   RustBox(const RustBox &other) : RustBox(*other) {}
@@ -122,11 +122,11 @@ private:
   T *deref_mut() noexcept;
   uintptr_t repr;
 };
-#endif // CXXBRIDGE00_RUST_BOX
+#endif // CXXBRIDGE01_RUST_BOX
 
 std::ostream &operator<<(std::ostream &os, const RustString &s);
 std::ostream &operator<<(std::ostream &os, const RustStr &s);
 
-} // namespace cxxbridge00
+} // namespace cxxbridge01
 
-namespace cxxbridge = cxxbridge00;
+namespace cxxbridge = cxxbridge01;
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index f7256e0..2d14527 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.0.0"
+version = "0.1.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -19,4 +19,4 @@ quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.0", path = ".." }
+cxx = { version = "0.1", path = ".." }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 63f7032..e631e67 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -128,7 +128,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = format!("{}cxxbridge00${}", namespace, ident);
+    let link_name = format!("{}cxxbridge01${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
@@ -266,7 +266,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         expr = quote!(::std::ptr::write(__return, #expr));
     }
     let ret = expand_extern_return_type(&efn.ret, types);
-    let link_name = format!("{}cxxbridge00${}", namespace, ident);
+    let link_name = format!("{}cxxbridge01${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     quote! {
@@ -280,7 +280,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge00$rust_box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge01$rust_box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_set_raw = format!("{}set_raw", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
@@ -337,7 +337,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let prefix = format!("cxxbridge00$unique_ptr${}{}$", namespace, ident);
+    let prefix = format!("cxxbridge01$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index c169797..40a1731 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -4,9 +4,9 @@ use std::slice;
 use std::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge00$cxx_string$data"]
+    #[link_name = "cxxbridge01$cxx_string$data"]
     fn string_data(_: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge00$cxx_string$length"]
+    #[link_name = "cxxbridge01$cxx_string$length"]
     fn string_length(_: &CxxString) -> usize;
 }
 
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 3d1a902..a502d20 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -3,48 +3,48 @@
 #include <memory>
 #include <stdexcept>
 
-namespace cxxbridge = cxxbridge00;
+namespace cxxbridge = cxxbridge01;
 
 extern "C" {
-const char *cxxbridge00$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge00$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
 // RustString
-void cxxbridge00$rust_string$new(cxxbridge::RustString *self) noexcept;
-void cxxbridge00$rust_string$clone(cxxbridge::RustString *self,
+void cxxbridge01$rust_string$new(cxxbridge::RustString *self) noexcept;
+void cxxbridge01$rust_string$clone(cxxbridge::RustString *self,
                                    const cxxbridge::RustString &other) noexcept;
-bool cxxbridge00$rust_string$from(cxxbridge::RustString *self, const char *ptr,
+bool cxxbridge01$rust_string$from(cxxbridge::RustString *self, const char *ptr,
                                   size_t len) noexcept;
-void cxxbridge00$rust_string$drop(cxxbridge::RustString *self) noexcept;
+void cxxbridge01$rust_string$drop(cxxbridge::RustString *self) noexcept;
 const char *
-cxxbridge00$rust_string$ptr(const cxxbridge::RustString *self) noexcept;
-size_t cxxbridge00$rust_string$len(const cxxbridge::RustString *self) noexcept;
+cxxbridge01$rust_string$ptr(const cxxbridge::RustString *self) noexcept;
+size_t cxxbridge01$rust_string$len(const cxxbridge::RustString *self) noexcept;
 
 // RustStr
-bool cxxbridge00$rust_str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
-namespace cxxbridge00 {
+namespace cxxbridge01 {
 
-RustString::RustString() noexcept { cxxbridge00$rust_string$new(this); }
+RustString::RustString() noexcept { cxxbridge01$rust_string$new(this); }
 
 RustString::RustString(const RustString &other) noexcept {
-  cxxbridge00$rust_string$clone(this, other);
+  cxxbridge01$rust_string$clone(this, other);
 }
 
 RustString::RustString(RustString &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge00$rust_string$new(&other);
+  cxxbridge01$rust_string$new(&other);
 }
 
 RustString::RustString(const char *s) {
   auto len = strlen(s);
-  if (!cxxbridge00$rust_string$from(this, s, len)) {
+  if (!cxxbridge01$rust_string$from(this, s, len)) {
     throw std::invalid_argument("data for RustString is not utf-8");
   }
 }
@@ -52,12 +52,12 @@ RustString::RustString(const char *s) {
 RustString::RustString(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
-  if (!cxxbridge00$rust_string$from(this, ptr, len)) {
+  if (!cxxbridge01$rust_string$from(this, ptr, len)) {
     throw std::invalid_argument("data for RustString is not utf-8");
   }
 }
 
-RustString::~RustString() noexcept { cxxbridge00$rust_string$drop(this); }
+RustString::~RustString() noexcept { cxxbridge01$rust_string$drop(this); }
 
 RustString::operator std::string() const {
   return std::string(this->data(), this->size());
@@ -65,31 +65,31 @@ RustString::operator std::string() const {
 
 RustString &RustString::operator=(const RustString &other) noexcept {
   if (this != &other) {
-    cxxbridge00$rust_string$drop(this);
-    cxxbridge00$rust_string$clone(this, other);
+    cxxbridge01$rust_string$drop(this);
+    cxxbridge01$rust_string$clone(this, other);
   }
   return *this;
 }
 
 RustString &RustString::operator=(RustString &&other) noexcept {
   if (this != &other) {
-    cxxbridge00$rust_string$drop(this);
+    cxxbridge01$rust_string$drop(this);
     this->repr = other.repr;
-    cxxbridge00$rust_string$new(&other);
+    cxxbridge01$rust_string$new(&other);
   }
   return *this;
 }
 
 const char *RustString::data() const noexcept {
-  return cxxbridge00$rust_string$ptr(this);
+  return cxxbridge01$rust_string$ptr(this);
 }
 
 size_t RustString::size() const noexcept {
-  return cxxbridge00$rust_string$len(this);
+  return cxxbridge01$rust_string$len(this);
 }
 
 size_t RustString::length() const noexcept {
-  return cxxbridge00$rust_string$len(this);
+  return cxxbridge01$rust_string$len(this);
 }
 
 std::ostream &operator<<(std::ostream &os, const RustString &s) {
@@ -101,13 +101,13 @@ RustStr::RustStr() noexcept
     : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
 RustStr::RustStr(const char *s) : repr(Repr{s, strlen(s)}) {
-  if (!cxxbridge00$rust_str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for RustStr is not utf-8");
   }
 }
 
 RustStr::RustStr(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge00$rust_str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for RustStr is not utf-8");
   }
 }
@@ -138,30 +138,30 @@ std::ostream &operator<<(std::ostream &os, const RustStr &s) {
   return os;
 }
 
-} // namespace cxxbridge00
+} // namespace cxxbridge01
 
 extern "C" {
-void cxxbridge00$unique_ptr$std$string$null(
+void cxxbridge01$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge00$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
+void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
                                            std::string *value) noexcept {
   new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
 }
-void cxxbridge00$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge00$unique_ptr$std$string$get(
+const std::string *cxxbridge01$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge00$unique_ptr$std$string$release(
+std::string *cxxbridge01$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge00$unique_ptr$std$string$drop(
+void cxxbridge01$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
diff --git a/src/lib.rs b/src/lib.rs
index 8ed9572..5c018c2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -298,9 +298,9 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+//! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
 //!
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 5aeac28..59a7784 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -23,7 +23,7 @@ impl RustStr {
     }
 }
 
-#[export_name = "cxxbridge00$rust_str$valid"]
+#[export_name = "cxxbridge01$rust_str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 5756efa..250a46f 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -26,17 +26,17 @@ impl RustString {
     }
 }
 
-#[export_name = "cxxbridge00$rust_string$new"]
+#[export_name = "cxxbridge01$rust_string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge00$rust_string$clone"]
+#[export_name = "cxxbridge01$rust_string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge00$rust_string$from"]
+#[export_name = "cxxbridge01$rust_string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -52,17 +52,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge00$rust_string$drop"]
+#[export_name = "cxxbridge01$rust_string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge00$rust_string$ptr"]
+#[export_name = "cxxbridge01$rust_string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge00$rust_string$len"]
+#[export_name = "cxxbridge01$rust_string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index f6d2e86..19718bb 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -130,17 +130,17 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge00$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge00$unique_ptr$std$string$new"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$new"]
     fn unique_ptr_std_string_new(this: *mut *mut c_void, value: *mut CxxString);
-    #[link_name = "cxxbridge00$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge00$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge00$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge00$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge01$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 

From ccd3975f4086fc6dbc87e0b1c53b15122dd48c2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 08 2020 17:35:04 +0000
Subject: [PATCH 2/2232] Add a brief safety explanation up top


---

diff --git a/README.md b/README.md
index a978e96..cdd2e51 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,12 @@ This library provides a **safe** mechanism for calling C++ code from Rust and
 Rust code from C++, not subject to the many ways that things can go wrong when
 using bindgen or cbindgen to generate unsafe C-style bindings.
 
+This doesn't change the fact that 100% of C++ code is unsafe. When auditing a
+project, you would be on the hook for auditing all the unsafe Rust code and
+*all* the C++ code. The core safety claim under this new model is that auditing
+just the C++ side would be sufficient to catch all problems, i.e. the Rust side
+can be 100% safe.
+
 ```toml
 [dependencies]
 cxx = "0.1"
diff --git a/src/lib.rs b/src/lib.rs
index 5c018c2..50bf516 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,12 @@
 //! and Rust code from C++, not subject to the many ways that things can go
 //! wrong when using bindgen or cbindgen to generate unsafe C-style bindings.
 //!
+//! This doesn't change the fact that 100% of C++ code is unsafe. When auditing
+//! a project, you would be on the hook for auditing all the unsafe Rust code
+//! and *all* the C++ code. The core safety claim under this new model is that
+//! auditing just the C++ side would be sufficient to catch all problems, i.e.
+//! the Rust side can be 100% safe.
+//!
 //! <br>
 //!
 //! *Compiler support: requires rustc 1.42+ (beta on January 30, stable on March

From 84f232ed0b8e3d871d94dc4fbf71946dcd5d039c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 08 2020 20:22:56 +0000
Subject: [PATCH 3/2232] Fill in blank table cells with placeholder


---

diff --git a/README.md b/README.md
index cdd2e51..e7eaa3a 100644
--- a/README.md
+++ b/README.md
@@ -316,13 +316,13 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;[T]</td><td></td></tr>
-<tr><td>Vec&lt;T&gt;</td><td></td></tr>
-<tr><td>BTreeMap&lt;K, V&gt;</td><td></td></tr>
-<tr><td>HashMap&lt;K, V&gt;</td><td></td></tr>
-<tr><td></td><td>std::vector&lt;T&gt;</td></tr>
-<tr><td></td><td>std::map&lt;K, V&gt;</td></tr>
-<tr><td></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td>&amp;[T]</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 </table>
 
 <br>
diff --git a/src/lib.rs b/src/lib.rs
index 50bf516..5331084 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -320,13 +320,13 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th></tr>
-//! <tr><td>&amp;[T]</td><td></td></tr>
-//! <tr><td>Vec&lt;T&gt;</td><td></td></tr>
-//! <tr><td>BTreeMap&lt;K, V&gt;</td><td></td></tr>
-//! <tr><td>HashMap&lt;K, V&gt;</td><td></td></tr>
-//! <tr><td></td><td>std::vector&lt;T&gt;</td></tr>
-//! <tr><td></td><td>std::map&lt;K, V&gt;</td></tr>
-//! <tr><td></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+//! <tr><td>&amp;[T]</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
+//! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
+//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! </table>
 
 #![deny(improper_ctypes)]

From 17955e2e8c73f132191db4ea213c5e73ebdb4c9b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:09:41 +0000
Subject: [PATCH 4/2232] Implement special case types in extern Rust argument position


---

diff --git a/gen/write.rs b/gen/write.rs
index 81f26b8..eb11470 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -308,6 +308,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 write!(out, "&");
             }
             write!(out, "{}", arg.ident);
+            match arg.ty {
+                Type::RustBox(_) => write!(out, ".into_raw()"),
+                Type::UniquePtr(_) => write!(out, ".release()"),
+                _ => {}
+            }
         }
         if indirect_return {
             if !efn.args.is_empty() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e631e67..ac10b78 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -231,10 +231,21 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     let args = efn.args.iter().map(|arg| expand_extern_arg(arg, types));
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        if types.needs_indirect_abi(&arg.ty) {
+        let var = if types.needs_indirect_abi(&arg.ty) {
             quote!(::std::ptr::read(#ident))
         } else {
             quote!(#ident)
+        };
+        match &arg.ty {
+            Type::Ident(ident) if ident == "String" => quote!(#var.into_string()),
+            Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#var)),
+            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#var)),
+            Type::Ref(ty) => match &ty.inner {
+                Type::Ident(ident) if ident == "String" => quote!(#var.as_string()),
+                _ => var,
+            },
+            Type::Str(_) => quote!(#var.as_str()),
+            _ => var,
         }
     });
     let mut outparam = None;

From 94a5cdb033160f2dbb87cf7b9b41000ed48a97f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:11:32 +0000
Subject: [PATCH 5/2232] Merge pull request #14 from dtolnay/rustarg


Implement special case types in extern Rust argument position
---

diff --git a/gen/write.rs b/gen/write.rs
index 81f26b8..eb11470 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -308,6 +308,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 write!(out, "&");
             }
             write!(out, "{}", arg.ident);
+            match arg.ty {
+                Type::RustBox(_) => write!(out, ".into_raw()"),
+                Type::UniquePtr(_) => write!(out, ".release()"),
+                _ => {}
+            }
         }
         if indirect_return {
             if !efn.args.is_empty() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e631e67..ac10b78 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -231,10 +231,21 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     let args = efn.args.iter().map(|arg| expand_extern_arg(arg, types));
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        if types.needs_indirect_abi(&arg.ty) {
+        let var = if types.needs_indirect_abi(&arg.ty) {
             quote!(::std::ptr::read(#ident))
         } else {
             quote!(#ident)
+        };
+        match &arg.ty {
+            Type::Ident(ident) if ident == "String" => quote!(#var.into_string()),
+            Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#var)),
+            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#var)),
+            Type::Ref(ty) => match &ty.inner {
+                Type::Ident(ident) if ident == "String" => quote!(#var.as_string()),
+                _ => var,
+            },
+            Type::Str(_) => quote!(#var.as_str()),
+            _ => var,
         }
     });
     let mut outparam = None;

From 159a9f535cca686ae795780a5daefe038eea5221 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:13:00 +0000
Subject: [PATCH 6/2232] Release 0.1.1


---

diff --git a/Cargo.toml b/Cargo.toml
index d111367..4018cb2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.1.0"
+version = "0.1.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge01"
@@ -18,7 +18,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
-cxxbridge-macro = { version = "0.1", path = "macro" }
+cxxbridge-macro = { version = "=0.1.1", path = "macro" }
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 0cfe883..1a0b4ba 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.1.0"
+version = "0.1.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 2d14527..fc216ba 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.1.0"
+version = "0.1.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"

From 8861bee797c81aa501e6c30797e83dafcc19456e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:40:16 +0000
Subject: [PATCH 7/2232] Support opaque types that are not structs


---

diff --git a/gen/write.rs b/gen/write.rs
index eb11470..97fdc48 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -40,7 +40,8 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
     for api in apis {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) | Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
             _ => {}
         }
     }
@@ -167,6 +168,10 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "struct {};", ident);
 }
 
+fn write_struct_using(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "using {} = {};", ident, ident);
+}
+
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     let indirect_return = efn
         .ret

From 199d73509b5c89c602e4fc58687689d54ea76541 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:40:16 +0000
Subject: [PATCH 8/2232] Format with rustfmt 2019-10-07


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ac10b78..bcd02f1 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -23,7 +23,9 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
             if !has_rust_type {
-                hidden.extend(quote!(const fn __assert_sized<T>() {}));
+                hidden.extend(quote!(
+                    const fn __assert_sized<T>() {}
+                ));
                 has_rust_type = true;
             }
             let ident = &ety.ident;

From 270b8851327dc90846bd9f1f545e92c3a21fbb5c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:50:52 +0000
Subject: [PATCH 9/2232] Merge pull request #15 from dtolnay/opaque


Support opaque types that are not structs
---

diff --git a/gen/write.rs b/gen/write.rs
index eb11470..97fdc48 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -40,7 +40,8 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
     for api in apis {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) | Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
             _ => {}
         }
     }
@@ -167,6 +168,10 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "struct {};", ident);
 }
 
+fn write_struct_using(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "using {} = {};", ident, ident);
+}
+
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     let indirect_return = efn
         .ret

From 61b6771334bf0dda141d8acb130d3d2d7ebf67d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 21 2020 02:53:20 +0000
Subject: [PATCH 10/2232] Release 0.1.2


---

diff --git a/Cargo.toml b/Cargo.toml
index 4018cb2..118c7ad 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.1.1"
+version = "0.1.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge01"
@@ -18,7 +18,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
-cxxbridge-macro = { version = "=0.1.1", path = "macro" }
+cxxbridge-macro = { version = "=0.1.2", path = "macro" }
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 1a0b4ba..f39609a 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.1.1"
+version = "0.1.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index fc216ba..8159ec7 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.1.1"
+version = "0.1.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"

From af60e239b054a653cf5c1fb27cc4f7451f18e0d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 24 2020 23:23:20 +0000
Subject: [PATCH 11/2232] Use platform's default C++ standard library


---

diff --git a/Cargo.toml b/Cargo.toml
index 118c7ad..b120173 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
 cxxbridge-macro = { version = "=0.1.2", path = "macro" }
+link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
diff --git a/build.rs b/build.rs
index f16f265..ea562c2 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,6 @@ fn main() {
         .file("src/cxxbridge.cc")
         .flag("-std=c++11")
         .compile("cxxbridge01");
-    println!("cargo:rustc-flags=-l dylib=stdc++");
     println!("cargo:rerun-if-changed=src/cxxbridge.cc");
     println!("cargo:rerun-if-changed=include/cxxbridge.h");
 }
diff --git a/src/lib.rs b/src/lib.rs
index 5331084..509cfa6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -342,6 +342,8 @@
     clippy::useless_let_if_seq
 )]
 
+extern crate link_cplusplus;
+
 mod cxx_string;
 mod error;
 mod gen;

From 05e9cc4d9b9c86a367e3d46c65c7d2135cbba650 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 25 2020 00:07:20 +0000
Subject: [PATCH 12/2232] Merge pull request #21 from dtolnay/link


Use platform's default C++ standard library
---

diff --git a/Cargo.toml b/Cargo.toml
index 118c7ad..b120173 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
 cxxbridge-macro = { version = "=0.1.2", path = "macro" }
+link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
diff --git a/build.rs b/build.rs
index f16f265..ea562c2 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,6 @@ fn main() {
         .file("src/cxxbridge.cc")
         .flag("-std=c++11")
         .compile("cxxbridge01");
-    println!("cargo:rustc-flags=-l dylib=stdc++");
     println!("cargo:rerun-if-changed=src/cxxbridge.cc");
     println!("cargo:rerun-if-changed=include/cxxbridge.h");
 }
diff --git a/src/lib.rs b/src/lib.rs
index 5331084..509cfa6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -342,6 +342,8 @@
     clippy::useless_let_if_seq
 )]
 
+extern crate link_cplusplus;
+
 mod cxx_string;
 mod error;
 mod gen;

From 4a44122b0f49daefcca68572d5707b9d0f7f02c4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 26 2020 00:26:54 +0000
Subject: [PATCH 13/2232] Resolve Wreturn-type-c-linkage warnings


---

diff --git a/gen/write.rs b/gen/write.rs
index 97fdc48..ea6a812 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -211,8 +211,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "new (return$) ");
         write_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
-    } else if efn.ret.is_some() {
+    } else if let Some(ret) = &efn.ret {
         write!(out, "return ");
+        if let Type::Ref(_) = ret {
+            write!(out, "&");
+        }
     }
     write!(out, "{}$(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
@@ -298,8 +301,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             write_type(out, efn.ret.as_ref().unwrap());
             writeln!(out, ")];");
             write!(out, "  ");
-        } else if efn.ret.is_some() {
+        } else if let Some(ret) = &efn.ret {
             write!(out, "return ");
+            if let Type::Ref(_) = ret {
+                write!(out, "*");
+            }
         }
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
@@ -352,6 +358,13 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
+        Some(Type::Ref(ty)) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
         Some(Type::Str(_)) => write!(out, "cxxbridge::RustStr::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),

From 152119246e40e8b6366c1378e4de93d758ae203f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 26 2020 00:32:33 +0000
Subject: [PATCH 14/2232] Merge pull request #23 from dtolnay/retref


Resolve Wreturn-type-c-linkage warnings
---

diff --git a/gen/write.rs b/gen/write.rs
index 97fdc48..ea6a812 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -211,8 +211,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "new (return$) ");
         write_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
-    } else if efn.ret.is_some() {
+    } else if let Some(ret) = &efn.ret {
         write!(out, "return ");
+        if let Type::Ref(_) = ret {
+            write!(out, "&");
+        }
     }
     write!(out, "{}$(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
@@ -298,8 +301,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             write_type(out, efn.ret.as_ref().unwrap());
             writeln!(out, ")];");
             write!(out, "  ");
-        } else if efn.ret.is_some() {
+        } else if let Some(ret) = &efn.ret {
             write!(out, "return ");
+            if let Type::Ref(_) = ret {
+                write!(out, "*");
+            }
         }
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
@@ -352,6 +358,13 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
+        Some(Type::Ref(ty)) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
         Some(Type::Str(_)) => write!(out, "cxxbridge::RustStr::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),

From 366ef8b486c0c433355fc5d5da240e1066f65096 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 26 2020 22:15:59 +0000
Subject: [PATCH 15/2232] Print error cause chain on failures in build.rs


---

diff --git a/src/lib.rs b/src/lib.rs
index 509cfa6..3267b3f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -370,6 +370,7 @@ pub mod private {
 }
 
 use crate::error::Result;
+use anyhow::anyhow;
 use std::fs;
 use std::io::{self, Write};
 use std::path::Path;
@@ -442,7 +443,7 @@ impl Build {
         match try_generate_bridge(rust_source_file.as_ref()) {
             Ok(build) => build,
             Err(err) => {
-                let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", err);
+                let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
                 process::exit(1);
             }
         }

From 015c5e85a543c0623ca76aad547ff48d6ba5cefc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2020 00:31:48 +0000
Subject: [PATCH 16/2232] Remove strip_prefix failure mode from relative paths


---

diff --git a/src/error.rs b/src/error.rs
index a05f7c8..0c19f98 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,16 +1,14 @@
 use std::io;
-use std::path::StripPrefixError;
 use thiserror::Error;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Error, Debug)]
-#[error(transparent)]
 pub(super) enum Error {
     #[error("missing OUT_DIR environment variable")]
     MissingOutDir,
     #[error("failed to locate target dir")]
     TargetDir,
+    #[error(transparent)]
     Io(#[from] io::Error),
-    StripPrefix(#[from] StripPrefixError),
 }
diff --git a/src/paths.rs b/src/paths.rs
index 866d377..8e5d717 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -44,10 +44,17 @@ fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
 
 fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
     let target_dir = target_dir()?;
-    let parent_of_target_dir = target_dir.parent().unwrap();
+    let mut outer = target_dir.parent().unwrap();
     let original = original.canonicalize()?;
-    let suffix = original.strip_prefix(parent_of_target_dir)?;
-    Ok(suffix.to_owned())
+    loop {
+        if let Ok(suffix) = original.strip_prefix(outer) {
+            return Ok(suffix.to_owned());
+        }
+        match outer.parent() {
+            Some(parent) => outer = parent,
+            None => return Ok(original.components().skip(1).collect()),
+        }
+    }
 }
 
 pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {

From 0a2d117fbab513788f42fc110c4a624fe7357c02 Mon Sep 17 00:00:00 2001
From: RS <sayrer@gmail.com>
Date: Jan 28 2020 05:47:37 +0000
Subject: [PATCH 17/2232] Emit cxxbridge (#27)


* Working cxxbridge output.

* Add a way to emit cxxbridge.h

---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index daa5ac0..96d21a5 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -1,7 +1,8 @@
 mod gen;
 mod syntax;
 
-use std::io::{self, Write};
+use gen::include::get_full_cxxbridge;
+use std::io::{self, Error, ErrorKind, Write};
 use std::path::PathBuf;
 use structopt::StructOpt;
 
@@ -10,20 +11,28 @@ use structopt::StructOpt;
 struct Opt {
     /// Input Rust source file containing #[cxx::bridge]
     #[structopt(parse(from_os_str))]
-    input: PathBuf,
+    input: Option<PathBuf>,
 
-    /// Emit header with declarations only
+    /// Emit header with declarations only. If no input is specified, emit cxxbridge.h
     #[structopt(long)]
     header: bool,
 }
 
-fn main() {
+fn main() -> Result<(), Error> {
     let opt = Opt::from_args();
-    let gen = if opt.header {
-        gen::do_generate_header
+
+    if let Some(input) = opt.input {
+        let gen = if opt.header {
+            gen::do_generate_header
+        } else {
+            gen::do_generate_bridge
+        };
+        let bridge = gen(&input);
+        io::stdout().lock().write_all(bridge.as_ref())
+    } else if opt.header {
+        io::stdout().lock().write_all(get_full_cxxbridge().as_ref())
     } else {
-        gen::do_generate_bridge
-    };
-    let bridge = gen(&opt.input);
-    let _ = io::stdout().lock().write_all(bridge.as_ref());
+        let mut clap = Opt::clap().after_help("");
+        clap.print_help().or(Err(Error::new(ErrorKind::Other, "Failed to write help")))
+    }
 }
diff --git a/gen/include.rs b/gen/include.rs
index 00e67f0..f38ae73 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -11,3 +11,7 @@ pub fn get(guard: &str) -> &'static str {
         panic!("not found in cxxbridge.h header: {}", guard)
     }
 }
+
+pub fn get_full_cxxbridge() -> &'static str {
+    return HEADER
+}

From 7eb9c6b2a09932d0a6285382e1709ce70faa860a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 28 2020 06:35:59 +0000
Subject: [PATCH 18/2232] Touch up cxxbridge.h emit PR


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 96d21a5..8550261 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -1,9 +1,10 @@
 mod gen;
 mod syntax;
 
-use gen::include::get_full_cxxbridge;
-use std::io::{self, Error, ErrorKind, Write};
+use gen::include;
+use std::io::{self, Write};
 use std::path::PathBuf;
+use std::process;
 use structopt::StructOpt;
 
 #[derive(StructOpt, Debug)]
@@ -13,12 +14,12 @@ struct Opt {
     #[structopt(parse(from_os_str))]
     input: Option<PathBuf>,
 
-    /// Emit header with declarations only. If no input is specified, emit cxxbridge.h
+    /// Emit header with declarations only
     #[structopt(long)]
     header: bool,
 }
 
-fn main() -> Result<(), Error> {
+fn main() {
     let opt = Opt::from_args();
 
     if let Some(input) = opt.input {
@@ -28,11 +29,12 @@ fn main() -> Result<(), Error> {
             gen::do_generate_bridge
         };
         let bridge = gen(&input);
-        io::stdout().lock().write_all(bridge.as_ref())
+        let _ = io::stdout().lock().write_all(bridge.as_ref());
     } else if opt.header {
-        io::stdout().lock().write_all(get_full_cxxbridge().as_ref())
+        let header = include::HEADER;
+        let _ = io::stdout().lock().write_all(header.as_ref());
     } else {
-        let mut clap = Opt::clap().after_help("");
-        clap.print_help().or(Err(Error::new(ErrorKind::Other, "Failed to write help")))
+        let _ = Opt::clap().after_help("").print_help();
+        process::exit(1);
     }
 }
diff --git a/gen/include.rs b/gen/include.rs
index f38ae73..d4ff758 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,4 +1,4 @@
-static HEADER: &str = include_str!("include/cxxbridge.h");
+pub static HEADER: &str = include_str!("include/cxxbridge.h");
 
 pub fn get(guard: &str) -> &'static str {
     let ifndef = format!("#ifndef {}\n", guard);
@@ -11,7 +11,3 @@ pub fn get(guard: &str) -> &'static str {
         panic!("not found in cxxbridge.h header: {}", guard)
     }
 }
-
-pub fn get_full_cxxbridge() -> &'static str {
-    return HEADER
-}

From 4aea27578878bdd8416a2c95defcef57d9d65302 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 28 2020 06:55:55 +0000
Subject: [PATCH 19/2232] Use clap's required_unless to enforce input file path


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 8550261..c0b4cc4 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -4,14 +4,13 @@ mod syntax;
 use gen::include;
 use std::io::{self, Write};
 use std::path::PathBuf;
-use std::process;
 use structopt::StructOpt;
 
 #[derive(StructOpt, Debug)]
 #[structopt(name = "cxxbridge", author)]
 struct Opt {
     /// Input Rust source file containing #[cxx::bridge]
-    #[structopt(parse(from_os_str))]
+    #[structopt(parse(from_os_str), required_unless = "header")]
     input: Option<PathBuf>,
 
     /// Emit header with declarations only
@@ -19,22 +18,17 @@ struct Opt {
     header: bool,
 }
 
+fn write(content: impl AsRef<[u8]>) {
+    let _ = io::stdout().lock().write_all(content.as_ref());
+}
+
 fn main() {
     let opt = Opt::from_args();
 
-    if let Some(input) = opt.input {
-        let gen = if opt.header {
-            gen::do_generate_header
-        } else {
-            gen::do_generate_bridge
-        };
-        let bridge = gen(&input);
-        let _ = io::stdout().lock().write_all(bridge.as_ref());
-    } else if opt.header {
-        let header = include::HEADER;
-        let _ = io::stdout().lock().write_all(header.as_ref());
-    } else {
-        let _ = Opt::clap().after_help("").print_help();
-        process::exit(1);
+    match (opt.input, opt.header) {
+        (Some(input), true) => write(gen::do_generate_header(&input)),
+        (Some(input), false) => write(gen::do_generate_bridge(&input)),
+        (None, true) => write(include::HEADER),
+        (None, false) => unreachable!(), // enforced by required_unless
     }
 }

From fa66e2afa6f43034a564ded0f4ee8a6555f7160d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 28 2020 07:24:40 +0000
Subject: [PATCH 20/2232] Customize usage message of cmd


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index c0b4cc4..26b6ef6 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -7,7 +7,17 @@ use std::path::PathBuf;
 use structopt::StructOpt;
 
 #[derive(StructOpt, Debug)]
-#[structopt(name = "cxxbridge", author)]
+#[structopt(
+    name = "cxxbridge",
+    author,
+    about = "https://github.com/dtolnay/cxx",
+    usage = "\
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit cxxbridge.h header to stdout",
+    help_message = "Print help information",
+    version_message = "Print version information"
+)]
 struct Opt {
     /// Input Rust source file containing #[cxx::bridge]
     #[structopt(parse(from_os_str), required_unless = "header")]

From 0c88e03a4ae2eee4b6c2585bab6f7986b925f02d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 28 2020 08:43:51 +0000
Subject: [PATCH 21/2232] Remove any existing link before writing symlink


---

diff --git a/src/paths.rs b/src/paths.rs
index 8e5d717..16bf12a 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -31,9 +31,10 @@ pub(crate) fn symlink_header(path: &Path, original: &Path) {
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
     let suffix = relative_to_parent_of_target_dir(original)?;
-    let dst = target_dir()?.join("cxxbridge").join(suffix);
+    let ref dst = target_dir()?.join("cxxbridge").join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
+    let _ = fs::remove_file(dst);
     #[cfg(unix)]
     os::unix::fs::symlink(path, dst)?;
     #[cfg(windows)]

From c43627aee6c9caf021e6a931687aea631579f37b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 28 2020 08:50:25 +0000
Subject: [PATCH 22/2232] Always write cxxbridge.h into a predictable place from build script


---

diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 51dd81b..417edfb 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "../include/cxxbridge.h"
+#include "cxxbridge/cxxbridge.h"
 #include <memory>
 #include <string>
 
diff --git a/src/lib.rs b/src/lib.rs
index 3267b3f..6f40124 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -463,5 +463,10 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let mut build = paths::cc_build();
     build.file(&bridge_path);
 
+    let ref cxxbridge_h = paths::include_dir()?.join("cxxbridge/cxxbridge.h");
+    let _ = fs::create_dir_all(cxxbridge_h.parent().unwrap());
+    let _ = fs::remove_file(cxxbridge_h);
+    let _ = fs::write(cxxbridge_h, gen::include::HEADER);
+
     Ok(build)
 }
diff --git a/src/paths.rs b/src/paths.rs
index 16bf12a..f253939 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -15,11 +15,9 @@ pub(crate) fn cc_build() -> cc::Build {
 }
 
 fn try_cc_build() -> Result<cc::Build> {
-    let target_dir = target_dir()?;
-
     let mut build = cc::Build::new();
-    build.include(target_dir.join("cxxbridge"));
-    build.include(target_dir.parent().unwrap());
+    build.include(include_dir()?);
+    build.include(target_dir()?.parent().unwrap());
     Ok(build)
 }
 
@@ -31,7 +29,7 @@ pub(crate) fn symlink_header(path: &Path, original: &Path) {
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
     let suffix = relative_to_parent_of_target_dir(original)?;
-    let ref dst = target_dir()?.join("cxxbridge").join(suffix);
+    let ref dst = include_dir()?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
@@ -67,6 +65,11 @@ pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
     Ok(out_dir.join(rel).with_file_name(file_name))
 }
 
+pub(crate) fn include_dir() -> Result<PathBuf> {
+    let target_dir = target_dir()?;
+    Ok(target_dir.join("cxxbridge"))
+}
+
 fn target_dir() -> Result<PathBuf> {
     let mut dir = out_dir()?.canonicalize()?;
     loop {

From f4b2421805be92610fc4c5e964953e9e983453ee Mon Sep 17 00:00:00 2001
From: Robert Sayre <sayrer@gmail.com>
Date: Feb 03 2020 18:10:13 +0000
Subject: [PATCH 23/2232] Add macos and cargo test


---

diff --git a/.travis.yml b/.travis.yml
index af5dce8..1933ec6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,6 @@
 language: rust
 rust: nightly
-script: cargo run --manifest-path demo-rs/Cargo.toml
+os:
+  - linux
+  - macos
+script: cargo run --manifest-path demo-rs/Cargo.toml && cargo test

From e45bd7c842c7351eec27c791eef7316f6580ba95 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 03 2020 18:35:41 +0000
Subject: [PATCH 24/2232] Merge pull request #31 from sayrer/travis_macos


Add macos and cargo test
---

diff --git a/.travis.yml b/.travis.yml
index af5dce8..1933ec6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,6 @@
 language: rust
 rust: nightly
-script: cargo run --manifest-path demo-rs/Cargo.toml
+os:
+  - linux
+  - macos
+script: cargo run --manifest-path demo-rs/Cargo.toml && cargo test

From f184feb74776e4ef39ffd4b75ade51d27a678090 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 03 2020 18:37:36 +0000
Subject: [PATCH 25/2232] Space out the Travis config


---

diff --git a/.travis.yml b/.travis.yml
index 1933ec6..f054344 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,11 @@
 language: rust
+
 rust: nightly
+
 os:
   - linux
   - macos
-script: cargo run --manifest-path demo-rs/Cargo.toml && cargo test
+
+script:
+  - cargo run --manifest-path demo-rs/Cargo.toml
+  - cargo test

From bd3a6b27fbe857c1861ab645c9c0386f6173e421 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 08 2020 00:58:20 +0000
Subject: [PATCH 26/2232] Update ui tests to nightly-2020-02-08


---

diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 419b83d..1146b80 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -10,3 +10,4 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required because it appears within the type `TypeR`
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 5bde59dd2de886b7bfc5989acb7a2227bd21bf4a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 18 2020 09:29:40 +0000
Subject: [PATCH 27/2232] Add buck targets


---

diff --git a/.buckconfig b/.buckconfig
new file mode 100644
index 0000000..33c15ec
--- /dev/null
+++ b/.buckconfig
@@ -0,0 +1,12 @@
+[project]
+  # We use some symlinks in the source tree, but they get eliminated by `cargo
+  # publish` and `cargo vendor` so this allow_symlinks setting should not be
+  # required downstream.
+  allow_symlinks = allow
+
+[cxx]
+  cxxflags = -std=c++11
+
+[rust]
+  default_edition = 2018
+  rustc_flags = -Crelocation-model=dynamic-no-pic --cap-lints=allow
diff --git a/.gitignore b/.gitignore
index a874449..b403b1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+/.buckd
+/buck-out
 /Cargo.lock
 /expand.cc
 /expand.rs
diff --git a/.travis.yml b/.travis.yml
index f054344..74f438d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,3 +9,18 @@ os:
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
   - cargo test
+
+matrix:
+  include:
+    - name: Buck
+      before_install:
+        - sudo apt-get install -y openjdk-8-jdk
+        - export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+        - wget -O buck.deb https://github.com/facebook/buck/releases/download/v2019.10.17.01/buck.2019.10.17.01_all.deb
+        - sudo dpkg -i buck.deb
+      before_script:
+        - cp third-party/Cargo.lock .
+        - cargo vendor --versioned-dirs third-party/vendor
+      script:
+        - buck build :cxx#check --verbose=0
+        - buck run demo-rs --verbose=0
diff --git a/BUCK b/BUCK
new file mode 100644
index 0000000..2d12753
--- /dev/null
+++ b/BUCK
@@ -0,0 +1,60 @@
+rust_library(
+    name = "cxx",
+    srcs = glob(["src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":core",
+        ":macro",
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan",
+        "//third-party:codespan-reporting",
+        "//third-party:link-cplusplus",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+rust_binary(
+    name = "codegen",
+    srcs = glob(["cmd/src/**"]),
+    visibility = ["PUBLIC"],
+    env = {
+        "CARGO_PKG_AUTHORS": "David Tolnay <dtolnay@gmail.com>",
+    },
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:codespan",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:structopt",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+cxx_library(
+    name = "core",
+    srcs = ["src/cxxbridge.cc"],
+    visibility = ["PUBLIC"],
+    header_namespace = "cxxbridge",
+    exported_headers = {
+        "cxxbridge.h": "include/cxxbridge.h",
+    },
+    exported_linker_flags = ["-lstdc++"],
+)
+
+rust_library(
+    name = "macro",
+    srcs = glob(["macro/src/**"]),
+    proc_macro = True,
+    crate = "cxxbridge_macro",
+    deps = [
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
new file mode 100644
index 0000000..595a18b
--- /dev/null
+++ b/demo-cxx/BUCK
@@ -0,0 +1,16 @@
+cxx_library(
+    name = "demo-cxx",
+    srcs = ["demo.cc"],
+    visibility = ["PUBLIC"],
+    deps = [
+        ":include",
+        "//demo-rs:include",
+    ],
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = ["demo.h"],
+    visibility = ["PUBLIC"],
+    deps = ["//:core"],
+)
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
new file mode 100644
index 0000000..a0f6fb0
--- /dev/null
+++ b/demo-rs/BUCK
@@ -0,0 +1,42 @@
+rust_binary(
+    name = "demo-rs",
+    srcs = glob(["src/**"]),
+    deps = [
+        ":gen",
+        "//:cxx",
+        "//demo-cxx:demo-cxx",
+    ],
+)
+
+cxx_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":include",
+        "//demo-cxx:include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+    out = "gen-demo.h",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+    out = "gen-demo.cc",
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = {
+        "src/main.rs": ":gen-header",
+    },
+    visibility = ["PUBLIC"],
+)
diff --git a/third-party/.gitignore b/third-party/.gitignore
new file mode 100644
index 0000000..61ead86
--- /dev/null
+++ b/third-party/.gitignore
@@ -0,0 +1 @@
+/vendor
diff --git a/third-party/BUCK b/third-party/BUCK
new file mode 100644
index 0000000..1c1bf3d
--- /dev/null
+++ b/third-party/BUCK
@@ -0,0 +1,243 @@
+# To be generated by Facebook's `reindeer` tool once that is open source.
+
+rust_library(
+    name = "anyhow",
+    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    visibility = ["PUBLIC"],
+    features = ["std"],
+)
+
+rust_library(
+    name = "bitflags",
+    srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
+)
+
+rust_library(
+    name = "cc",
+    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    visibility = ["PUBLIC"],
+)
+
+rust_library(
+    name = "clap",
+    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    edition = "2015",
+    deps = [
+        ":bitflags",
+        ":textwrap",
+        ":unicode-width",
+    ],
+)
+
+rust_library(
+    name = "codespan",
+    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [":unicode-segmentation"],
+)
+
+rust_library(
+    name = "codespan-reporting",
+    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":codespan",
+        ":termcolor",
+        ":unicode-width",
+    ],
+)
+
+rust_library(
+    name = "heck",
+    srcs = glob(["vendor/heck-0.3.1/src/**"]),
+    edition = "2015",
+    deps = [":unicode-segmentation"],
+)
+
+rust_library(
+    name = "lazy_static",
+    srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+)
+
+rust_library(
+    name = "link-cplusplus",
+    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    visibility = ["PUBLIC"],
+)
+
+rust_library(
+    name = "proc-macro-error",
+    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    rustc_flags = ["--cfg=use_fallback"],
+    deps = [
+        ":proc-macro-error-attr",
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "proc-macro-error-attr",
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":rustversion",
+        ":syn",
+        ":syn-mid",
+    ],
+)
+
+rust_library(
+    name = "proc-macro2",
+    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    visibility = ["PUBLIC"],
+    features = [
+        "proc-macro",
+        "span-locations",
+    ],
+    rustc_flags = [
+        "--cfg=span_locations",
+        "--cfg=use_proc_macro",
+        "--cfg=wrap_proc_macro",
+    ],
+    deps = [":unicode-xid"],
+)
+
+rust_library(
+    name = "quote",
+    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    visibility = ["PUBLIC"],
+    features = ["proc-macro"],
+    deps = [":proc-macro2"],
+)
+
+rust_library(
+    name = "rustversion",
+    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
+    mapped_srcs = {
+        ":rustversion-buildscript-run": "vendor/rustversion-1.0.2/src/generated",
+    },
+    proc_macro = True,
+    env = {
+        "OUT_DIR": "generated",
+    },
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_binary(
+    name = "rustversion-buildscript",
+    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
+    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
+)
+
+genrule(
+    name = "rustversion-buildscript-run",
+    cmd = "OUT_DIR=${OUT} $(exe :rustversion-buildscript)",
+    type = "build.rs",
+    out = ".",
+)
+
+rust_library(
+    name = "structopt",
+    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":clap",
+        ":lazy_static",
+        ":structopt-derive",
+    ],
+)
+
+rust_library(
+    name = "structopt-derive",
+    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":heck",
+        ":proc-macro-error",
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "syn",
+    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    visibility = ["PUBLIC"],
+    features = [
+        "clone-impls",
+        "derive",
+        "full",
+        "parsing",
+        "printing",
+        "proc-macro",
+    ],
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":unicode-xid",
+    ],
+)
+
+rust_library(
+    name = "syn-mid",
+    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "termcolor",
+    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+)
+
+rust_library(
+    name = "textwrap",
+    srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
+    deps = [":unicode-width"],
+)
+
+rust_library(
+    name = "thiserror",
+    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [":thiserror-impl"],
+)
+
+rust_library(
+    name = "thiserror-impl",
+    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "unicode-segmentation",
+    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
+    edition = "2015",
+)
+
+rust_library(
+    name = "unicode-width",
+    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+)
+
+rust_library(
+    name = "unicode-xid",
+    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+)
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
new file mode 100644
index 0000000..fda2025
--- /dev/null
+++ b/third-party/Cargo.lock
@@ -0,0 +1,434 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+
+[[package]]
+name = "clap"
+version = "2.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "codespan"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "codespan-reporting"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "657b2c99e1f17bc3e5153808d9f704c8ba6171c3fe45e69fde26e2876156938b"
+dependencies = [
+ "codespan",
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "cxx"
+version = "0.1.2"
+dependencies = [
+ "anyhow",
+ "cc",
+ "codespan",
+ "codespan-reporting",
+ "cxxbridge-macro",
+ "link-cplusplus",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+ "thiserror",
+ "trybuild",
+]
+
+[[package]]
+name = "cxxbridge-cmd"
+version = "0.1.2"
+dependencies = [
+ "anyhow",
+ "codespan",
+ "codespan-reporting",
+ "proc-macro2",
+ "quote",
+ "structopt",
+ "syn",
+ "thiserror",
+]
+
+[[package]]
+name = "cxxbridge-demo"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+]
+
+[[package]]
+name = "cxxbridge-macro"
+version = "0.1.2"
+dependencies = [
+ "cxx",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628cd9d7b5c99cb930617438a3d7896f5eb734647bc2838ded9ca50689507295"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052b3c9af39c7e5e94245f820530487d19eb285faedcb40e0c3275132293f242"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d175bef481c7902e63e3165627123fff3502f06ac043d3ef42d08c1246da9253"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+ "syn-mid",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
+
+[[package]]
+name = "serde"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "syn-mid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "trybuild"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f5b3f750c701725331ac78e389b5d143b7d25f6b6ffffd0d419759a9063ac5f"
+dependencies = [
+ "glob",
+ "lazy_static",
+ "serde",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+
+[[package]]
+name = "vec_map"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

From ab9fa6d08c7a458a243329c40601c46f256f7a57 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 18 2020 09:44:45 +0000
Subject: [PATCH 28/2232] Merge pull request #34 from dtolnay/buck


Add buck targets
---

diff --git a/.buckconfig b/.buckconfig
new file mode 100644
index 0000000..33c15ec
--- /dev/null
+++ b/.buckconfig
@@ -0,0 +1,12 @@
+[project]
+  # We use some symlinks in the source tree, but they get eliminated by `cargo
+  # publish` and `cargo vendor` so this allow_symlinks setting should not be
+  # required downstream.
+  allow_symlinks = allow
+
+[cxx]
+  cxxflags = -std=c++11
+
+[rust]
+  default_edition = 2018
+  rustc_flags = -Crelocation-model=dynamic-no-pic --cap-lints=allow
diff --git a/.gitignore b/.gitignore
index a874449..b403b1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+/.buckd
+/buck-out
 /Cargo.lock
 /expand.cc
 /expand.rs
diff --git a/.travis.yml b/.travis.yml
index f054344..74f438d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,3 +9,18 @@ os:
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
   - cargo test
+
+matrix:
+  include:
+    - name: Buck
+      before_install:
+        - sudo apt-get install -y openjdk-8-jdk
+        - export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+        - wget -O buck.deb https://github.com/facebook/buck/releases/download/v2019.10.17.01/buck.2019.10.17.01_all.deb
+        - sudo dpkg -i buck.deb
+      before_script:
+        - cp third-party/Cargo.lock .
+        - cargo vendor --versioned-dirs third-party/vendor
+      script:
+        - buck build :cxx#check --verbose=0
+        - buck run demo-rs --verbose=0
diff --git a/BUCK b/BUCK
new file mode 100644
index 0000000..2d12753
--- /dev/null
+++ b/BUCK
@@ -0,0 +1,60 @@
+rust_library(
+    name = "cxx",
+    srcs = glob(["src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":core",
+        ":macro",
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan",
+        "//third-party:codespan-reporting",
+        "//third-party:link-cplusplus",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+rust_binary(
+    name = "codegen",
+    srcs = glob(["cmd/src/**"]),
+    visibility = ["PUBLIC"],
+    env = {
+        "CARGO_PKG_AUTHORS": "David Tolnay <dtolnay@gmail.com>",
+    },
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:codespan",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:structopt",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+cxx_library(
+    name = "core",
+    srcs = ["src/cxxbridge.cc"],
+    visibility = ["PUBLIC"],
+    header_namespace = "cxxbridge",
+    exported_headers = {
+        "cxxbridge.h": "include/cxxbridge.h",
+    },
+    exported_linker_flags = ["-lstdc++"],
+)
+
+rust_library(
+    name = "macro",
+    srcs = glob(["macro/src/**"]),
+    proc_macro = True,
+    crate = "cxxbridge_macro",
+    deps = [
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
new file mode 100644
index 0000000..595a18b
--- /dev/null
+++ b/demo-cxx/BUCK
@@ -0,0 +1,16 @@
+cxx_library(
+    name = "demo-cxx",
+    srcs = ["demo.cc"],
+    visibility = ["PUBLIC"],
+    deps = [
+        ":include",
+        "//demo-rs:include",
+    ],
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = ["demo.h"],
+    visibility = ["PUBLIC"],
+    deps = ["//:core"],
+)
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
new file mode 100644
index 0000000..a0f6fb0
--- /dev/null
+++ b/demo-rs/BUCK
@@ -0,0 +1,42 @@
+rust_binary(
+    name = "demo-rs",
+    srcs = glob(["src/**"]),
+    deps = [
+        ":gen",
+        "//:cxx",
+        "//demo-cxx:demo-cxx",
+    ],
+)
+
+cxx_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":include",
+        "//demo-cxx:include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+    out = "gen-demo.h",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+    out = "gen-demo.cc",
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = {
+        "src/main.rs": ":gen-header",
+    },
+    visibility = ["PUBLIC"],
+)
diff --git a/third-party/.gitignore b/third-party/.gitignore
new file mode 100644
index 0000000..61ead86
--- /dev/null
+++ b/third-party/.gitignore
@@ -0,0 +1 @@
+/vendor
diff --git a/third-party/BUCK b/third-party/BUCK
new file mode 100644
index 0000000..1c1bf3d
--- /dev/null
+++ b/third-party/BUCK
@@ -0,0 +1,243 @@
+# To be generated by Facebook's `reindeer` tool once that is open source.
+
+rust_library(
+    name = "anyhow",
+    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    visibility = ["PUBLIC"],
+    features = ["std"],
+)
+
+rust_library(
+    name = "bitflags",
+    srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
+)
+
+rust_library(
+    name = "cc",
+    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    visibility = ["PUBLIC"],
+)
+
+rust_library(
+    name = "clap",
+    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    edition = "2015",
+    deps = [
+        ":bitflags",
+        ":textwrap",
+        ":unicode-width",
+    ],
+)
+
+rust_library(
+    name = "codespan",
+    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [":unicode-segmentation"],
+)
+
+rust_library(
+    name = "codespan-reporting",
+    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":codespan",
+        ":termcolor",
+        ":unicode-width",
+    ],
+)
+
+rust_library(
+    name = "heck",
+    srcs = glob(["vendor/heck-0.3.1/src/**"]),
+    edition = "2015",
+    deps = [":unicode-segmentation"],
+)
+
+rust_library(
+    name = "lazy_static",
+    srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+)
+
+rust_library(
+    name = "link-cplusplus",
+    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    visibility = ["PUBLIC"],
+)
+
+rust_library(
+    name = "proc-macro-error",
+    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    rustc_flags = ["--cfg=use_fallback"],
+    deps = [
+        ":proc-macro-error-attr",
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "proc-macro-error-attr",
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":rustversion",
+        ":syn",
+        ":syn-mid",
+    ],
+)
+
+rust_library(
+    name = "proc-macro2",
+    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    visibility = ["PUBLIC"],
+    features = [
+        "proc-macro",
+        "span-locations",
+    ],
+    rustc_flags = [
+        "--cfg=span_locations",
+        "--cfg=use_proc_macro",
+        "--cfg=wrap_proc_macro",
+    ],
+    deps = [":unicode-xid"],
+)
+
+rust_library(
+    name = "quote",
+    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    visibility = ["PUBLIC"],
+    features = ["proc-macro"],
+    deps = [":proc-macro2"],
+)
+
+rust_library(
+    name = "rustversion",
+    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
+    mapped_srcs = {
+        ":rustversion-buildscript-run": "vendor/rustversion-1.0.2/src/generated",
+    },
+    proc_macro = True,
+    env = {
+        "OUT_DIR": "generated",
+    },
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_binary(
+    name = "rustversion-buildscript",
+    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
+    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
+)
+
+genrule(
+    name = "rustversion-buildscript-run",
+    cmd = "OUT_DIR=${OUT} $(exe :rustversion-buildscript)",
+    type = "build.rs",
+    out = ".",
+)
+
+rust_library(
+    name = "structopt",
+    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        ":clap",
+        ":lazy_static",
+        ":structopt-derive",
+    ],
+)
+
+rust_library(
+    name = "structopt-derive",
+    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":heck",
+        ":proc-macro-error",
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "syn",
+    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    visibility = ["PUBLIC"],
+    features = [
+        "clone-impls",
+        "derive",
+        "full",
+        "parsing",
+        "printing",
+        "proc-macro",
+    ],
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":unicode-xid",
+    ],
+)
+
+rust_library(
+    name = "syn-mid",
+    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "termcolor",
+    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+)
+
+rust_library(
+    name = "textwrap",
+    srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
+    deps = [":unicode-width"],
+)
+
+rust_library(
+    name = "thiserror",
+    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [":thiserror-impl"],
+)
+
+rust_library(
+    name = "thiserror-impl",
+    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    proc_macro = True,
+    deps = [
+        ":proc-macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "unicode-segmentation",
+    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
+    edition = "2015",
+)
+
+rust_library(
+    name = "unicode-width",
+    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+)
+
+rust_library(
+    name = "unicode-xid",
+    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+)
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
new file mode 100644
index 0000000..fda2025
--- /dev/null
+++ b/third-party/Cargo.lock
@@ -0,0 +1,434 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+[[package]]
+name = "ansi_term"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+
+[[package]]
+name = "cc"
+version = "1.0.50"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+
+[[package]]
+name = "clap"
+version = "2.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "codespan"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "codespan-reporting"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "657b2c99e1f17bc3e5153808d9f704c8ba6171c3fe45e69fde26e2876156938b"
+dependencies = [
+ "codespan",
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
+name = "cxx"
+version = "0.1.2"
+dependencies = [
+ "anyhow",
+ "cc",
+ "codespan",
+ "codespan-reporting",
+ "cxxbridge-macro",
+ "link-cplusplus",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+ "thiserror",
+ "trybuild",
+]
+
+[[package]]
+name = "cxxbridge-cmd"
+version = "0.1.2"
+dependencies = [
+ "anyhow",
+ "codespan",
+ "codespan-reporting",
+ "proc-macro2",
+ "quote",
+ "structopt",
+ "syn",
+ "thiserror",
+]
+
+[[package]]
+name = "cxxbridge-demo"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+]
+
+[[package]]
+name = "cxxbridge-macro"
+version = "0.1.2"
+dependencies = [
+ "cxx",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "628cd9d7b5c99cb930617438a3d7896f5eb734647bc2838ded9ca50689507295"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052b3c9af39c7e5e94245f820530487d19eb285faedcb40e0c3275132293f242"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d175bef481c7902e63e3165627123fff3502f06ac043d3ef42d08c1246da9253"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+ "syn-mid",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
+
+[[package]]
+name = "serde"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "syn-mid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "termcolor"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "trybuild"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f5b3f750c701725331ac78e389b5d143b7d25f6b6ffffd0d419759a9063ac5f"
+dependencies = [
+ "glob",
+ "lazy_static",
+ "serde",
+ "serde_json",
+ "termcolor",
+ "toml",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+
+[[package]]
+name = "vec_map"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+
+[[package]]
+name = "winapi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

From c9f2798772cdb7252b18743a7cb82092fbf8310f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 18 2020 23:31:25 +0000
Subject: [PATCH 29/2232] Set buckversion=last


Buck in some environments requires this file for multiplexing across
different versions.

---

diff --git a/.buckversion b/.buckversion
new file mode 100644
index 0000000..b25fa3f
--- /dev/null
+++ b/.buckversion
@@ -0,0 +1 @@
+last

From 461712be9f5473439911602c5b887ab013f8a378 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 19 2020 08:22:26 +0000
Subject: [PATCH 30/2232] Add CI build on beta toolchain


---

diff --git a/.travis.yml b/.travis.yml
index 74f438d..273a6c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,8 @@
 language: rust
 
-rust: nightly
+rust:
+  - nightly
+  - beta
 
 os:
   - linux
@@ -13,6 +15,7 @@ script:
 matrix:
   include:
     - name: Buck
+      rust: nightly
       before_install:
         - sudo apt-get install -y openjdk-8-jdk
         - export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

From e10910f3c77519bc78db3ebf2105d9f2f983e92f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 19 2020 08:28:54 +0000
Subject: [PATCH 31/2232] Reduce to just one mac builder


---

diff --git a/.travis.yml b/.travis.yml
index 273a6c4..59b29a3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,16 +4,14 @@ rust:
   - nightly
   - beta
 
-os:
-  - linux
-  - macos
-
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
   - cargo test
 
 matrix:
   include:
+    - os: macos
+      rust: nightly
     - name: Buck
       rust: nightly
       before_install:

From b5bc0b4c9a9497dd322ac0e456d8363193af5584 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 22 2020 23:36:13 +0000
Subject: [PATCH 32/2232] Ensure third-party lockfile is adequate for vendor


---

diff --git a/.travis.yml b/.travis.yml
index 59b29a3..6352e8d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ matrix:
         - sudo dpkg -i buck.deb
       before_script:
         - cp third-party/Cargo.lock .
-        - cargo vendor --versioned-dirs third-party/vendor
+        - cargo vendor --versioned-dirs --locked third-party/vendor
       script:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0

From c19936ce7473e48808d15e3db28f3b4361167f5a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 00:01:35 +0000
Subject: [PATCH 33/2232] Add bazel targets


---

diff --git a/.gitignore b/.gitignore
index b403b1d..e7499e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
 /.buckd
+/bazel-bin
+/bazel-cxx
+/bazel-out
+/bazel-testlogs
 /buck-out
 /Cargo.lock
 /expand.cc
diff --git a/.travis.yml b/.travis.yml
index 6352e8d..d1fc088 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,3 +25,14 @@ matrix:
       script:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0
+    - name: Bazel
+      rust: nightly
+      before_install:
+        - wget -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+        - chmod +x install.sh
+        - ./install.sh --user
+      before_script:
+        - cp third-party/Cargo.lock .
+        - cargo vendor --versioned-dirs --locked third-party/vendor
+      script:
+        - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..b48c930
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,63 @@
+load("//:build/rust.bzl", "rust_binary", "rust_library")
+
+rust_library(
+    name = "cxx",
+    srcs = glob(["src/**/*.rs"]),
+    data = ["src/gen/include/cxxbridge.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":core_lib",
+        ":cxxbridge_macro",
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan",
+        "//third-party:codespan_reporting",
+        "//third-party:link_cplusplus",
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+rust_binary(
+    name = "codegen",
+    srcs = glob(["cmd/src/**/*.rs"]),
+    data = ["cmd/src/gen/include/cxxbridge.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:codespan",
+        "//third-party:codespan_reporting",
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:structopt",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+cc_library(
+    name = "core",
+    hdrs = ["include/cxxbridge.h"],
+    include_prefix = "cxxbridge",
+    strip_include_prefix = "include",
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "core_lib",
+    srcs = ["src/cxxbridge.cc"],
+    hdrs = ["include/cxxbridge.h"],
+)
+
+rust_library(
+    name = "cxxbridge_macro",
+    srcs = glob(["macro/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..26866e8
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,32 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "io_bazel_rules_rust",
+    sha256 = "3d3faa85e49ebf4d26c40075549a17739d636360064b94a9d481b37ace0add82",
+    strip_prefix = "rules_rust-6e87304c834c30b9c9f585cad19f30e7045281d7",
+    # Master branch as of 2020-02-22
+    url = "https://github.com/bazelbuild/rules_rust/archive/6e87304c834c30b9c9f585cad19f30e7045281d7.tar.gz",
+)
+
+http_archive(
+    name = "bazel_skylib",
+    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+    ],
+)
+
+load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
+
+bazel_version(name = "bazel_version")
+
+load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
+
+rust_repository_set(
+    name = "rust_1_42_beta",
+    exec_triple = "x86_64-unknown-linux-gnu",
+    extra_target_triples = [],
+    iso_date = "2020-02-08",
+    version = "beta",
+)
diff --git a/build/rust.bzl b/build/rust.bzl
new file mode 100644
index 0000000..c2dade7
--- /dev/null
+++ b/build/rust.bzl
@@ -0,0 +1,19 @@
+load(
+    "@io_bazel_rules_rust//rust:rust.bzl",
+    _rust_binary = "rust_binary",
+    _rust_library = "rust_library",
+)
+
+def rust_binary(edition = "2018", **kwargs):
+    _rust_binary(edition = edition, **kwargs)
+
+def third_party_rust_binary(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_binary(rustc_flags = rustc_flags, **kwargs)
+
+def rust_library(edition = "2018", **kwargs):
+    _rust_library(edition = edition, **kwargs)
+
+def third_party_rust_library(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_library(rustc_flags = rustc_flags, **kwargs)
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
new file mode 100644
index 0000000..da97cfa
--- /dev/null
+++ b/demo-cxx/BUILD
@@ -0,0 +1,16 @@
+cc_library(
+    name = "demo-cxx",
+    srcs = ["demo.cc"],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":include",
+        "//demo-rs:include",
+    ],
+)
+
+cc_library(
+    name = "include",
+    hdrs = ["demo.h"],
+    visibility = ["//visibility:public"],
+    deps = ["//:core"],
+)
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
new file mode 100644
index 0000000..fb781b6
--- /dev/null
+++ b/demo-rs/BUILD
@@ -0,0 +1,43 @@
+load("//:build/rust.bzl", "rust_binary", "rust_library")
+
+rust_binary(
+    name = "demo_rs",
+    srcs = glob(["src/**"]),
+    deps = [
+        ":gen",
+        "//:cxx",
+        "//demo-cxx",
+    ],
+)
+
+cc_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":include",
+        "//demo-cxx:include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    outs = ["main.rs"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    outs = ["gen-demo.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "demo-rs/src",
+    visibility = ["//visibility:public"],
+)
diff --git a/third-party/BUILD b/third-party/BUILD
new file mode 100644
index 0000000..11b4257
--- /dev/null
+++ b/third-party/BUILD
@@ -0,0 +1,249 @@
+load(
+    "//:build/rust.bzl",
+    rust_binary = "third_party_rust_binary",
+    rust_library = "third_party_rust_library",
+)
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
+
+rust_library(
+    name = "anyhow",
+    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    crate_features = ["std"],
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "bitflags",
+    srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
+)
+
+rust_library(
+    name = "cc",
+    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "clap",
+    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    edition = "2015",
+    deps = [
+        ":bitflags",
+        ":textwrap",
+        ":unicode_width",
+    ],
+)
+
+rust_library(
+    name = "codespan",
+    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [":unicode_segmentation"],
+)
+
+rust_library(
+    name = "codespan_reporting",
+    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        ":codespan",
+        ":termcolor",
+        ":unicode_width",
+    ],
+)
+
+rust_library(
+    name = "heck",
+    srcs = glob(["vendor/heck-0.3.1/src/**"]),
+    edition = "2015",
+    deps = [":unicode_segmentation"],
+)
+
+rust_library(
+    name = "lazy_static",
+    srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+)
+
+rust_library(
+    name = "link_cplusplus",
+    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "proc_macro_error",
+    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    rustc_flags = ["--cfg=use_fallback"],
+    deps = [
+        ":proc_macro2",
+        ":proc_macro_error_attr",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "proc_macro_error_attr",
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":rustversion",
+        ":syn",
+        ":syn_mid",
+    ],
+)
+
+rust_library(
+    name = "proc_macro2",
+    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    crate_features = [
+        "proc-macro",
+        "span-locations",
+    ],
+    rustc_flags = [
+        "--cfg=span_locations",
+        "--cfg=use_proc_macro",
+        "--cfg=wrap_proc_macro",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [":unicode_xid"],
+)
+
+rust_library(
+    name = "quote",
+    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    crate_features = ["proc-macro"],
+    visibility = ["//visibility:public"],
+    deps = [":proc_macro2"],
+)
+
+rust_library(
+    name = "rustversion",
+    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
+    crate_type = "proc-macro",
+    out_dir_tar = ":rustversion_buildscript_outdir",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_binary(
+    name = "rustversion_buildscript",
+    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
+    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
+)
+
+pkg_tar(
+    name = "rustversion_buildscript_outdir",
+    srcs = [":rustversion_buildscript_run"],
+    extension = "tar.gz",
+)
+
+genrule(
+    name = "rustversion_buildscript_run",
+    outs = ["version.rs"],
+    cmd = "OUT_DIR=$(@D) $(location :rustversion_buildscript)",
+    tools = [":rustversion_buildscript"],
+)
+
+rust_library(
+    name = "structopt",
+    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        ":clap",
+        ":lazy_static",
+        ":structopt_derive",
+    ],
+)
+
+rust_library(
+    name = "structopt_derive",
+    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":heck",
+        ":proc_macro2",
+        ":proc_macro_error",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "syn",
+    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    crate_features = [
+        "clone-impls",
+        "derive",
+        "full",
+        "parsing",
+        "printing",
+        "proc-macro",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":unicode_xid",
+    ],
+)
+
+rust_library(
+    name = "syn_mid",
+    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "termcolor",
+    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+)
+
+rust_library(
+    name = "textwrap",
+    srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
+    deps = [":unicode_width"],
+)
+
+rust_library(
+    name = "thiserror",
+    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [":thiserror_impl"],
+)
+
+rust_library(
+    name = "thiserror_impl",
+    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "unicode_segmentation",
+    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
+    edition = "2015",
+)
+
+rust_library(
+    name = "unicode_width",
+    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+)
+
+rust_library(
+    name = "unicode_xid",
+    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+)

From 67a658fddfa21090d6180f56c74c03ebbd6eab6c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 00:10:43 +0000
Subject: [PATCH 34/2232] Merge pull request #36 from dtolnay/bazel


Add bazel targets
---

diff --git a/.gitignore b/.gitignore
index b403b1d..e7499e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,8 @@
 /.buckd
+/bazel-bin
+/bazel-cxx
+/bazel-out
+/bazel-testlogs
 /buck-out
 /Cargo.lock
 /expand.cc
diff --git a/.travis.yml b/.travis.yml
index 6352e8d..d1fc088 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,3 +25,14 @@ matrix:
       script:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0
+    - name: Bazel
+      rust: nightly
+      before_install:
+        - wget -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+        - chmod +x install.sh
+        - ./install.sh --user
+      before_script:
+        - cp third-party/Cargo.lock .
+        - cargo vendor --versioned-dirs --locked third-party/vendor
+      script:
+        - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..b48c930
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,63 @@
+load("//:build/rust.bzl", "rust_binary", "rust_library")
+
+rust_library(
+    name = "cxx",
+    srcs = glob(["src/**/*.rs"]),
+    data = ["src/gen/include/cxxbridge.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":core_lib",
+        ":cxxbridge_macro",
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan",
+        "//third-party:codespan_reporting",
+        "//third-party:link_cplusplus",
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+rust_binary(
+    name = "codegen",
+    srcs = glob(["cmd/src/**/*.rs"]),
+    data = ["cmd/src/gen/include/cxxbridge.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:codespan",
+        "//third-party:codespan_reporting",
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:structopt",
+        "//third-party:syn",
+        "//third-party:thiserror",
+    ],
+)
+
+cc_library(
+    name = "core",
+    hdrs = ["include/cxxbridge.h"],
+    include_prefix = "cxxbridge",
+    strip_include_prefix = "include",
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "core_lib",
+    srcs = ["src/cxxbridge.cc"],
+    hdrs = ["include/cxxbridge.h"],
+)
+
+rust_library(
+    name = "cxxbridge_macro",
+    srcs = glob(["macro/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        "//third-party:proc_macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..26866e8
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,32 @@
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+    name = "io_bazel_rules_rust",
+    sha256 = "3d3faa85e49ebf4d26c40075549a17739d636360064b94a9d481b37ace0add82",
+    strip_prefix = "rules_rust-6e87304c834c30b9c9f585cad19f30e7045281d7",
+    # Master branch as of 2020-02-22
+    url = "https://github.com/bazelbuild/rules_rust/archive/6e87304c834c30b9c9f585cad19f30e7045281d7.tar.gz",
+)
+
+http_archive(
+    name = "bazel_skylib",
+    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+    ],
+)
+
+load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
+
+bazel_version(name = "bazel_version")
+
+load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
+
+rust_repository_set(
+    name = "rust_1_42_beta",
+    exec_triple = "x86_64-unknown-linux-gnu",
+    extra_target_triples = [],
+    iso_date = "2020-02-08",
+    version = "beta",
+)
diff --git a/build/rust.bzl b/build/rust.bzl
new file mode 100644
index 0000000..c2dade7
--- /dev/null
+++ b/build/rust.bzl
@@ -0,0 +1,19 @@
+load(
+    "@io_bazel_rules_rust//rust:rust.bzl",
+    _rust_binary = "rust_binary",
+    _rust_library = "rust_library",
+)
+
+def rust_binary(edition = "2018", **kwargs):
+    _rust_binary(edition = edition, **kwargs)
+
+def third_party_rust_binary(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_binary(rustc_flags = rustc_flags, **kwargs)
+
+def rust_library(edition = "2018", **kwargs):
+    _rust_library(edition = edition, **kwargs)
+
+def third_party_rust_library(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_library(rustc_flags = rustc_flags, **kwargs)
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
new file mode 100644
index 0000000..da97cfa
--- /dev/null
+++ b/demo-cxx/BUILD
@@ -0,0 +1,16 @@
+cc_library(
+    name = "demo-cxx",
+    srcs = ["demo.cc"],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":include",
+        "//demo-rs:include",
+    ],
+)
+
+cc_library(
+    name = "include",
+    hdrs = ["demo.h"],
+    visibility = ["//visibility:public"],
+    deps = ["//:core"],
+)
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
new file mode 100644
index 0000000..fb781b6
--- /dev/null
+++ b/demo-rs/BUILD
@@ -0,0 +1,43 @@
+load("//:build/rust.bzl", "rust_binary", "rust_library")
+
+rust_binary(
+    name = "demo_rs",
+    srcs = glob(["src/**"]),
+    deps = [
+        ":gen",
+        "//:cxx",
+        "//demo-cxx",
+    ],
+)
+
+cc_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":include",
+        "//demo-cxx:include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    outs = ["main.rs"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    outs = ["gen-demo.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "demo-rs/src",
+    visibility = ["//visibility:public"],
+)
diff --git a/third-party/BUILD b/third-party/BUILD
new file mode 100644
index 0000000..11b4257
--- /dev/null
+++ b/third-party/BUILD
@@ -0,0 +1,249 @@
+load(
+    "//:build/rust.bzl",
+    rust_binary = "third_party_rust_binary",
+    rust_library = "third_party_rust_library",
+)
+load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
+
+rust_library(
+    name = "anyhow",
+    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    crate_features = ["std"],
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "bitflags",
+    srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
+)
+
+rust_library(
+    name = "cc",
+    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "clap",
+    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    edition = "2015",
+    deps = [
+        ":bitflags",
+        ":textwrap",
+        ":unicode_width",
+    ],
+)
+
+rust_library(
+    name = "codespan",
+    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [":unicode_segmentation"],
+)
+
+rust_library(
+    name = "codespan_reporting",
+    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        ":codespan",
+        ":termcolor",
+        ":unicode_width",
+    ],
+)
+
+rust_library(
+    name = "heck",
+    srcs = glob(["vendor/heck-0.3.1/src/**"]),
+    edition = "2015",
+    deps = [":unicode_segmentation"],
+)
+
+rust_library(
+    name = "lazy_static",
+    srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+)
+
+rust_library(
+    name = "link_cplusplus",
+    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
+    name = "proc_macro_error",
+    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    rustc_flags = ["--cfg=use_fallback"],
+    deps = [
+        ":proc_macro2",
+        ":proc_macro_error_attr",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "proc_macro_error_attr",
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":rustversion",
+        ":syn",
+        ":syn_mid",
+    ],
+)
+
+rust_library(
+    name = "proc_macro2",
+    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    crate_features = [
+        "proc-macro",
+        "span-locations",
+    ],
+    rustc_flags = [
+        "--cfg=span_locations",
+        "--cfg=use_proc_macro",
+        "--cfg=wrap_proc_macro",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [":unicode_xid"],
+)
+
+rust_library(
+    name = "quote",
+    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    crate_features = ["proc-macro"],
+    visibility = ["//visibility:public"],
+    deps = [":proc_macro2"],
+)
+
+rust_library(
+    name = "rustversion",
+    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
+    crate_type = "proc-macro",
+    out_dir_tar = ":rustversion_buildscript_outdir",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_binary(
+    name = "rustversion_buildscript",
+    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
+    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
+)
+
+pkg_tar(
+    name = "rustversion_buildscript_outdir",
+    srcs = [":rustversion_buildscript_run"],
+    extension = "tar.gz",
+)
+
+genrule(
+    name = "rustversion_buildscript_run",
+    outs = ["version.rs"],
+    cmd = "OUT_DIR=$(@D) $(location :rustversion_buildscript)",
+    tools = [":rustversion_buildscript"],
+)
+
+rust_library(
+    name = "structopt",
+    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [
+        ":clap",
+        ":lazy_static",
+        ":structopt_derive",
+    ],
+)
+
+rust_library(
+    name = "structopt_derive",
+    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":heck",
+        ":proc_macro2",
+        ":proc_macro_error",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "syn",
+    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    crate_features = [
+        "clone-impls",
+        "derive",
+        "full",
+        "parsing",
+        "printing",
+        "proc-macro",
+    ],
+    visibility = ["//visibility:public"],
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":unicode_xid",
+    ],
+)
+
+rust_library(
+    name = "syn_mid",
+    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "termcolor",
+    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+)
+
+rust_library(
+    name = "textwrap",
+    srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
+    deps = [":unicode_width"],
+)
+
+rust_library(
+    name = "thiserror",
+    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    visibility = ["//visibility:public"],
+    deps = [":thiserror_impl"],
+)
+
+rust_library(
+    name = "thiserror_impl",
+    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    crate_type = "proc-macro",
+    deps = [
+        ":proc_macro2",
+        ":quote",
+        ":syn",
+    ],
+)
+
+rust_library(
+    name = "unicode_segmentation",
+    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
+    edition = "2015",
+)
+
+rust_library(
+    name = "unicode_width",
+    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+)
+
+rust_library(
+    name = "unicode_xid",
+    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+)

From c6244698ad3a4abf312f38b74b8d3d62e0bb53b8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 02:51:30 +0000
Subject: [PATCH 35/2232] Add a bazel rust toolchain for macOS


---

diff --git a/WORKSPACE b/WORKSPACE
index 26866e8..e6f96d2 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,9 +24,17 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_42_beta",
+    name = "rust_1_42_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [],
     iso_date = "2020-02-08",
     version = "beta",
 )
+
+rust_repository_set(
+    name = "rust_1_42_beta_darwin",
+    exec_triple = "x86_64-apple-darwin",
+    extra_target_triples = [],
+    iso_date = "2020-02-08",
+    version = "beta",
+)

From 54a53df768cbf99fd3cd4565938a8a99612e6ba8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 03:30:23 +0000
Subject: [PATCH 36/2232] Update vendored dependencies


Nothing important, but just working out this workflow.

---

diff --git a/third-party/BUCK b/third-party/BUCK
index 1c1bf3d..5c0e90d 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -170,7 +170,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    srcs = glob(["vendor/syn-1.0.15/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 11b4257..ceae8e2 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -176,7 +176,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.14/src/**"]),
+    srcs = glob(["vendor/syn-1.0.15/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index fda2025..3844959 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -160,9 +160,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.66"
+version = "0.2.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
+checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
 
 [[package]]
 name = "link-cplusplus"
@@ -297,9 +297,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
+checksum = "7a0294dc449adc58bb6592fff1a23d3e5e6e235afc6a0ffca2657d19e7bbffe5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -366,9 +366,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.21"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f5b3f750c701725331ac78e389b5d143b7d25f6b6ffffd0d419759a9063ac5f"
+checksum = "26ff1b18659a2218332848d76ad1c867ce4c6ee37b085e6bc8de9a6d11401220"
 dependencies = [
  "glob",
  "lazy_static",

From 97c72100391fdc26bc872e55c68b62fb6ec8e039 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 03:31:49 +0000
Subject: [PATCH 37/2232] Add test suite beyond the existing demo


---

diff --git a/Cargo.toml b/Cargo.toml
index b120173..fdfadc8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,8 +29,9 @@ thiserror = "1.0"
 cc = "1.0.49"
 
 [dev-dependencies]
+cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = "1.0"
+trybuild = "1.0.21"
 
 [workspace]
-members = ["cmd", "demo-rs", "macro"]
+members = ["cmd", "demo-rs", "macro", "tests/ffi"]
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
new file mode 100644
index 0000000..c84df61
--- /dev/null
+++ b/tests/ffi/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "cxx-test-suite"
+version = "0.0.0"
+edition = "2018"
+publish = false
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+cxx = { path = "../.." }
+
+[build-dependencies]
+cxx = { path = "../.." }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
new file mode 100644
index 0000000..5c1bec3
--- /dev/null
+++ b/tests/ffi/build.rs
@@ -0,0 +1,11 @@
+fn main() {
+    if cfg!(trybuild) {
+        return;
+    }
+
+    cxx::Build::new()
+        .bridge("lib.rs")
+        .file("tests.cc")
+        .flag("-std=c++11")
+        .compile("cxx-test-suite");
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
new file mode 100644
index 0000000..3ae732a
--- /dev/null
+++ b/tests/ffi/lib.rs
@@ -0,0 +1,6 @@
+#[cxx::bridge(namespace = tests)]
+pub mod ffi {
+    extern "C" {
+        include!("tests/ffi/tests.h");
+    }
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
new file mode 100644
index 0000000..6996d77
--- /dev/null
+++ b/tests/ffi/tests.cc
@@ -0,0 +1,6 @@
+#include "tests/ffi/lib.rs"
+#include "tests/ffi/tests.h"
+
+namespace tests {
+
+} // namespace tests
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
new file mode 100644
index 0000000..61f11d5
--- /dev/null
+++ b/tests/ffi/tests.h
@@ -0,0 +1,6 @@
+#pragma once
+#include "include/cxxbridge.h"
+
+namespace tests {
+
+} // namespace tests

From ad5b8afd9b5a3a03d8423b22d5006d8446b4ada4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 03:31:49 +0000
Subject: [PATCH 38/2232] Add exhaustive coverage of signature kinds


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 3ae732a..168261d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,6 +1,115 @@
+use cxx::{CxxString, UniquePtr};
+
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
+    struct Shared {
+        z: usize,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
+
+        type C;
+
+        fn c_return_primitive() -> usize;
+        fn c_return_shared() -> Shared;
+        //TODO fn c_return_box() -> Box<R>;
+        fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_ref(shared: &Shared) -> &usize;
+        fn c_return_str(shared: &Shared) -> &str;
+        fn c_return_rust_string() -> String;
+        fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
+
+        fn c_take_primitive(n: usize);
+        fn c_take_shared(shared: Shared);
+        fn c_take_box(r: Box<R>);
+        fn c_take_unique_ptr(c: UniquePtr<C>);
+        //TODO fn c_take_ref_r(r: &R);
+        fn c_take_ref_c(c: &C);
+        fn c_take_str(s: &str);
+        fn c_take_rust_string(s: String);
+        fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+    }
+
+    extern "Rust" {
+        type R;
+
+        fn r_return_primitive() -> usize;
+        fn r_return_shared() -> Shared;
+        //TODO fn r_return_box() -> Box<R>;
+        //TODO fn r_return_unique_ptr() -> UniquePtr<C>;
+        fn r_return_ref(shared: &Shared) -> &usize;
+        fn r_return_str(shared: &Shared) -> &str;
+        fn r_return_rust_string() -> String;
+        //TODO fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
+
+        fn r_take_primitive(n: usize);
+        fn r_take_shared(shared: Shared);
+        fn r_take_box(r: Box<R>);
+        fn r_take_unique_ptr(c: UniquePtr<C>);
+        fn r_take_ref_r(r: &R);
+        fn r_take_ref_c(c: &C);
+        fn r_take_str(s: &str);
+        fn r_take_rust_string(s: String);
+        fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
     }
 }
+
+type R = ();
+
+fn r_return_primitive() -> usize {
+    2020
+}
+
+fn r_return_shared() -> ffi::Shared {
+    ffi::Shared { z: 2020 }
+}
+
+fn r_return_ref(shared: &ffi::Shared) -> &usize {
+    &shared.z
+}
+
+fn r_return_str(shared: &ffi::Shared) -> &str {
+    let _ = shared;
+    "2020"
+}
+
+fn r_return_rust_string() -> String {
+    "2020".to_owned()
+}
+
+fn r_take_primitive(n: usize) {
+    let _ = n;
+}
+
+fn r_take_shared(shared: ffi::Shared) {
+    let _ = shared;
+}
+
+fn r_take_box(r: Box<R>) {
+    let _ = r;
+}
+
+fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
+    let _ = c;
+}
+
+fn r_take_ref_r(r: &R) {
+    let _ = r;
+}
+
+fn r_take_ref_c(c: &ffi::C) {
+    let _ = c;
+}
+
+fn r_take_str(s: &str) {
+    let _ = s;
+}
+
+fn r_take_rust_string(s: String) {
+    let _ = s;
+}
+
+fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
+    let _ = s;
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6996d77..ecfafd0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -3,4 +3,71 @@
 
 namespace tests {
 
+C::C(size_t n) : n(n) {}
+
+size_t c_return_primitive() {
+  return 2020;
+}
+
+Shared c_return_shared() {
+  return Shared{2020};
+}
+
+std::unique_ptr<C> c_return_unique_ptr() {
+  return std::unique_ptr<C>(new C{2020});
+}
+
+const size_t &c_return_ref(const Shared &shared) {
+  return shared.z;
+}
+
+cxxbridge::RustStr c_return_str(const Shared &shared) {
+  (void)shared;
+  return "2020";
+}
+
+cxxbridge::RustString c_return_rust_string() {
+  return "2020";
+}
+
+std::unique_ptr<std::string> c_return_unique_ptr_string() {
+  return std::unique_ptr<std::string>(new std::string("2020"));
+}
+
+void c_take_primitive(size_t n) {
+  (void)n;
+}
+
+void c_take_shared(Shared shared) {
+  (void)shared;
+}
+
+void c_take_box(cxxbridge::RustBox<R> r) {
+  (void)r;
+}
+
+void c_take_unique_ptr(std::unique_ptr<C> c) {
+  (void)c;
+}
+
+void c_take_ref_r(const R &r) {
+  (void)r;
+}
+
+void c_take_ref_c(const C &c) {
+  (void)c;
+}
+
+void c_take_str(cxxbridge::RustStr s) {
+  (void)s;
+}
+
+void c_take_rust_string(cxxbridge::RustString s) {
+  (void)s;
+}
+
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
+  (void)s;
+}
+
 } // namespace tests
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 61f11d5..8510946 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -1,6 +1,38 @@
 #pragma once
 #include "include/cxxbridge.h"
+#include <memory>
+#include <string>
 
 namespace tests {
 
+struct R;
+struct Shared;
+
+class C {
+public:
+  C(size_t n);
+
+private:
+  size_t n;
+};
+
+size_t c_return_primitive();
+Shared c_return_shared();
+cxxbridge::RustBox<R> c_return_box();
+std::unique_ptr<C> c_return_unique_ptr();
+const size_t &c_return_ref(const Shared &shared);
+cxxbridge::RustStr c_return_str(const Shared &shared);
+cxxbridge::RustString c_return_rust_string();
+std::unique_ptr<std::string> c_return_unique_ptr_string();
+
+void c_take_primitive(size_t n);
+void c_take_shared(Shared shared);
+void c_take_box(cxxbridge::RustBox<R> r);
+void c_take_unique_ptr(std::unique_ptr<C> c);
+void c_take_ref_r(const R &r);
+void c_take_ref_c(const C &c);
+void c_take_str(cxxbridge::RustStr s);
+void c_take_rust_string(cxxbridge::RustString s);
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+
 } // namespace tests

From b871577737a9bea9a200766d16a3ab9c1489176e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 03:31:49 +0000
Subject: [PATCH 39/2232] Format with clang-format


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index ecfafd0..26c14fe 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,73 +1,47 @@
-#include "tests/ffi/lib.rs"
 #include "tests/ffi/tests.h"
+#include "tests/ffi/lib.rs"
 
 namespace tests {
 
 C::C(size_t n) : n(n) {}
 
-size_t c_return_primitive() {
-  return 2020;
-}
+size_t c_return_primitive() { return 2020; }
 
-Shared c_return_shared() {
-  return Shared{2020};
-}
+Shared c_return_shared() { return Shared{2020}; }
 
 std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
 
-const size_t &c_return_ref(const Shared &shared) {
-  return shared.z;
-}
+const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
 cxxbridge::RustStr c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
 
-cxxbridge::RustString c_return_rust_string() {
-  return "2020";
-}
+cxxbridge::RustString c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
 }
 
-void c_take_primitive(size_t n) {
-  (void)n;
-}
+void c_take_primitive(size_t n) { (void)n; }
 
-void c_take_shared(Shared shared) {
-  (void)shared;
-}
+void c_take_shared(Shared shared) { (void)shared; }
 
-void c_take_box(cxxbridge::RustBox<R> r) {
-  (void)r;
-}
+void c_take_box(cxxbridge::RustBox<R> r) { (void)r; }
 
-void c_take_unique_ptr(std::unique_ptr<C> c) {
-  (void)c;
-}
+void c_take_unique_ptr(std::unique_ptr<C> c) { (void)c; }
 
-void c_take_ref_r(const R &r) {
-  (void)r;
-}
+void c_take_ref_r(const R &r) { (void)r; }
 
-void c_take_ref_c(const C &c) {
-  (void)c;
-}
+void c_take_ref_c(const C &c) { (void)c; }
 
-void c_take_str(cxxbridge::RustStr s) {
-  (void)s;
-}
+void c_take_str(cxxbridge::RustStr s) { (void)s; }
 
-void c_take_rust_string(cxxbridge::RustString s) {
-  (void)s;
-}
+void c_take_rust_string(cxxbridge::RustString s) { (void)s; }
 
-void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
-  (void)s;
-}
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s) { (void)s; }
 
 } // namespace tests

From 3fd7f56275674a5ce22ef987be7596d1c27195f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 04:02:02 +0000
Subject: [PATCH 40/2232] Test rust calling to c++


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 26c14fe..cfe07ab 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,10 +1,14 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
 
+extern "C" void cxx_test_suite_set_correct();
+
 namespace tests {
 
 C::C(size_t n) : n(n) {}
 
+size_t C::get() const { return this->n; }
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -26,22 +30,53 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
 }
 
-void c_take_primitive(size_t n) { (void)n; }
+void c_take_primitive(size_t n) {
+  if (n == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
 
-void c_take_shared(Shared shared) { (void)shared; }
+void c_take_shared(Shared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
 
-void c_take_box(cxxbridge::RustBox<R> r) { (void)r; }
+void c_take_box(cxxbridge::RustBox<R> r) {
+  (void)r;
+  cxx_test_suite_set_correct();
+}
 
-void c_take_unique_ptr(std::unique_ptr<C> c) { (void)c; }
+void c_take_unique_ptr(std::unique_ptr<C> c) {
+  if (c->get() == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
 
 void c_take_ref_r(const R &r) { (void)r; }
 
-void c_take_ref_c(const C &c) { (void)c; }
+void c_take_ref_c(const C &c) {
+  if (c.get() == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
 
-void c_take_str(cxxbridge::RustStr s) { (void)s; }
+void c_take_str(cxxbridge::RustStr s) {
+  if (std::string(s) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
 
-void c_take_rust_string(cxxbridge::RustString s) { (void)s; }
+void c_take_rust_string(cxxbridge::RustString s) {
+  if (std::string(s) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
 
-void c_take_unique_ptr_string(std::unique_ptr<std::string> s) { (void)s; }
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
+  if (*s == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
 
 } // namespace tests
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 8510946..14e019f 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -11,6 +11,7 @@ struct Shared;
 class C {
 public:
   C(size_t n);
+  size_t get() const;
 
 private:
   size_t n;
diff --git a/tests/test.rs b/tests/test.rs
new file mode 100644
index 0000000..9f595f7
--- /dev/null
+++ b/tests/test.rs
@@ -0,0 +1,55 @@
+use cxx_test_suite::ffi;
+use std::cell::Cell;
+
+thread_local! {
+    static CORRECT: Cell<bool> = Cell::new(false);
+}
+
+#[no_mangle]
+extern "C" fn cxx_test_suite_set_correct() {
+    CORRECT.with(|correct| correct.set(true));
+}
+
+#[test]
+fn test_c_return() {
+    let shared = ffi::Shared { z: 2020 };
+
+    assert_eq!(2020, ffi::c_return_primitive());
+    assert_eq!(2020, ffi::c_return_shared().z);
+    ffi::c_return_unique_ptr();
+    assert_eq!(2020, *ffi::c_return_ref(&shared));
+    assert_eq!("2020", ffi::c_return_str(&shared));
+    assert_eq!("2020", ffi::c_return_rust_string());
+    assert_eq!(
+        "2020",
+        ffi::c_return_unique_ptr_string()
+            .as_ref()
+            .unwrap()
+            .to_str()
+            .unwrap()
+    );
+}
+
+#[test]
+fn test_c_take() {
+    macro_rules! check {
+        ($run:expr) => {{
+            CORRECT.with(|correct| correct.set(false));
+            $run;
+            assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
+        }};
+    }
+
+    let unique_ptr = ffi::c_return_unique_ptr();
+
+    check!(ffi::c_take_primitive(2020));
+    check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
+    check!(ffi::c_take_box(Box::new(())));
+    check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
+    check!(ffi::c_take_unique_ptr(unique_ptr));
+    check!(ffi::c_take_str("2020"));
+    check!(ffi::c_take_rust_string("2020".to_owned()));
+    check!(ffi::c_take_unique_ptr_string(
+        ffi::c_return_unique_ptr_string()
+    ));
+}

From f306da4dc713a3ea78edc10e0d73d4252cde73a0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 06:42:35 +0000
Subject: [PATCH 41/2232] Test c++ calling to rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 168261d..098253a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -79,11 +79,11 @@ fn r_return_rust_string() -> String {
 }
 
 fn r_take_primitive(n: usize) {
-    let _ = n;
+    assert_eq!(n, 2020);
 }
 
 fn r_take_shared(shared: ffi::Shared) {
-    let _ = shared;
+    assert_eq!(shared.z, 2020);
 }
 
 fn r_take_box(r: Box<R>) {
@@ -103,13 +103,13 @@ fn r_take_ref_c(c: &ffi::C) {
 }
 
 fn r_take_str(s: &str) {
-    let _ = s;
+    assert_eq!(s, "2020");
 }
 
 fn r_take_rust_string(s: String) {
-    let _ = s;
+    assert_eq!(s, "2020");
 }
 
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
-    let _ = s;
+    assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index cfe07ab..d27df41 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -79,4 +79,33 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+extern "C" const char *cxx_run_test() noexcept {
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define ASSERT(x)                                                              \
+  do {                                                                         \
+    if (!(x)) {                                                                \
+      return "Assertion failed: `" #x "`, " __FILE__ ":" TOSTRING(__LINE__);   \
+    }                                                                          \
+  } while (false)
+
+  ASSERT(r_return_primitive() == 2020);
+  ASSERT(r_return_shared().z == 2020);
+  ASSERT(r_return_ref(Shared{2020}) == 2020);
+  ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
+  ASSERT(std::string(r_return_rust_string()) == "2020");
+
+  r_take_primitive(2020);
+  r_take_shared(Shared{2020});
+  r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
+  r_take_ref_c(C{2020});
+  r_take_str(cxxbridge::RustStr("2020"));
+  // TODO r_take_rust_string(cxxbridge::RustString("2020"));
+  r_take_unique_ptr_string(
+      std::unique_ptr<std::string>(new std::string("2020")));
+
+  cxx_test_suite_set_correct();
+  return nullptr;
+}
+
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index 9f595f7..28e5c3b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,5 +1,6 @@
 use cxx_test_suite::ffi;
 use std::cell::Cell;
+use std::ffi::CStr;
 
 thread_local! {
     static CORRECT: Cell<bool> = Cell::new(false);
@@ -10,6 +11,14 @@ extern "C" fn cxx_test_suite_set_correct() {
     CORRECT.with(|correct| correct.set(true));
 }
 
+macro_rules! check {
+    ($run:expr) => {{
+        CORRECT.with(|correct| correct.set(false));
+        $run;
+        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
+    }};
+}
+
 #[test]
 fn test_c_return() {
     let shared = ffi::Shared { z: 2020 };
@@ -32,14 +41,6 @@ fn test_c_return() {
 
 #[test]
 fn test_c_take() {
-    macro_rules! check {
-        ($run:expr) => {{
-            CORRECT.with(|correct| correct.set(false));
-            $run;
-            assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
-        }};
-    }
-
     let unique_ptr = ffi::c_return_unique_ptr();
 
     check!(ffi::c_take_primitive(2020));
@@ -53,3 +54,18 @@ fn test_c_take() {
         ffi::c_return_unique_ptr_string()
     ));
 }
+
+#[test]
+fn test_c_call_r() {
+    fn cxx_run_test() {
+        extern "C" {
+            fn cxx_run_test() -> *const i8;
+        }
+        let failure = unsafe { cxx_run_test() };
+        if !failure.is_null() {
+            let msg = unsafe { CStr::from_ptr(failure) };
+            eprintln!("{}", msg.to_string_lossy());
+        }
+    }
+    check!(cxx_run_test());
+}

From c9bf95703faea0ee08c2e90e4fc6028a8a7e7e19 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 06:53:03 +0000
Subject: [PATCH 42/2232] Update lockfile to include test suite crate


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3844959..5f2a1ca 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -81,6 +81,7 @@ dependencies = [
  "cc",
  "codespan",
  "codespan-reporting",
+ "cxx-test-suite",
  "cxxbridge-macro",
  "link-cplusplus",
  "proc-macro2",
@@ -92,6 +93,13 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxx-test-suite"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+]
+
+[[package]]
 name = "cxxbridge-cmd"
 version = "0.1.2"
 dependencies = [

From d1010bdb390103a258a393bab872ca776337ee65 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 07:03:10 +0000
Subject: [PATCH 43/2232] Merge pull request #38 from dtolnay/suite


Add test suite covering various permutations of signatures
---

diff --git a/Cargo.toml b/Cargo.toml
index b120173..fdfadc8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,8 +29,9 @@ thiserror = "1.0"
 cc = "1.0.49"
 
 [dev-dependencies]
+cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = "1.0"
+trybuild = "1.0.21"
 
 [workspace]
-members = ["cmd", "demo-rs", "macro"]
+members = ["cmd", "demo-rs", "macro", "tests/ffi"]
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
new file mode 100644
index 0000000..c84df61
--- /dev/null
+++ b/tests/ffi/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "cxx-test-suite"
+version = "0.0.0"
+edition = "2018"
+publish = false
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+cxx = { path = "../.." }
+
+[build-dependencies]
+cxx = { path = "../.." }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
new file mode 100644
index 0000000..5c1bec3
--- /dev/null
+++ b/tests/ffi/build.rs
@@ -0,0 +1,11 @@
+fn main() {
+    if cfg!(trybuild) {
+        return;
+    }
+
+    cxx::Build::new()
+        .bridge("lib.rs")
+        .file("tests.cc")
+        .flag("-std=c++11")
+        .compile("cxx-test-suite");
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
new file mode 100644
index 0000000..098253a
--- /dev/null
+++ b/tests/ffi/lib.rs
@@ -0,0 +1,115 @@
+use cxx::{CxxString, UniquePtr};
+
+#[cxx::bridge(namespace = tests)]
+pub mod ffi {
+    struct Shared {
+        z: usize,
+    }
+
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        type C;
+
+        fn c_return_primitive() -> usize;
+        fn c_return_shared() -> Shared;
+        //TODO fn c_return_box() -> Box<R>;
+        fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_ref(shared: &Shared) -> &usize;
+        fn c_return_str(shared: &Shared) -> &str;
+        fn c_return_rust_string() -> String;
+        fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
+
+        fn c_take_primitive(n: usize);
+        fn c_take_shared(shared: Shared);
+        fn c_take_box(r: Box<R>);
+        fn c_take_unique_ptr(c: UniquePtr<C>);
+        //TODO fn c_take_ref_r(r: &R);
+        fn c_take_ref_c(c: &C);
+        fn c_take_str(s: &str);
+        fn c_take_rust_string(s: String);
+        fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+    }
+
+    extern "Rust" {
+        type R;
+
+        fn r_return_primitive() -> usize;
+        fn r_return_shared() -> Shared;
+        //TODO fn r_return_box() -> Box<R>;
+        //TODO fn r_return_unique_ptr() -> UniquePtr<C>;
+        fn r_return_ref(shared: &Shared) -> &usize;
+        fn r_return_str(shared: &Shared) -> &str;
+        fn r_return_rust_string() -> String;
+        //TODO fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
+
+        fn r_take_primitive(n: usize);
+        fn r_take_shared(shared: Shared);
+        fn r_take_box(r: Box<R>);
+        fn r_take_unique_ptr(c: UniquePtr<C>);
+        fn r_take_ref_r(r: &R);
+        fn r_take_ref_c(c: &C);
+        fn r_take_str(s: &str);
+        fn r_take_rust_string(s: String);
+        fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+    }
+}
+
+type R = ();
+
+fn r_return_primitive() -> usize {
+    2020
+}
+
+fn r_return_shared() -> ffi::Shared {
+    ffi::Shared { z: 2020 }
+}
+
+fn r_return_ref(shared: &ffi::Shared) -> &usize {
+    &shared.z
+}
+
+fn r_return_str(shared: &ffi::Shared) -> &str {
+    let _ = shared;
+    "2020"
+}
+
+fn r_return_rust_string() -> String {
+    "2020".to_owned()
+}
+
+fn r_take_primitive(n: usize) {
+    assert_eq!(n, 2020);
+}
+
+fn r_take_shared(shared: ffi::Shared) {
+    assert_eq!(shared.z, 2020);
+}
+
+fn r_take_box(r: Box<R>) {
+    let _ = r;
+}
+
+fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
+    let _ = c;
+}
+
+fn r_take_ref_r(r: &R) {
+    let _ = r;
+}
+
+fn r_take_ref_c(c: &ffi::C) {
+    let _ = c;
+}
+
+fn r_take_str(s: &str) {
+    assert_eq!(s, "2020");
+}
+
+fn r_take_rust_string(s: String) {
+    assert_eq!(s, "2020");
+}
+
+fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
+    assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
new file mode 100644
index 0000000..d27df41
--- /dev/null
+++ b/tests/ffi/tests.cc
@@ -0,0 +1,111 @@
+#include "tests/ffi/tests.h"
+#include "tests/ffi/lib.rs"
+
+extern "C" void cxx_test_suite_set_correct();
+
+namespace tests {
+
+C::C(size_t n) : n(n) {}
+
+size_t C::get() const { return this->n; }
+
+size_t c_return_primitive() { return 2020; }
+
+Shared c_return_shared() { return Shared{2020}; }
+
+std::unique_ptr<C> c_return_unique_ptr() {
+  return std::unique_ptr<C>(new C{2020});
+}
+
+const size_t &c_return_ref(const Shared &shared) { return shared.z; }
+
+cxxbridge::RustStr c_return_str(const Shared &shared) {
+  (void)shared;
+  return "2020";
+}
+
+cxxbridge::RustString c_return_rust_string() { return "2020"; }
+
+std::unique_ptr<std::string> c_return_unique_ptr_string() {
+  return std::unique_ptr<std::string>(new std::string("2020"));
+}
+
+void c_take_primitive(size_t n) {
+  if (n == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_shared(Shared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_box(cxxbridge::RustBox<R> r) {
+  (void)r;
+  cxx_test_suite_set_correct();
+}
+
+void c_take_unique_ptr(std::unique_ptr<C> c) {
+  if (c->get() == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_ref_r(const R &r) { (void)r; }
+
+void c_take_ref_c(const C &c) {
+  if (c.get() == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_str(cxxbridge::RustStr s) {
+  if (std::string(s) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_rust_string(cxxbridge::RustString s) {
+  if (std::string(s) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
+  if (*s == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+extern "C" const char *cxx_run_test() noexcept {
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define ASSERT(x)                                                              \
+  do {                                                                         \
+    if (!(x)) {                                                                \
+      return "Assertion failed: `" #x "`, " __FILE__ ":" TOSTRING(__LINE__);   \
+    }                                                                          \
+  } while (false)
+
+  ASSERT(r_return_primitive() == 2020);
+  ASSERT(r_return_shared().z == 2020);
+  ASSERT(r_return_ref(Shared{2020}) == 2020);
+  ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
+  ASSERT(std::string(r_return_rust_string()) == "2020");
+
+  r_take_primitive(2020);
+  r_take_shared(Shared{2020});
+  r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
+  r_take_ref_c(C{2020});
+  r_take_str(cxxbridge::RustStr("2020"));
+  // TODO r_take_rust_string(cxxbridge::RustString("2020"));
+  r_take_unique_ptr_string(
+      std::unique_ptr<std::string>(new std::string("2020")));
+
+  cxx_test_suite_set_correct();
+  return nullptr;
+}
+
+} // namespace tests
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
new file mode 100644
index 0000000..14e019f
--- /dev/null
+++ b/tests/ffi/tests.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "include/cxxbridge.h"
+#include <memory>
+#include <string>
+
+namespace tests {
+
+struct R;
+struct Shared;
+
+class C {
+public:
+  C(size_t n);
+  size_t get() const;
+
+private:
+  size_t n;
+};
+
+size_t c_return_primitive();
+Shared c_return_shared();
+cxxbridge::RustBox<R> c_return_box();
+std::unique_ptr<C> c_return_unique_ptr();
+const size_t &c_return_ref(const Shared &shared);
+cxxbridge::RustStr c_return_str(const Shared &shared);
+cxxbridge::RustString c_return_rust_string();
+std::unique_ptr<std::string> c_return_unique_ptr_string();
+
+void c_take_primitive(size_t n);
+void c_take_shared(Shared shared);
+void c_take_box(cxxbridge::RustBox<R> r);
+void c_take_unique_ptr(std::unique_ptr<C> c);
+void c_take_ref_r(const R &r);
+void c_take_ref_c(const C &c);
+void c_take_str(cxxbridge::RustStr s);
+void c_take_rust_string(cxxbridge::RustString s);
+void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+
+} // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
new file mode 100644
index 0000000..28e5c3b
--- /dev/null
+++ b/tests/test.rs
@@ -0,0 +1,71 @@
+use cxx_test_suite::ffi;
+use std::cell::Cell;
+use std::ffi::CStr;
+
+thread_local! {
+    static CORRECT: Cell<bool> = Cell::new(false);
+}
+
+#[no_mangle]
+extern "C" fn cxx_test_suite_set_correct() {
+    CORRECT.with(|correct| correct.set(true));
+}
+
+macro_rules! check {
+    ($run:expr) => {{
+        CORRECT.with(|correct| correct.set(false));
+        $run;
+        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
+    }};
+}
+
+#[test]
+fn test_c_return() {
+    let shared = ffi::Shared { z: 2020 };
+
+    assert_eq!(2020, ffi::c_return_primitive());
+    assert_eq!(2020, ffi::c_return_shared().z);
+    ffi::c_return_unique_ptr();
+    assert_eq!(2020, *ffi::c_return_ref(&shared));
+    assert_eq!("2020", ffi::c_return_str(&shared));
+    assert_eq!("2020", ffi::c_return_rust_string());
+    assert_eq!(
+        "2020",
+        ffi::c_return_unique_ptr_string()
+            .as_ref()
+            .unwrap()
+            .to_str()
+            .unwrap()
+    );
+}
+
+#[test]
+fn test_c_take() {
+    let unique_ptr = ffi::c_return_unique_ptr();
+
+    check!(ffi::c_take_primitive(2020));
+    check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
+    check!(ffi::c_take_box(Box::new(())));
+    check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
+    check!(ffi::c_take_unique_ptr(unique_ptr));
+    check!(ffi::c_take_str("2020"));
+    check!(ffi::c_take_rust_string("2020".to_owned()));
+    check!(ffi::c_take_unique_ptr_string(
+        ffi::c_return_unique_ptr_string()
+    ));
+}
+
+#[test]
+fn test_c_call_r() {
+    fn cxx_run_test() {
+        extern "C" {
+            fn cxx_run_test() -> *const i8;
+        }
+        let failure = unsafe { cxx_run_test() };
+        if !failure.is_null() {
+            let msg = unsafe { CStr::from_ptr(failure) };
+            eprintln!("{}", msg.to_string_lossy());
+        }
+    }
+    check!(cxx_run_test());
+}
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3844959..5f2a1ca 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -81,6 +81,7 @@ dependencies = [
  "cc",
  "codespan",
  "codespan-reporting",
+ "cxx-test-suite",
  "cxxbridge-macro",
  "link-cplusplus",
  "proc-macro2",
@@ -92,6 +93,13 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxx-test-suite"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+]
+
+[[package]]
 name = "cxxbridge-cmd"
 version = "0.1.2"
 dependencies = [

From e3e0a7129111d81f77424fe321ca1635de33d20b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 08:18:57 +0000
Subject: [PATCH 44/2232] Use the public cxxbridge.h include path


---

diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 14e019f..87aac67 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "include/cxxbridge.h"
+#include "cxxbridge/cxxbridge.h"
 #include <memory>
 #include <string>
 

From 9bc613e7dbba8041a130deb61d11aa1689f5d818 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 08:36:44 +0000
Subject: [PATCH 45/2232] Add test suite targets for buck and bazel


---

diff --git a/.travis.yml b/.travis.yml
index d1fc088..6d7f255 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,6 +25,7 @@ matrix:
       script:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0
+        - buck test ... --verbose=0
     - name: Bazel
       rust: nightly
       before_install:
@@ -36,3 +37,4 @@ matrix:
         - cargo vendor --versioned-dirs --locked third-party/vendor
       script:
         - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
+        - bazel test ... --verbose_failures --noshow_progress
diff --git a/build/rust.bzl b/build/rust.bzl
index c2dade7..3ef4d91 100644
--- a/build/rust.bzl
+++ b/build/rust.bzl
@@ -2,6 +2,7 @@ load(
     "@io_bazel_rules_rust//rust:rust.bzl",
     _rust_binary = "rust_binary",
     _rust_library = "rust_library",
+    _rust_test = "rust_test",
 )
 
 def rust_binary(edition = "2018", **kwargs):
@@ -17,3 +18,6 @@ def rust_library(edition = "2018", **kwargs):
 def third_party_rust_library(rustc_flags = [], **kwargs):
     rustc_flags = rustc_flags + ["--cap-lints=allow"]
     rust_library(rustc_flags = rustc_flags, **kwargs)
+
+def rust_test(edition = "2018", **kwargs):
+    _rust_test(edition = edition, **kwargs)
diff --git a/tests/BUCK b/tests/BUCK
new file mode 100644
index 0000000..81f74de
--- /dev/null
+++ b/tests/BUCK
@@ -0,0 +1,42 @@
+rust_test(
+    name = "test",
+    srcs = ["test.rs"],
+    deps = [":ffi"],
+)
+
+rust_library(
+    name = "ffi",
+    srcs = ["ffi/lib.rs"],
+    crate = "cxx_test_suite",
+    deps = [
+        ":impl",
+        "//:cxx",
+    ],
+)
+
+cxx_library(
+    name = "impl",
+    srcs = [
+        "ffi/tests.cc",
+        ":gen-source",
+    ],
+    headers = {
+        "ffi/lib.rs": ":gen-header",
+        "ffi/tests.h": "ffi/tests.h",
+    },
+    deps = ["//:core"],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["ffi/lib.rs"],
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    out = "gen.h",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["ffi/lib.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    out = "gen.cc",
+)
diff --git a/tests/BUILD b/tests/BUILD
new file mode 100644
index 0000000..a88cde5
--- /dev/null
+++ b/tests/BUILD
@@ -0,0 +1,51 @@
+load("//:build/rust.bzl", "rust_library", "rust_test")
+
+rust_test(
+    name = "test",
+    srcs = ["test.rs"],
+    deps = [":cxx_test_suite"],
+)
+
+rust_library(
+    name = "cxx_test_suite",
+    srcs = ["ffi/lib.rs"],
+    deps = [
+        ":impl",
+        "//:cxx",
+    ],
+)
+
+cc_library(
+    name = "impl",
+    srcs = [
+        "ffi/tests.cc",
+        ":gen-source",
+    ],
+    hdrs = ["ffi/tests.h"],
+    deps = [
+        ":include",
+        "//:core",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["ffi/lib.rs"],
+    outs = ["lib.rs"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["ffi/lib.rs"],
+    outs = ["gen.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "tests/ffi",
+)

From 54875798eca132136a7b0281b084627c3b14d9d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 08:46:22 +0000
Subject: [PATCH 46/2232] Merge pull request #39 from dtolnay/suite


Add test suite targets for buck and bazel
---

diff --git a/.travis.yml b/.travis.yml
index d1fc088..6d7f255 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,6 +25,7 @@ matrix:
       script:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0
+        - buck test ... --verbose=0
     - name: Bazel
       rust: nightly
       before_install:
@@ -36,3 +37,4 @@ matrix:
         - cargo vendor --versioned-dirs --locked third-party/vendor
       script:
         - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
+        - bazel test ... --verbose_failures --noshow_progress
diff --git a/build/rust.bzl b/build/rust.bzl
index c2dade7..3ef4d91 100644
--- a/build/rust.bzl
+++ b/build/rust.bzl
@@ -2,6 +2,7 @@ load(
     "@io_bazel_rules_rust//rust:rust.bzl",
     _rust_binary = "rust_binary",
     _rust_library = "rust_library",
+    _rust_test = "rust_test",
 )
 
 def rust_binary(edition = "2018", **kwargs):
@@ -17,3 +18,6 @@ def rust_library(edition = "2018", **kwargs):
 def third_party_rust_library(rustc_flags = [], **kwargs):
     rustc_flags = rustc_flags + ["--cap-lints=allow"]
     rust_library(rustc_flags = rustc_flags, **kwargs)
+
+def rust_test(edition = "2018", **kwargs):
+    _rust_test(edition = edition, **kwargs)
diff --git a/tests/BUCK b/tests/BUCK
new file mode 100644
index 0000000..81f74de
--- /dev/null
+++ b/tests/BUCK
@@ -0,0 +1,42 @@
+rust_test(
+    name = "test",
+    srcs = ["test.rs"],
+    deps = [":ffi"],
+)
+
+rust_library(
+    name = "ffi",
+    srcs = ["ffi/lib.rs"],
+    crate = "cxx_test_suite",
+    deps = [
+        ":impl",
+        "//:cxx",
+    ],
+)
+
+cxx_library(
+    name = "impl",
+    srcs = [
+        "ffi/tests.cc",
+        ":gen-source",
+    ],
+    headers = {
+        "ffi/lib.rs": ":gen-header",
+        "ffi/tests.h": "ffi/tests.h",
+    },
+    deps = ["//:core"],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["ffi/lib.rs"],
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    out = "gen.h",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["ffi/lib.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    out = "gen.cc",
+)
diff --git a/tests/BUILD b/tests/BUILD
new file mode 100644
index 0000000..a88cde5
--- /dev/null
+++ b/tests/BUILD
@@ -0,0 +1,51 @@
+load("//:build/rust.bzl", "rust_library", "rust_test")
+
+rust_test(
+    name = "test",
+    srcs = ["test.rs"],
+    deps = [":cxx_test_suite"],
+)
+
+rust_library(
+    name = "cxx_test_suite",
+    srcs = ["ffi/lib.rs"],
+    deps = [
+        ":impl",
+        "//:cxx",
+    ],
+)
+
+cc_library(
+    name = "impl",
+    srcs = [
+        "ffi/tests.cc",
+        ":gen-source",
+    ],
+    hdrs = ["ffi/tests.h"],
+    deps = [
+        ":include",
+        "//:core",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["ffi/lib.rs"],
+    outs = ["lib.rs"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["ffi/lib.rs"],
+    outs = ["gen.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "tests/ffi",
+)

From 908385887bde9a6309ffa770fcfaf9db19f323fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 08:57:03 +0000
Subject: [PATCH 47/2232] Protect from ADL in Box construction and assignment


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index a0d9dbb..0bfe805 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -66,7 +66,7 @@ public:
   RustBox(RustBox &&other) noexcept : repr(other.repr) { other.repr = 0; }
   RustBox(const T &val) {
     this->uninit();
-    new (this->deref_mut()) T(val);
+    ::new (this->deref_mut()) T(val);
   }
   RustBox &operator=(const RustBox &other) {
     if (this != &other) {
@@ -74,7 +74,7 @@ public:
         **this = *other;
       } else {
         this->uninit();
-        new (this->deref_mut()) T(*other);
+        ::new (this->deref_mut()) T(*other);
       }
     }
     return *this;

From 2fc07c11a831beceaac1e0ab7d36cfffcf94ddfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 23 2020 09:06:28 +0000
Subject: [PATCH 48/2232] Merge pull request #40 from dtolnay/box


Protect from ADL in Box construction and assignment
---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index a0d9dbb..0bfe805 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -66,7 +66,7 @@ public:
   RustBox(RustBox &&other) noexcept : repr(other.repr) { other.repr = 0; }
   RustBox(const T &val) {
     this->uninit();
-    new (this->deref_mut()) T(val);
+    ::new (this->deref_mut()) T(val);
   }
   RustBox &operator=(const RustBox &other) {
     if (this != &other) {
@@ -74,7 +74,7 @@ public:
         **this = *other;
       } else {
         this->uninit();
-        new (this->deref_mut()) T(*other);
+        ::new (this->deref_mut()) T(*other);
       }
     }
     return *this;

From bce77ba9fe44f3b45c72333e9244a0517c689311 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 24 2020 09:54:27 +0000
Subject: [PATCH 49/2232] Add travis build on windows


---

diff --git a/.travis.yml b/.travis.yml
index 6d7f255..9534d50 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,12 @@ matrix:
   include:
     - os: macos
       rust: nightly
+    - os: windows
+      rust: nightly
+      before_script:
+        # windows is bad at symlinks
+        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
+        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
     - name: Buck
       rust: nightly
       before_install:

From 2a1eaac049ca759f962ea7cfea594f45b9b8c832 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 24 2020 10:02:58 +0000
Subject: [PATCH 50/2232] Accept non-\n line endings


On Windows, include_str brings in cxxbridge.h with \r\n line endings.

---

diff --git a/gen/include.rs b/gen/include.rs
index d4ff758..ef741af 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,8 +1,8 @@
 pub static HEADER: &str = include_str!("include/cxxbridge.h");
 
 pub fn get(guard: &str) -> &'static str {
-    let ifndef = format!("#ifndef {}\n", guard);
-    let endif = format!("#endif // {}\n", guard);
+    let ifndef = format!("#ifndef {}", guard);
+    let endif = format!("#endif // {}", guard);
     let begin = HEADER.find(&ifndef);
     let end = HEADER.find(&endif);
     if let (Some(begin), Some(end)) = (begin, end) {

From 44806f760fcf1605e07ceee9e05e63d42621685d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 24 2020 10:08:10 +0000
Subject: [PATCH 51/2232] Ignore windows build for now


---

diff --git a/.travis.yml b/.travis.yml
index 9534d50..b238cff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,3 +44,5 @@ matrix:
       script:
         - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
+  allow_failures:
+    - os: windows # https://github.com/dtolnay/cxx/issues/25

From 3fdda34015fcf79356918eab6f142ed5ec614651 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 00:47:56 +0000
Subject: [PATCH 52/2232] Pull in io_bazel_rules_rust update to support hyphens


---

diff --git a/WORKSPACE b/WORKSPACE
index e6f96d2..2feb345 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "3d3faa85e49ebf4d26c40075549a17739d636360064b94a9d481b37ace0add82",
-    strip_prefix = "rules_rust-6e87304c834c30b9c9f585cad19f30e7045281d7",
-    # Master branch as of 2020-02-22
-    url = "https://github.com/bazelbuild/rules_rust/archive/6e87304c834c30b9c9f585cad19f30e7045281d7.tar.gz",
+    sha256 = "b7ac870f4cab1cd7e56fd2cbe303f63d78d21cc1a6e3922f21887d373c090e20",
+    strip_prefix = "rules_rust-5a679d418955a122798f42c7bb67c55ca68a2493",
+    # Master branch as of 2020-02-24
+    url = "https://github.com/dtolnay/rules_rust/archive/5a679d418955a122798f42c7bb67c55ca68a2493.tar.gz",
 )
 
 http_archive(

From 671dff87d6f51ae3d39b73368044e5614636a9e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 00:48:03 +0000
Subject: [PATCH 53/2232] Preserve hyphens in third-party crate names


---

diff --git a/.travis.yml b/.travis.yml
index b238cff..0248fc3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,7 +42,7 @@ matrix:
         - cp third-party/Cargo.lock .
         - cargo vendor --versioned-dirs --locked third-party/vendor
       script:
-        - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
+        - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
   allow_failures:
     - os: windows # https://github.com/dtolnay/cxx/issues/25
diff --git a/BUILD b/BUILD
index b48c930..5d463b2 100644
--- a/BUILD
+++ b/BUILD
@@ -6,14 +6,14 @@ rust_library(
     data = ["src/gen/include/cxxbridge.h"],
     visibility = ["//visibility:public"],
     deps = [
-        ":core_lib",
-        ":cxxbridge_macro",
+        ":core-lib",
+        ":cxxbridge-macro",
         "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan",
-        "//third-party:codespan_reporting",
-        "//third-party:link_cplusplus",
-        "//third-party:proc_macro2",
+        "//third-party:codespan-reporting",
+        "//third-party:link-cplusplus",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
         "//third-party:thiserror",
@@ -28,8 +28,8 @@ rust_binary(
     deps = [
         "//third-party:anyhow",
         "//third-party:codespan",
-        "//third-party:codespan_reporting",
-        "//third-party:proc_macro2",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:structopt",
         "//third-party:syn",
@@ -46,17 +46,17 @@ cc_library(
 )
 
 cc_library(
-    name = "core_lib",
+    name = "core-lib",
     srcs = ["src/cxxbridge.cc"],
     hdrs = ["include/cxxbridge.h"],
 )
 
 rust_library(
-    name = "cxxbridge_macro",
+    name = "cxxbridge-macro",
     srcs = glob(["macro/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        "//third-party:proc_macro2",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
     ],
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index fb781b6..674b3d9 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -1,7 +1,7 @@
 load("//:build/rust.bzl", "rust_binary", "rust_library")
 
 rust_binary(
-    name = "demo_rs",
+    name = "demo-rs",
     srcs = glob(["src/**"]),
     deps = [
         ":gen",
diff --git a/third-party/BUILD b/third-party/BUILD
index ceae8e2..6792a98 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -30,7 +30,7 @@ rust_library(
     deps = [
         ":bitflags",
         ":textwrap",
-        ":unicode_width",
+        ":unicode-width",
     ],
 )
 
@@ -38,17 +38,17 @@ rust_library(
     name = "codespan",
     srcs = glob(["vendor/codespan-0.7.0/src/**"]),
     visibility = ["//visibility:public"],
-    deps = [":unicode_segmentation"],
+    deps = [":unicode-segmentation"],
 )
 
 rust_library(
-    name = "codespan_reporting",
+    name = "codespan-reporting",
     srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":codespan",
         ":termcolor",
-        ":unicode_width",
+        ":unicode-width",
     ],
 )
 
@@ -56,7 +56,7 @@ rust_library(
     name = "heck",
     srcs = glob(["vendor/heck-0.3.1/src/**"]),
     edition = "2015",
-    deps = [":unicode_segmentation"],
+    deps = [":unicode-segmentation"],
 )
 
 rust_library(
@@ -65,38 +65,38 @@ rust_library(
 )
 
 rust_library(
-    name = "link_cplusplus",
+    name = "link-cplusplus",
     srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
     visibility = ["//visibility:public"],
 )
 
 rust_library(
-    name = "proc_macro_error",
+    name = "proc-macro-error",
     srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
-        ":proc_macro2",
-        ":proc_macro_error_attr",
+        ":proc-macro2",
+        ":proc-macro-error-attr",
         ":quote",
         ":syn",
     ],
 )
 
 rust_library(
-    name = "proc_macro_error_attr",
+    name = "proc-macro-error-attr",
     srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":rustversion",
         ":syn",
-        ":syn_mid",
+        ":syn-mid",
     ],
 )
 
 rust_library(
-    name = "proc_macro2",
+    name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
     crate_features = [
         "proc-macro",
@@ -108,7 +108,7 @@ rust_library(
         "--cfg=wrap_proc_macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [":unicode_xid"],
+    deps = [":unicode-xid"],
 )
 
 rust_library(
@@ -116,7 +116,7 @@ rust_library(
     srcs = glob(["vendor/quote-1.0.2/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
-    deps = [":proc_macro2"],
+    deps = [":proc-macro2"],
 )
 
 rust_library(
@@ -125,7 +125,7 @@ rust_library(
     crate_type = "proc-macro",
     out_dir_tar = ":rustversion_buildscript_outdir",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
@@ -157,18 +157,18 @@ rust_library(
     deps = [
         ":clap",
         ":lazy_static",
-        ":structopt_derive",
+        ":structopt-derive",
     ],
 )
 
 rust_library(
-    name = "structopt_derive",
+    name = "structopt-derive",
     srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
-        ":proc_macro2",
-        ":proc_macro_error",
+        ":proc-macro2",
+        ":proc-macro-error",
         ":quote",
         ":syn",
     ],
@@ -187,17 +187,17 @@ rust_library(
     ],
     visibility = ["//visibility:public"],
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
-        ":unicode_xid",
+        ":unicode-xid",
     ],
 )
 
 rust_library(
-    name = "syn_mid",
+    name = "syn-mid",
     srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
@@ -211,39 +211,39 @@ rust_library(
 rust_library(
     name = "textwrap",
     srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
-    deps = [":unicode_width"],
+    deps = [":unicode-width"],
 )
 
 rust_library(
     name = "thiserror",
     srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
     visibility = ["//visibility:public"],
-    deps = [":thiserror_impl"],
+    deps = [":thiserror-impl"],
 )
 
 rust_library(
-    name = "thiserror_impl",
+    name = "thiserror-impl",
     srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
 )
 
 rust_library(
-    name = "unicode_segmentation",
+    name = "unicode-segmentation",
     srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
     edition = "2015",
 )
 
 rust_library(
-    name = "unicode_width",
+    name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
 )
 
 rust_library(
-    name = "unicode_xid",
+    name = "unicode-xid",
     srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
 )

From 7ce723cae039f91a86090efd231bbd8a3fcee5fd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 04:15:32 +0000
Subject: [PATCH 54/2232] Merge pull request #37 from dtolnay/hyphen


Preserve hyphens in bazel third-party crate names
---

diff --git a/.travis.yml b/.travis.yml
index b238cff..0248fc3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,7 +42,7 @@ matrix:
         - cp third-party/Cargo.lock .
         - cargo vendor --versioned-dirs --locked third-party/vendor
       script:
-        - bazel run demo-rs:demo_rs --verbose_failures --noshow_progress
+        - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
   allow_failures:
     - os: windows # https://github.com/dtolnay/cxx/issues/25
diff --git a/BUILD b/BUILD
index b48c930..5d463b2 100644
--- a/BUILD
+++ b/BUILD
@@ -6,14 +6,14 @@ rust_library(
     data = ["src/gen/include/cxxbridge.h"],
     visibility = ["//visibility:public"],
     deps = [
-        ":core_lib",
-        ":cxxbridge_macro",
+        ":core-lib",
+        ":cxxbridge-macro",
         "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan",
-        "//third-party:codespan_reporting",
-        "//third-party:link_cplusplus",
-        "//third-party:proc_macro2",
+        "//third-party:codespan-reporting",
+        "//third-party:link-cplusplus",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
         "//third-party:thiserror",
@@ -28,8 +28,8 @@ rust_binary(
     deps = [
         "//third-party:anyhow",
         "//third-party:codespan",
-        "//third-party:codespan_reporting",
-        "//third-party:proc_macro2",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:structopt",
         "//third-party:syn",
@@ -46,17 +46,17 @@ cc_library(
 )
 
 cc_library(
-    name = "core_lib",
+    name = "core-lib",
     srcs = ["src/cxxbridge.cc"],
     hdrs = ["include/cxxbridge.h"],
 )
 
 rust_library(
-    name = "cxxbridge_macro",
+    name = "cxxbridge-macro",
     srcs = glob(["macro/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        "//third-party:proc_macro2",
+        "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
     ],
diff --git a/WORKSPACE b/WORKSPACE
index e6f96d2..2feb345 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "3d3faa85e49ebf4d26c40075549a17739d636360064b94a9d481b37ace0add82",
-    strip_prefix = "rules_rust-6e87304c834c30b9c9f585cad19f30e7045281d7",
-    # Master branch as of 2020-02-22
-    url = "https://github.com/bazelbuild/rules_rust/archive/6e87304c834c30b9c9f585cad19f30e7045281d7.tar.gz",
+    sha256 = "b7ac870f4cab1cd7e56fd2cbe303f63d78d21cc1a6e3922f21887d373c090e20",
+    strip_prefix = "rules_rust-5a679d418955a122798f42c7bb67c55ca68a2493",
+    # Master branch as of 2020-02-24
+    url = "https://github.com/dtolnay/rules_rust/archive/5a679d418955a122798f42c7bb67c55ca68a2493.tar.gz",
 )
 
 http_archive(
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index fb781b6..674b3d9 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -1,7 +1,7 @@
 load("//:build/rust.bzl", "rust_binary", "rust_library")
 
 rust_binary(
-    name = "demo_rs",
+    name = "demo-rs",
     srcs = glob(["src/**"]),
     deps = [
         ":gen",
diff --git a/third-party/BUILD b/third-party/BUILD
index ceae8e2..6792a98 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -30,7 +30,7 @@ rust_library(
     deps = [
         ":bitflags",
         ":textwrap",
-        ":unicode_width",
+        ":unicode-width",
     ],
 )
 
@@ -38,17 +38,17 @@ rust_library(
     name = "codespan",
     srcs = glob(["vendor/codespan-0.7.0/src/**"]),
     visibility = ["//visibility:public"],
-    deps = [":unicode_segmentation"],
+    deps = [":unicode-segmentation"],
 )
 
 rust_library(
-    name = "codespan_reporting",
+    name = "codespan-reporting",
     srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":codespan",
         ":termcolor",
-        ":unicode_width",
+        ":unicode-width",
     ],
 )
 
@@ -56,7 +56,7 @@ rust_library(
     name = "heck",
     srcs = glob(["vendor/heck-0.3.1/src/**"]),
     edition = "2015",
-    deps = [":unicode_segmentation"],
+    deps = [":unicode-segmentation"],
 )
 
 rust_library(
@@ -65,38 +65,38 @@ rust_library(
 )
 
 rust_library(
-    name = "link_cplusplus",
+    name = "link-cplusplus",
     srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
     visibility = ["//visibility:public"],
 )
 
 rust_library(
-    name = "proc_macro_error",
+    name = "proc-macro-error",
     srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
-        ":proc_macro2",
-        ":proc_macro_error_attr",
+        ":proc-macro2",
+        ":proc-macro-error-attr",
         ":quote",
         ":syn",
     ],
 )
 
 rust_library(
-    name = "proc_macro_error_attr",
+    name = "proc-macro-error-attr",
     srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":rustversion",
         ":syn",
-        ":syn_mid",
+        ":syn-mid",
     ],
 )
 
 rust_library(
-    name = "proc_macro2",
+    name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
     crate_features = [
         "proc-macro",
@@ -108,7 +108,7 @@ rust_library(
         "--cfg=wrap_proc_macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [":unicode_xid"],
+    deps = [":unicode-xid"],
 )
 
 rust_library(
@@ -116,7 +116,7 @@ rust_library(
     srcs = glob(["vendor/quote-1.0.2/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
-    deps = [":proc_macro2"],
+    deps = [":proc-macro2"],
 )
 
 rust_library(
@@ -125,7 +125,7 @@ rust_library(
     crate_type = "proc-macro",
     out_dir_tar = ":rustversion_buildscript_outdir",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
@@ -157,18 +157,18 @@ rust_library(
     deps = [
         ":clap",
         ":lazy_static",
-        ":structopt_derive",
+        ":structopt-derive",
     ],
 )
 
 rust_library(
-    name = "structopt_derive",
+    name = "structopt-derive",
     srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
-        ":proc_macro2",
-        ":proc_macro_error",
+        ":proc-macro2",
+        ":proc-macro-error",
         ":quote",
         ":syn",
     ],
@@ -187,17 +187,17 @@ rust_library(
     ],
     visibility = ["//visibility:public"],
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
-        ":unicode_xid",
+        ":unicode-xid",
     ],
 )
 
 rust_library(
-    name = "syn_mid",
+    name = "syn-mid",
     srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
@@ -211,39 +211,39 @@ rust_library(
 rust_library(
     name = "textwrap",
     srcs = glob(["vendor/textwrap-0.11.0/src/**"]),
-    deps = [":unicode_width"],
+    deps = [":unicode-width"],
 )
 
 rust_library(
     name = "thiserror",
     srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
     visibility = ["//visibility:public"],
-    deps = [":thiserror_impl"],
+    deps = [":thiserror-impl"],
 )
 
 rust_library(
-    name = "thiserror_impl",
+    name = "thiserror-impl",
     srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
     crate_type = "proc-macro",
     deps = [
-        ":proc_macro2",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
 )
 
 rust_library(
-    name = "unicode_segmentation",
+    name = "unicode-segmentation",
     srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
     edition = "2015",
 )
 
 rust_library(
-    name = "unicode_width",
+    name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
 )
 
 rust_library(
-    name = "unicode_xid",
+    name = "unicode-xid",
     srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
 )

From fa1a2bdb5a93c6b174bfa3e21796462c73e4781f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 05:58:17 +0000
Subject: [PATCH 55/2232] Remove reliance on fs::canonicalize on Windows


---

diff --git a/src/paths.rs b/src/paths.rs
index f253939..e318664 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -44,7 +44,7 @@ fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
 fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
     let target_dir = target_dir()?;
     let mut outer = target_dir.parent().unwrap();
-    let original = original.canonicalize()?;
+    let original = canonicalize(original)?;
     loop {
         if let Ok(suffix) = original.strip_prefix(outer) {
             return Ok(suffix.to_owned());
@@ -71,7 +71,7 @@ pub(crate) fn include_dir() -> Result<PathBuf> {
 }
 
 fn target_dir() -> Result<PathBuf> {
-    let mut dir = out_dir()?.canonicalize()?;
+    let mut dir = out_dir().and_then(canonicalize)?;
     loop {
         if dir.ends_with("target") {
             return Ok(dir);
@@ -81,3 +81,17 @@ fn target_dir() -> Result<PathBuf> {
         }
     }
 }
+
+#[cfg(not(windows))]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    Ok(fs::canonicalize(path)?)
+}
+
+#[cfg(windows)]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
+    // unable to handle in includes. Use a poor approximation instead.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    Ok(env::current_dir()?.join(path))
+}

From 25221c110bba3d2da12b4ba03007b7c54ada5347 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 06:20:17 +0000
Subject: [PATCH 56/2232] Merge pull request #41 from dtolnay/canonicalize


Remove reliance on fs::canonicalize on Windows
---

diff --git a/src/paths.rs b/src/paths.rs
index f253939..e318664 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -44,7 +44,7 @@ fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
 fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
     let target_dir = target_dir()?;
     let mut outer = target_dir.parent().unwrap();
-    let original = original.canonicalize()?;
+    let original = canonicalize(original)?;
     loop {
         if let Ok(suffix) = original.strip_prefix(outer) {
             return Ok(suffix.to_owned());
@@ -71,7 +71,7 @@ pub(crate) fn include_dir() -> Result<PathBuf> {
 }
 
 fn target_dir() -> Result<PathBuf> {
-    let mut dir = out_dir()?.canonicalize()?;
+    let mut dir = out_dir().and_then(canonicalize)?;
     loop {
         if dir.ends_with("target") {
             return Ok(dir);
@@ -81,3 +81,17 @@ fn target_dir() -> Result<PathBuf> {
         }
     }
 }
+
+#[cfg(not(windows))]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    Ok(fs::canonicalize(path)?)
+}
+
+#[cfg(windows)]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
+    // unable to handle in includes. Use a poor approximation instead.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    Ok(env::current_dir()?.join(path))
+}

From c8a2494a0a10e236d053a18f5810594468763869 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 06:20:34 +0000
Subject: [PATCH 57/2232] Enable windows CI


---

diff --git a/.travis.yml b/.travis.yml
index 0248fc3..e3caff6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,5 +44,3 @@ matrix:
       script:
         - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
-  allow_failures:
-    - os: windows # https://github.com/dtolnay/cxx/issues/25

From b3d52389a826c9fa0486459aa39993a6e24a1bfa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 06:20:34 +0000
Subject: [PATCH 58/2232] Use platform's path separator when writing cxxbridge.h


---

diff --git a/src/lib.rs b/src/lib.rs
index 6f40124..4c0f3c9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -463,7 +463,7 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let mut build = paths::cc_build();
     build.file(&bridge_path);
 
-    let ref cxxbridge_h = paths::include_dir()?.join("cxxbridge/cxxbridge.h");
+    let ref cxxbridge_h = paths::include_dir()?.join("cxxbridge").join("cxxbridge.h");
     let _ = fs::create_dir_all(cxxbridge_h.parent().unwrap());
     let _ = fs::remove_file(cxxbridge_h);
     let _ = fs::write(cxxbridge_h, gen::include::HEADER);

From 764d5e90bb6e6838fef20658548201f45d97b2bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 06:39:41 +0000
Subject: [PATCH 59/2232] Merge pull request #42 from dtolnay/windows


Enable windows CI
---

diff --git a/.travis.yml b/.travis.yml
index 0248fc3..e3caff6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,5 +44,3 @@ matrix:
       script:
         - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
-  allow_failures:
-    - os: windows # https://github.com/dtolnay/cxx/issues/25

From 3e7ac51fc068f7a0baf69c1c717bb0762ac322b9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 07:18:12 +0000
Subject: [PATCH 60/2232] Add windows msvc build


---

diff --git a/.travis.yml b/.travis.yml
index e3caff6..aa158b7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,14 +10,22 @@ script:
 
 matrix:
   include:
-    - os: macos
-      rust: nightly
-    - os: windows
+    - name: macOS
+      os: macos
       rust: nightly
+    - name: Windows (gnu)
+      os: windows
+      rust: nightly-x86_64-pc-windows-gnu
       before_script:
         # windows is bad at symlinks
         - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
         - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+    - name: Windows (msvc)
+      os: windows
+      rust: nightly-x86_64-pc-windows-msvc
+      before_script:
+        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
+        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
     - name: Buck
       rust: nightly
       before_install:

From 089e479b228445b7b7a1db26e2355049039aee48 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 08:12:50 +0000
Subject: [PATCH 61/2232] Run buildifier to resort after hyphen conversion


---

diff --git a/third-party/BUILD b/third-party/BUILD
index 6792a98..e2f6d76 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -75,8 +75,8 @@ rust_library(
     srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
-        ":proc-macro2",
         ":proc-macro-error-attr",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],
@@ -167,8 +167,8 @@ rust_library(
     crate_type = "proc-macro",
     deps = [
         ":heck",
-        ":proc-macro2",
         ":proc-macro-error",
+        ":proc-macro2",
         ":quote",
         ":syn",
     ],

From 63576d458db8a10719c6b9c8a1f423624afa96e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 25 2020 08:13:25 +0000
Subject: [PATCH 62/2232] Move build -> tools/bazel


Fixes https://github.com/dtolnay/cxx/issues/45.

---

diff --git a/BUILD b/BUILD
index 5d463b2..0405df1 100644
--- a/BUILD
+++ b/BUILD
@@ -1,4 +1,4 @@
-load("//:build/rust.bzl", "rust_binary", "rust_library")
+load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_library(
     name = "cxx",
diff --git a/build/rust.bzl b/build/rust.bzl
deleted file mode 100644
index 3ef4d91..0000000
--- a/build/rust.bzl
+++ /dev/null
@@ -1,23 +0,0 @@
-load(
-    "@io_bazel_rules_rust//rust:rust.bzl",
-    _rust_binary = "rust_binary",
-    _rust_library = "rust_library",
-    _rust_test = "rust_test",
-)
-
-def rust_binary(edition = "2018", **kwargs):
-    _rust_binary(edition = edition, **kwargs)
-
-def third_party_rust_binary(rustc_flags = [], **kwargs):
-    rustc_flags = rustc_flags + ["--cap-lints=allow"]
-    rust_binary(rustc_flags = rustc_flags, **kwargs)
-
-def rust_library(edition = "2018", **kwargs):
-    _rust_library(edition = edition, **kwargs)
-
-def third_party_rust_library(rustc_flags = [], **kwargs):
-    rustc_flags = rustc_flags + ["--cap-lints=allow"]
-    rust_library(rustc_flags = rustc_flags, **kwargs)
-
-def rust_test(edition = "2018", **kwargs):
-    _rust_test(edition = edition, **kwargs)
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index 674b3d9..389ee58 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -1,4 +1,4 @@
-load("//:build/rust.bzl", "rust_binary", "rust_library")
+load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_binary(
     name = "demo-rs",
diff --git a/tests/BUILD b/tests/BUILD
index a88cde5..16825f6 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -1,4 +1,4 @@
-load("//:build/rust.bzl", "rust_library", "rust_test")
+load("//tools/bazel:rust.bzl", "rust_library", "rust_test")
 
 rust_test(
     name = "test",
diff --git a/third-party/BUILD b/third-party/BUILD
index e2f6d76..9af57d1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,5 +1,5 @@
 load(
-    "//:build/rust.bzl",
+    "//tools/bazel:rust.bzl",
     rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
diff --git a/tools/bazel/BUILD b/tools/bazel/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/bazel/BUILD
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
new file mode 100644
index 0000000..3ef4d91
--- /dev/null
+++ b/tools/bazel/rust.bzl
@@ -0,0 +1,23 @@
+load(
+    "@io_bazel_rules_rust//rust:rust.bzl",
+    _rust_binary = "rust_binary",
+    _rust_library = "rust_library",
+    _rust_test = "rust_test",
+)
+
+def rust_binary(edition = "2018", **kwargs):
+    _rust_binary(edition = edition, **kwargs)
+
+def third_party_rust_binary(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_binary(rustc_flags = rustc_flags, **kwargs)
+
+def rust_library(edition = "2018", **kwargs):
+    _rust_library(edition = edition, **kwargs)
+
+def third_party_rust_library(rustc_flags = [], **kwargs):
+    rustc_flags = rustc_flags + ["--cap-lints=allow"]
+    rust_library(rustc_flags = rustc_flags, **kwargs)
+
+def rust_test(edition = "2018", **kwargs):
+    _rust_test(edition = edition, **kwargs)

From 649337e12d79c2b275fb9b9e9266536844ffd1ae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 26 2020 02:11:20 +0000
Subject: [PATCH 63/2232] Move namespace alias to top of header for visibility


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 0bfe805..8061c28 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -4,6 +4,9 @@
 #include <iostream>
 #include <string>
 
+namespace cxxbridge01 {}
+namespace cxxbridge = cxxbridge01;
+
 namespace cxxbridge01 {
 
 class RustString final {
@@ -128,5 +131,3 @@ std::ostream &operator<<(std::ostream &os, const RustString &s);
 std::ostream &operator<<(std::ostream &os, const RustStr &s);
 
 } // namespace cxxbridge01
-
-namespace cxxbridge = cxxbridge01;

From e976487440df123b535b01821381352ff31d8d7d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 20:49:21 +0000
Subject: [PATCH 64/2232] Update third-party deps to drop rustversion


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 5c0e90d..0a5063f 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -67,7 +67,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.10/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -79,12 +79,11 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.10/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
         ":quote",
-        ":rustversion",
         ":syn",
         ":syn-mid",
     ],
@@ -92,7 +91,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.9/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -115,38 +114,8 @@ rust_library(
 )
 
 rust_library(
-    name = "rustversion",
-    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
-    mapped_srcs = {
-        ":rustversion-buildscript-run": "vendor/rustversion-1.0.2/src/generated",
-    },
-    proc_macro = True,
-    env = {
-        "OUT_DIR": "generated",
-    },
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_binary(
-    name = "rustversion-buildscript",
-    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
-    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
-)
-
-genrule(
-    name = "rustversion-buildscript-run",
-    cmd = "OUT_DIR=${OUT} $(exe :rustversion-buildscript)",
-    type = "build.rs",
-    out = ".",
-)
-
-rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.11/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":clap",
@@ -157,7 +126,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.4/src/**"]),
     proc_macro = True,
     deps = [
         ":heck",
@@ -170,7 +139,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.15/src/**"]),
+    srcs = glob(["vendor/syn-1.0.16/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 9af57d1..697c125 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.9/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.10/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -84,12 +84,11 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.9/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.10/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
         ":quote",
-        ":rustversion",
         ":syn",
         ":syn-mid",
     ],
@@ -97,7 +96,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.8/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.9/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -120,39 +119,8 @@ rust_library(
 )
 
 rust_library(
-    name = "rustversion",
-    srcs = glob(["vendor/rustversion-1.0.2/src/**"]),
-    crate_type = "proc-macro",
-    out_dir_tar = ":rustversion_buildscript_outdir",
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_binary(
-    name = "rustversion_buildscript",
-    srcs = glob(["vendor/rustversion-1.0.2/build/**"]),
-    crate_root = "vendor/rustversion-1.0.2/build/build.rs",
-)
-
-pkg_tar(
-    name = "rustversion_buildscript_outdir",
-    srcs = [":rustversion_buildscript_run"],
-    extension = "tar.gz",
-)
-
-genrule(
-    name = "rustversion_buildscript_run",
-    outs = ["version.rs"],
-    cmd = "OUT_DIR=$(@D) $(location :rustversion_buildscript)",
-    tools = [":rustversion_buildscript"],
-)
-
-rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.9/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.11/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
@@ -163,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.2/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.4/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
@@ -176,7 +144,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.15/src/**"]),
+    srcs = glob(["vendor/syn-1.0.16/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5f2a1ca..4e6cc7d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -147,9 +147,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
+checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
 dependencies = [
  "libc",
 ]
@@ -183,35 +183,35 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052b3c9af39c7e5e94245f820530487d19eb285faedcb40e0c3275132293f242"
+checksum = "8a857f7c61b149c868eb7e40311b48502fcc924744fb73191962748643336568"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "rustversion",
  "syn",
+ "version_check",
 ]
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d175bef481c7902e63e3165627123fff3502f06ac043d3ef42d08c1246da9253"
+checksum = "075d00534b62f176b55a48b68319be2f3fc05616d68ecd2bcb66bac0a49170e1"
 dependencies = [
  "proc-macro2",
  "quote",
- "rustversion",
  "syn",
  "syn-mid",
+ "version_check",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
+checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
 dependencies = [
  "unicode-xid",
 ]
@@ -281,9 +281,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.9"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1bcbed7d48956fcbb5d80c6b95aedb553513de0a1b451ea92679d999c010e98"
+checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
 dependencies = [
  "clap",
  "lazy_static",
@@ -292,9 +292,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.2"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "095064aa1f5b94d14e635d0a5684cf140c43ae40a0fd990708d38f5d669e5f64"
+checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -305,9 +305,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.15"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a0294dc449adc58bb6592fff1a23d3e5e6e235afc6a0ffca2657d19e7bbffe5"
+checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -411,6 +411,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
 
 [[package]]
+name = "version_check"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
+
+[[package]]
 name = "winapi"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From 7e219b8099c9372df5c564a506cbb83c1535d6b7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:14:55 +0000
Subject: [PATCH 65/2232] Use absolute qualified identifiers in generated C++


This avoids collision with the user's namespaces having the same name.

Less important in the context of the current names right now, but more
important after we move our public C++ API from cxxbridge:: to rust::.
In fact our example code already uses org::rust:: as the namespace,
inside of which a non-absolute rust:: would cause trouble.

---

diff --git a/gen/write.rs b/gen/write.rs
index ea6a812..9034a16 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -229,7 +229,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
-            write!(out, "std::move(*{})", arg.ident);
+            write!(out, "::std::move(*{})", arg.ident);
         } else {
             write!(out, "{}", arg.ident);
         }
@@ -365,7 +365,7 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "cxxbridge::RustStr::Repr "),
+        Some(Type::Str(_)) => write!(out, "::cxxbridge::RustStr::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -377,7 +377,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "cxxbridge::RustStr::Repr "),
+        Type::Str(_) => write!(out, "::cxxbridge::RustStr::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -400,17 +400,17 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I32) => write!(out, "int32_t"),
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
-            Some(CxxString) => write!(out, "std::string"),
-            Some(RustString) => write!(out, "cxxbridge::RustString"),
+            Some(CxxString) => write!(out, "::std::string"),
+            Some(RustString) => write!(out, "::cxxbridge::RustString"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
-            write!(out, "cxxbridge::RustBox<");
+            write!(out, "::cxxbridge::RustBox<");
             write_type(out, &ty.inner);
             write!(out, ">");
         }
         Type::UniquePtr(ptr) => {
-            write!(out, "std::unique_ptr<");
+            write!(out, "::std::unique_ptr<");
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
@@ -422,7 +422,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, " &");
         }
         Type::Str(_) => {
-            write!(out, "cxxbridge::RustStr");
+            write!(out, "::cxxbridge::RustStr");
         }
     }
 }
@@ -482,27 +482,27 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$uninit(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$uninit(::cxxbridge::RustBox<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$set_raw(cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$rust_box${}$set_raw(::cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$drop(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$drop(::cxxbridge::RustBox<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge01$rust_box${}$deref(const cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$rust_box${}$deref(const ::cxxbridge::RustBox<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge01$rust_box${}$deref_mut(cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$rust_box${}$deref_mut(::cxxbridge::RustBox<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
@@ -588,56 +588,56 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_UNIQUE_PTR_{}", instance);
     writeln!(
         out,
-        "static_assert(sizeof(std::unique_ptr<{}>) == sizeof(void *), \"\");",
+        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
         inner,
     );
     writeln!(
         out,
-        "static_assert(alignof(std::unique_ptr<{}>) == alignof(void *), \"\");",
+        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
         inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$null(std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  new (ptr) std::unique_ptr<{}>();", inner);
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$new(std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
         instance, inner, inner,
     );
     writeln!(
         out,
-        "  new (ptr) std::unique_ptr<{}>(new {}(std::move(*value)));",
+        "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
         inner, inner,
     );
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$raw(std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
-    writeln!(out, "  new (ptr) std::unique_ptr<{}>(raw);", inner);
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge01$unique_ptr${}$get(const std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge01$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge01$unique_ptr${}$release(std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge01$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$drop(std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge01$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");

From b92e66f4dc0ad413509dfc43c16e95697e077fa2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:37:15 +0000
Subject: [PATCH 66/2232] Support nested blocks in C++ emitter


---

diff --git a/gen/out.rs b/gen/out.rs
index d6735be..8d7499b 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -5,8 +5,8 @@ pub(crate) struct OutFile {
     pub header: bool,
     content: Vec<u8>,
     section_pending: bool,
-    block: &'static str,
-    block_pending: bool,
+    blocks: Vec<&'static str>,
+    blocks_pending: usize,
 }
 
 impl OutFile {
@@ -16,8 +16,8 @@ impl OutFile {
             header,
             content: Vec::new(),
             section_pending: false,
-            block: "",
-            block_pending: false,
+            blocks: Vec::new(),
+            blocks_pending: 0,
         }
     }
 
@@ -27,18 +27,18 @@ impl OutFile {
     }
 
     pub fn begin_block(&mut self, block: &'static str) {
-        self.block = block;
-        self.block_pending = true;
+        self.blocks.push(block);
+        self.blocks_pending += 1;
     }
 
     pub fn end_block(&mut self) {
-        if self.block_pending {
-            self.block_pending = false;
+        if self.blocks_pending > 0 {
+            self.blocks_pending -= 1;
         } else {
             self.content.extend_from_slice(b"} // ");
-            self.content.extend_from_slice(self.block.as_bytes());
+            self.content
+                .extend_from_slice(self.blocks.pop().unwrap().as_bytes());
             self.content.push(b'\n');
-            self.block = "";
             self.section_pending = true;
         }
     }
@@ -51,11 +51,13 @@ impl OutFile {
 impl Write for OutFile {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         if !s.is_empty() {
-            if self.block_pending {
+            if self.blocks_pending > 0 {
                 self.content.push(b'\n');
-                self.content.extend_from_slice(self.block.as_bytes());
-                self.content.extend_from_slice(b" {\n");
-                self.block_pending = false;
+                for block in &self.blocks[self.blocks.len() - self.blocks_pending..] {
+                    self.content.extend_from_slice(block.as_bytes());
+                    self.content.extend_from_slice(b" {\n");
+                }
+                self.blocks_pending = 0;
                 self.section_pending = false;
             } else if self.section_pending {
                 self.content.push(b'\n');

From d944446b9898a120b2f66a54ca86240e7189af9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:19 +0000
Subject: [PATCH 67/2232] Merge pull request #47 from dtolnay/nested


Support nested blocks in C++ emitter
---

diff --git a/gen/out.rs b/gen/out.rs
index d6735be..8d7499b 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -5,8 +5,8 @@ pub(crate) struct OutFile {
     pub header: bool,
     content: Vec<u8>,
     section_pending: bool,
-    block: &'static str,
-    block_pending: bool,
+    blocks: Vec<&'static str>,
+    blocks_pending: usize,
 }
 
 impl OutFile {
@@ -16,8 +16,8 @@ impl OutFile {
             header,
             content: Vec::new(),
             section_pending: false,
-            block: "",
-            block_pending: false,
+            blocks: Vec::new(),
+            blocks_pending: 0,
         }
     }
 
@@ -27,18 +27,18 @@ impl OutFile {
     }
 
     pub fn begin_block(&mut self, block: &'static str) {
-        self.block = block;
-        self.block_pending = true;
+        self.blocks.push(block);
+        self.blocks_pending += 1;
     }
 
     pub fn end_block(&mut self) {
-        if self.block_pending {
-            self.block_pending = false;
+        if self.blocks_pending > 0 {
+            self.blocks_pending -= 1;
         } else {
             self.content.extend_from_slice(b"} // ");
-            self.content.extend_from_slice(self.block.as_bytes());
+            self.content
+                .extend_from_slice(self.blocks.pop().unwrap().as_bytes());
             self.content.push(b'\n');
-            self.block = "";
             self.section_pending = true;
         }
     }
@@ -51,11 +51,13 @@ impl OutFile {
 impl Write for OutFile {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         if !s.is_empty() {
-            if self.block_pending {
+            if self.blocks_pending > 0 {
                 self.content.push(b'\n');
-                self.content.extend_from_slice(self.block.as_bytes());
-                self.content.extend_from_slice(b" {\n");
-                self.block_pending = false;
+                for block in &self.blocks[self.blocks.len() - self.blocks_pending..] {
+                    self.content.extend_from_slice(block.as_bytes());
+                    self.content.extend_from_slice(b" {\n");
+                }
+                self.blocks_pending = 0;
                 self.section_pending = false;
             } else if self.section_pending {
                 self.content.push(b'\n');

From 560821697943b62ccce25c8f75b226e355ad6835 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:28 +0000
Subject: [PATCH 68/2232] Rename C++ RustString to String


---

diff --git a/README.md b/README.md
index e7eaa3a..406518b 100644
--- a/README.md
+++ b/README.md
@@ -298,7 +298,7 @@ of functions.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-<tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
+<tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
diff --git a/gen/write.rs b/gen/write.rs
index 9034a16..d55d4ac 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -401,7 +401,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
             Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::cxxbridge::RustString"),
+            Some(RustString) => write!(out, "::cxxbridge::String"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 8061c28..395ec18 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -9,16 +9,16 @@ namespace cxxbridge = cxxbridge01;
 
 namespace cxxbridge01 {
 
-class RustString final {
+class String final {
 public:
-  RustString() noexcept;
-  RustString(const RustString &other) noexcept;
-  RustString(RustString &&other) noexcept;
-  RustString(const char *s);
-  RustString(const std::string &s);
-  RustString &operator=(const RustString &other) noexcept;
-  RustString &operator=(RustString &&other) noexcept;
-  ~RustString() noexcept;
+  String() noexcept;
+  String(const String &other) noexcept;
+  String(String &&other) noexcept;
+  String(const char *s);
+  String(const std::string &s);
+  String &operator=(const String &other) noexcept;
+  String &operator=(String &&other) noexcept;
+  ~String() noexcept;
   operator std::string() const;
 
   // Note: no null terminator.
@@ -127,7 +127,7 @@ private:
 };
 #endif // CXXBRIDGE01_RUST_BOX
 
-std::ostream &operator<<(std::ostream &os, const RustString &s);
+std::ostream &operator<<(std::ostream &os, const String &s);
 std::ostream &operator<<(std::ostream &os, const RustStr &s);
 
 } // namespace cxxbridge01
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index a502d20..1134c6b 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -14,16 +14,16 @@ size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
-// RustString
-void cxxbridge01$rust_string$new(cxxbridge::RustString *self) noexcept;
-void cxxbridge01$rust_string$clone(cxxbridge::RustString *self,
-                                   const cxxbridge::RustString &other) noexcept;
-bool cxxbridge01$rust_string$from(cxxbridge::RustString *self, const char *ptr,
+// cxxbridge::String
+void cxxbridge01$rust_string$new(cxxbridge::String *self) noexcept;
+void cxxbridge01$rust_string$clone(cxxbridge::String *self,
+                                   const cxxbridge::String &other) noexcept;
+bool cxxbridge01$rust_string$from(cxxbridge::String *self, const char *ptr,
                                   size_t len) noexcept;
-void cxxbridge01$rust_string$drop(cxxbridge::RustString *self) noexcept;
+void cxxbridge01$rust_string$drop(cxxbridge::String *self) noexcept;
 const char *
-cxxbridge01$rust_string$ptr(const cxxbridge::RustString *self) noexcept;
-size_t cxxbridge01$rust_string$len(const cxxbridge::RustString *self) noexcept;
+cxxbridge01$rust_string$ptr(const cxxbridge::String *self) noexcept;
+size_t cxxbridge01$rust_string$len(const cxxbridge::String *self) noexcept;
 
 // RustStr
 bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
@@ -31,39 +31,39 @@ bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
 
 namespace cxxbridge01 {
 
-RustString::RustString() noexcept { cxxbridge01$rust_string$new(this); }
+String::String() noexcept { cxxbridge01$rust_string$new(this); }
 
-RustString::RustString(const RustString &other) noexcept {
+String::String(const String &other) noexcept {
   cxxbridge01$rust_string$clone(this, other);
 }
 
-RustString::RustString(RustString &&other) noexcept {
+String::String(String &&other) noexcept {
   this->repr = other.repr;
   cxxbridge01$rust_string$new(&other);
 }
 
-RustString::RustString(const char *s) {
+String::String(const char *s) {
   auto len = strlen(s);
   if (!cxxbridge01$rust_string$from(this, s, len)) {
-    throw std::invalid_argument("data for RustString is not utf-8");
+    throw std::invalid_argument("data for cxxbridge::String is not utf-8");
   }
 }
 
-RustString::RustString(const std::string &s) {
+String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
   if (!cxxbridge01$rust_string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for RustString is not utf-8");
+    throw std::invalid_argument("data for cxxbridge::String is not utf-8");
   }
 }
 
-RustString::~RustString() noexcept { cxxbridge01$rust_string$drop(this); }
+String::~String() noexcept { cxxbridge01$rust_string$drop(this); }
 
-RustString::operator std::string() const {
+String::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-RustString &RustString::operator=(const RustString &other) noexcept {
+String &String::operator=(const String &other) noexcept {
   if (this != &other) {
     cxxbridge01$rust_string$drop(this);
     cxxbridge01$rust_string$clone(this, other);
@@ -71,7 +71,7 @@ RustString &RustString::operator=(const RustString &other) noexcept {
   return *this;
 }
 
-RustString &RustString::operator=(RustString &&other) noexcept {
+String &String::operator=(String &&other) noexcept {
   if (this != &other) {
     cxxbridge01$rust_string$drop(this);
     this->repr = other.repr;
@@ -80,19 +80,19 @@ RustString &RustString::operator=(RustString &&other) noexcept {
   return *this;
 }
 
-const char *RustString::data() const noexcept {
+const char *String::data() const noexcept {
   return cxxbridge01$rust_string$ptr(this);
 }
 
-size_t RustString::size() const noexcept {
+size_t String::size() const noexcept {
   return cxxbridge01$rust_string$len(this);
 }
 
-size_t RustString::length() const noexcept {
+size_t String::length() const noexcept {
   return cxxbridge01$rust_string$len(this);
 }
 
-std::ostream &operator<<(std::ostream &os, const RustString &s) {
+std::ostream &operator<<(std::ostream &os, const String &s) {
   os.write(s.data(), s.size());
   return os;
 }
diff --git a/src/lib.rs b/src/lib.rs
index 4c0f3c9..69f9447 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -302,7 +302,7 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-//! <tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
+//! <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d27df41..60f6141 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -24,7 +24,7 @@ cxxbridge::RustStr c_return_str(const Shared &shared) {
   return "2020";
 }
 
-cxxbridge::RustString c_return_rust_string() { return "2020"; }
+cxxbridge::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
@@ -67,7 +67,7 @@ void c_take_str(cxxbridge::RustStr s) {
   }
 }
 
-void c_take_rust_string(cxxbridge::RustString s) {
+void c_take_rust_string(cxxbridge::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -100,7 +100,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(cxxbridge::RustStr("2020"));
-  // TODO r_take_rust_string(cxxbridge::RustString("2020"));
+  // TODO r_take_rust_string(cxxbridge::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 87aac67..fa4e3c8 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -23,7 +23,7 @@ cxxbridge::RustBox<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 cxxbridge::RustStr c_return_str(const Shared &shared);
-cxxbridge::RustString c_return_rust_string();
+cxxbridge::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
@@ -33,7 +33,7 @@ void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_str(cxxbridge::RustStr s);
-void c_take_rust_string(cxxbridge::RustString s);
+void c_take_rust_string(cxxbridge::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
 } // namespace tests

From 09dbe75a5dac7bde0d18ccf659d898d6b5007c61 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:28 +0000
Subject: [PATCH 69/2232] Rename C++ RustStr to Str


---

diff --git a/README.md b/README.md
index 406518b..551bc7c 100644
--- a/README.md
+++ b/README.md
@@ -299,7 +299,7 @@ of functions.
 <table>
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
-<tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
+<tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 500ee3a..3900572 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,7 +9,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::RustStr appname) {
+std::unique_ptr<ThingC> make_demo(cxxbridge::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 417edfb..d41ea7a 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -16,7 +16,7 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::RustStr appname);
+std::unique_ptr<ThingC> make_demo(cxxbridge::Str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
diff --git a/gen/write.rs b/gen/write.rs
index d55d4ac..063a674 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -365,7 +365,7 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::cxxbridge::RustStr::Repr "),
+        Some(Type::Str(_)) => write!(out, "::cxxbridge::Str::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -377,7 +377,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::cxxbridge::RustStr::Repr "),
+        Type::Str(_) => write!(out, "::cxxbridge::Str::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -422,7 +422,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, " &");
         }
         Type::Str(_) => {
-            write!(out, "::cxxbridge::RustStr");
+            write!(out, "::cxxbridge::Str");
         }
     }
 }
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 395ec18..fb00bb4 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -31,14 +31,14 @@ private:
   std::array<uintptr_t, 3> repr;
 };
 
-class RustStr final {
+class Str final {
 public:
-  RustStr() noexcept;
-  RustStr(const char *s);
-  RustStr(const std::string &s);
-  RustStr(std::string &&s) = delete;
-  RustStr(const RustStr &other) noexcept;
-  RustStr &operator=(RustStr other) noexcept;
+  Str() noexcept;
+  Str(const char *s);
+  Str(const std::string &s);
+  Str(std::string &&s) = delete;
+  Str(const Str &other) noexcept;
+  Str &operator=(Str other) noexcept;
   operator std::string() const;
 
   // Note: no null terminator.
@@ -54,7 +54,7 @@ public:
     const char *ptr;
     size_t len;
   };
-  RustStr(Repr repr) noexcept;
+  Str(Repr repr) noexcept;
   operator Repr() noexcept;
 
 private:
@@ -128,6 +128,6 @@ private:
 #endif // CXXBRIDGE01_RUST_BOX
 
 std::ostream &operator<<(std::ostream &os, const String &s);
-std::ostream &operator<<(std::ostream &os, const RustStr &s);
+std::ostream &operator<<(std::ostream &os, const Str &s);
 
 } // namespace cxxbridge01
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 1134c6b..da0b450 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -25,7 +25,7 @@ const char *
 cxxbridge01$rust_string$ptr(const cxxbridge::String *self) noexcept;
 size_t cxxbridge01$rust_string$len(const cxxbridge::String *self) noexcept;
 
-// RustStr
+// cxxbridge::Str
 bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
@@ -97,43 +97,43 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-RustStr::RustStr() noexcept
+Str::Str() noexcept
     : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
-RustStr::RustStr(const char *s) : repr(Repr{s, strlen(s)}) {
+Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for RustStr is not utf-8");
+    throw std::invalid_argument("data for cxxbridge::Str is not utf-8");
   }
 }
 
-RustStr::RustStr(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for RustStr is not utf-8");
+    throw std::invalid_argument("data for cxxbridge::Str is not utf-8");
   }
 }
 
-RustStr::RustStr(const RustStr &) noexcept = default;
+Str::Str(const Str &) noexcept = default;
 
-RustStr &RustStr::operator=(RustStr other) noexcept {
+Str &Str::operator=(Str other) noexcept {
   this->repr = other.repr;
   return *this;
 }
 
-RustStr::operator std::string() const {
+Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-const char *RustStr::data() const noexcept { return this->repr.ptr; }
+const char *Str::data() const noexcept { return this->repr.ptr; }
 
-size_t RustStr::size() const noexcept { return this->repr.len; }
+size_t Str::size() const noexcept { return this->repr.len; }
 
-size_t RustStr::length() const noexcept { return this->repr.len; }
+size_t Str::length() const noexcept { return this->repr.len; }
 
-RustStr::RustStr(Repr repr_) noexcept : repr(repr_) {}
+Str::Str(Repr repr_) noexcept : repr(repr_) {}
 
-RustStr::operator Repr() noexcept { return this->repr; }
+Str::operator Repr() noexcept { return this->repr; }
 
-std::ostream &operator<<(std::ostream &os, const RustStr &s) {
+std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;
 }
diff --git a/src/lib.rs b/src/lib.rs
index 69f9447..2f21166 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -303,7 +303,7 @@
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
-//! <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
+//! <tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 60f6141..a5305ef 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -19,7 +19,7 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
-cxxbridge::RustStr c_return_str(const Shared &shared) {
+cxxbridge::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
@@ -61,7 +61,7 @@ void c_take_ref_c(const C &c) {
   }
 }
 
-void c_take_str(cxxbridge::RustStr s) {
+void c_take_str(cxxbridge::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -99,7 +99,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
-  r_take_str(cxxbridge::RustStr("2020"));
+  r_take_str(cxxbridge::Str("2020"));
   // TODO r_take_rust_string(cxxbridge::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fa4e3c8..fe3d966 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -22,7 +22,7 @@ Shared c_return_shared();
 cxxbridge::RustBox<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
-cxxbridge::RustStr c_return_str(const Shared &shared);
+cxxbridge::Str c_return_str(const Shared &shared);
 cxxbridge::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
@@ -32,7 +32,7 @@ void c_take_box(cxxbridge::RustBox<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
-void c_take_str(cxxbridge::RustStr s);
+void c_take_str(cxxbridge::Str s);
 void c_take_rust_string(cxxbridge::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 

From 324437a263a6b32149abf7133e96d437865a1fec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:29 +0000
Subject: [PATCH 70/2232] Rename C++ RustBox to Box


---

diff --git a/README.md b/README.md
index 551bc7c..27c0c83 100644
--- a/README.md
+++ b/README.md
@@ -301,7 +301,7 @@ of functions.
 <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-<tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td>Box&lt;T&gt;</td><td>cxxbridge::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td></td><td></td><td></td></tr>
 </table>
diff --git a/gen/write.rs b/gen/write.rs
index 063a674..31eee36 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -405,7 +405,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
-            write!(out, "::cxxbridge::RustBox<");
+            write!(out, "::cxxbridge::Box<");
             write_type(out, &ty.inner);
             write!(out, ">");
         }
@@ -482,27 +482,27 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$uninit(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$uninit(::cxxbridge::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$set_raw(::cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$rust_box${}$set_raw(::cxxbridge::Box<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$drop(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$drop(::cxxbridge::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge01$rust_box${}$deref(const ::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$rust_box${}$deref(const ::cxxbridge::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge01$rust_box${}$deref_mut(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$rust_box${}$deref_mut(::cxxbridge::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
@@ -518,7 +518,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let instance = inner.replace("::", "$");
 
     writeln!(out, "template <>");
-    writeln!(out, "void RustBox<{}>::uninit() noexcept {{", inner);
+    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$uninit(this);",
@@ -529,7 +529,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "void RustBox<{}>::set_raw({} *raw) noexcept {{",
+        "void Box<{}>::set_raw({} *raw) noexcept {{",
         inner, inner,
     );
     writeln!(
@@ -540,7 +540,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "void RustBox<{}>::drop() noexcept {{", inner);
+    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$drop(this);",
@@ -551,7 +551,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "const {} *RustBox<{}>::deref() const noexcept {{",
+        "const {} *Box<{}>::deref() const noexcept {{",
         inner, inner,
     );
     writeln!(
@@ -562,11 +562,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(
-        out,
-        "{} *RustBox<{}>::deref_mut() noexcept {{",
-        inner, inner,
-    );
+    writeln!(out, "{} *Box<{}>::deref_mut() noexcept {{", inner, inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$deref_mut(this);",
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index fb00bb4..2ff3d20 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -63,15 +63,15 @@ private:
 
 #ifndef CXXBRIDGE01_RUST_BOX
 #define CXXBRIDGE01_RUST_BOX
-template <typename T> class RustBox final {
+template <typename T> class Box final {
 public:
-  RustBox(const RustBox &other) : RustBox(*other) {}
-  RustBox(RustBox &&other) noexcept : repr(other.repr) { other.repr = 0; }
-  RustBox(const T &val) {
+  Box(const Box &other) : Box(*other) {}
+  Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
+  Box(const T &val) {
     this->uninit();
     ::new (this->deref_mut()) T(val);
   }
-  RustBox &operator=(const RustBox &other) {
+  Box &operator=(const Box &other) {
     if (this != &other) {
       if (this->repr) {
         **this = *other;
@@ -82,7 +82,7 @@ public:
     }
     return *this;
   }
-  RustBox &operator=(RustBox &&other) noexcept {
+  Box &operator=(Box &&other) noexcept {
     if (this->repr) {
       this->drop();
     }
@@ -90,7 +90,7 @@ public:
     other.repr = 0;
     return *this;
   }
-  ~RustBox() noexcept {
+  ~Box() noexcept {
     if (this->repr) {
       this->drop();
     }
@@ -103,8 +103,8 @@ public:
 
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
-  static RustBox from_raw(T *raw) noexcept {
-    RustBox box;
+  static Box from_raw(T *raw) noexcept {
+    Box box;
     box.set_raw(raw);
     return box;
   }
@@ -116,7 +116,7 @@ public:
   }
 
 private:
-  RustBox() noexcept {}
+  Box() noexcept {}
   void uninit() noexcept;
   void set_raw(T *) noexcept;
   T *get_raw() noexcept;
diff --git a/src/lib.rs b/src/lib.rs
index 2f21166..abf7321 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -305,7 +305,7 @@
 //! <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-//! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a5305ef..5800f29 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -42,7 +42,7 @@ void c_take_shared(Shared shared) {
   }
 }
 
-void c_take_box(cxxbridge::RustBox<R> r) {
+void c_take_box(cxxbridge::Box<R> r) {
   (void)r;
   cxx_test_suite_set_correct();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fe3d966..3600eb6 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,7 +19,7 @@ private:
 
 size_t c_return_primitive();
 Shared c_return_shared();
-cxxbridge::RustBox<R> c_return_box();
+cxxbridge::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 cxxbridge::Str c_return_str(const Shared &shared);
@@ -28,7 +28,7 @@ std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
-void c_take_box(cxxbridge::RustBox<R> r);
+void c_take_box(cxxbridge::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);

From 750755e55771dca2674a6bd5a2a5a59b86f0d8f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:29 +0000
Subject: [PATCH 71/2232] Rename namespace to rust::inline cxxbridge01


---

diff --git a/README.md b/README.md
index 27c0c83..07ea91e 100644
--- a/README.md
+++ b/README.md
@@ -298,10 +298,10 @@ of functions.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-<tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
-<tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
+<tr><td>String</td><td>rust::String</td><td></td></tr>
+<tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-<tr><td>Box&lt;T&gt;</td><td>cxxbridge::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td></td><td></td><td></td></tr>
 </table>
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 3900572..79340eb 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,7 +9,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::Str appname) {
+std::unique_ptr<ThingC> make_demo(::rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index d41ea7a..aa417c7 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -16,7 +16,7 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::Str appname);
+std::unique_ptr<ThingC> make_demo(::rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
diff --git a/gen/write.rs b/gen/write.rs
index 31eee36..a2c1b7a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -21,21 +21,11 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
     write_includes(out, types);
     write_include_cxxbridge(out, types);
 
-    if !header {
-        out.next_section();
-        write_namespace_alias(out, types);
-    }
-
     out.next_section();
     for name in &namespace {
         writeln!(out, "namespace {} {{", name);
     }
 
-    if header {
-        out.next_section();
-        write_namespace_alias(out, types);
-    }
-
     out.next_section();
     for api in apis {
         match api {
@@ -125,7 +115,8 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
 
-    out.begin_block("namespace cxxbridge01");
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge01");
     if needs_rust_box {
         writeln!(out, "// #include \"cxxbridge.h\"");
         for line in include::get("CXXBRIDGE01_RUST_BOX").lines() {
@@ -135,20 +126,7 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
     out.end_block();
-}
-
-fn write_namespace_alias(out: &mut OutFile, types: &Types) {
-    let mut needs_namespace_alias = false;
-    for ty in types {
-        if let Type::RustBox(_) = ty {
-            needs_namespace_alias = true;
-            break;
-        }
-    }
-
-    if needs_namespace_alias {
-        writeln!(out, "namespace cxxbridge = cxxbridge01;");
-    }
+    out.end_block();
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
@@ -365,7 +343,7 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::cxxbridge::Str::Repr "),
+        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -377,7 +355,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::cxxbridge::Str::Repr "),
+        Type::Str(_) => write!(out, "::rust::Str::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -401,11 +379,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
             Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::cxxbridge::String"),
+            Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
-            write!(out, "::cxxbridge::Box<");
+            write!(out, "::rust::Box<");
             write_type(out, &ty.inner);
             write!(out, ">");
         }
@@ -422,7 +400,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, " &");
         }
         Type::Str(_) => {
-            write!(out, "::cxxbridge::Str");
+            write!(out, "::rust::Str");
         }
     }
 }
@@ -458,7 +436,8 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     }
     out.end_block();
 
-    out.begin_block("namespace cxxbridge01");
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge01");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -467,6 +446,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         }
     }
     out.end_block();
+    out.end_block();
 }
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
@@ -482,27 +462,27 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$uninit(::cxxbridge::Box<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$set_raw(::cxxbridge::Box<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$rust_box${}$set_raw(::rust::Box<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$drop(::cxxbridge::Box<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge01$rust_box${}$deref(const ::cxxbridge::Box<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$rust_box${}$deref(const ::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge01$rust_box${}$deref_mut(::cxxbridge::Box<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$rust_box${}$deref_mut(::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 2ff3d20..a668a66 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -4,10 +4,8 @@
 #include <iostream>
 #include <string>
 
-namespace cxxbridge01 {}
-namespace cxxbridge = cxxbridge01;
-
-namespace cxxbridge01 {
+namespace rust {
+inline namespace cxxbridge01 {
 
 class String final {
 public:
@@ -130,4 +128,5 @@ private:
 std::ostream &operator<<(std::ostream &os, const String &s);
 std::ostream &operator<<(std::ostream &os, const Str &s);
 
-} // namespace cxxbridge01
+} // inline namespace cxxbridge01
+} // namespace rust
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index da0b450..c139688 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -3,8 +3,6 @@
 #include <memory>
 #include <stdexcept>
 
-namespace cxxbridge = cxxbridge01;
-
 extern "C" {
 const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -14,22 +12,23 @@ size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
-// cxxbridge::String
-void cxxbridge01$rust_string$new(cxxbridge::String *self) noexcept;
-void cxxbridge01$rust_string$clone(cxxbridge::String *self,
-                                   const cxxbridge::String &other) noexcept;
-bool cxxbridge01$rust_string$from(cxxbridge::String *self, const char *ptr,
+// rust::String
+void cxxbridge01$rust_string$new(rust::String *self) noexcept;
+void cxxbridge01$rust_string$clone(rust::String *self,
+                                   const rust::String &other) noexcept;
+bool cxxbridge01$rust_string$from(rust::String *self, const char *ptr,
                                   size_t len) noexcept;
-void cxxbridge01$rust_string$drop(cxxbridge::String *self) noexcept;
+void cxxbridge01$rust_string$drop(rust::String *self) noexcept;
 const char *
-cxxbridge01$rust_string$ptr(const cxxbridge::String *self) noexcept;
-size_t cxxbridge01$rust_string$len(const cxxbridge::String *self) noexcept;
+cxxbridge01$rust_string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge01$rust_string$len(const rust::String *self) noexcept;
 
-// cxxbridge::Str
+// rust::Str
 bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
-namespace cxxbridge01 {
+namespace rust {
+inline namespace cxxbridge01 {
 
 String::String() noexcept { cxxbridge01$rust_string$new(this); }
 
@@ -45,7 +44,7 @@ String::String(String &&other) noexcept {
 String::String(const char *s) {
   auto len = strlen(s);
   if (!cxxbridge01$rust_string$from(this, s, len)) {
-    throw std::invalid_argument("data for cxxbridge::String is not utf-8");
+    throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
@@ -53,7 +52,7 @@ String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
   if (!cxxbridge01$rust_string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for cxxbridge::String is not utf-8");
+    throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
@@ -102,13 +101,13 @@ Str::Str() noexcept
 
 Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for cxxbridge::Str is not utf-8");
+    throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for cxxbridge::Str is not utf-8");
+    throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
@@ -138,7 +137,8 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
-} // namespace cxxbridge01
+} // inline namespace cxxbridge01
+} // namespace rust
 
 extern "C" {
 void cxxbridge01$unique_ptr$std$string$null(
diff --git a/src/lib.rs b/src/lib.rs
index abf7321..006159a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -302,10 +302,10 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-//! <tr><td>String</td><td>cxxbridge::String</td><td></td></tr>
-//! <tr><td>&amp;str</td><td>cxxbridge::Str</td><td></td></tr>
+//! <tr><td>String</td><td>rust::String</td><td></td></tr>
+//! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-//! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 5800f29..65640df 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -19,12 +19,12 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
-cxxbridge::Str c_return_str(const Shared &shared) {
+rust::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
 
-cxxbridge::String c_return_rust_string() { return "2020"; }
+rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
@@ -42,7 +42,7 @@ void c_take_shared(Shared shared) {
   }
 }
 
-void c_take_box(cxxbridge::Box<R> r) {
+void c_take_box(rust::Box<R> r) {
   (void)r;
   cxx_test_suite_set_correct();
 }
@@ -61,13 +61,13 @@ void c_take_ref_c(const C &c) {
   }
 }
 
-void c_take_str(cxxbridge::Str s) {
+void c_take_str(rust::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_rust_string(cxxbridge::String s) {
+void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -99,8 +99,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
-  r_take_str(cxxbridge::Str("2020"));
-  // TODO r_take_rust_string(cxxbridge::String("2020"));
+  r_take_str(rust::Str("2020"));
+  // TODO r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3600eb6..f41cc5e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,21 +19,21 @@ private:
 
 size_t c_return_primitive();
 Shared c_return_shared();
-cxxbridge::Box<R> c_return_box();
+rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
-cxxbridge::Str c_return_str(const Shared &shared);
-cxxbridge::String c_return_rust_string();
+rust::Str c_return_str(const Shared &shared);
+rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
-void c_take_box(cxxbridge::Box<R> r);
+void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
-void c_take_str(cxxbridge::Str s);
-void c_take_rust_string(cxxbridge::String s);
+void c_take_str(rust::Str s);
+void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
 } // namespace tests

From aa17a5acbb8c3bdfdbfa5f2ba6cdcb03718ffcf4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 21:47:29 +0000
Subject: [PATCH 72/2232] Rename example's namespace to org::example


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 79340eb..b975e88 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -3,13 +3,13 @@
 #include <iostream>
 
 namespace org {
-namespace rust {
+namespace example {
 
 ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(::rust::Str appname) {
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
@@ -17,5 +17,5 @@ const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
 void do_thing(SharedThing state) { print_r(*state.y); }
 
-} // namespace rust
+} // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index aa417c7..a579986 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -4,7 +4,7 @@
 #include <string>
 
 namespace org {
-namespace rust {
+namespace example {
 
 class ThingC {
 public:
@@ -16,9 +16,9 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(::rust::Str appname);
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
-} // namespace rust
+} // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index dba4727..66dfc79 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -1,4 +1,4 @@
-#[cxx::bridge(namespace = org::rust)]
+#[cxx::bridge(namespace = org::example)]
 mod ffi {
     struct SharedThing {
         z: i32,

From e3bd6abf480343b3071e1ada61b9fc50cbf84913 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:00:40 +0000
Subject: [PATCH 73/2232] Merge pull request #48 from dtolnay/namespace


Better use of namespaces
---

diff --git a/README.md b/README.md
index e7eaa3a..07ea91e 100644
--- a/README.md
+++ b/README.md
@@ -298,10 +298,10 @@ of functions.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-<tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
-<tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
+<tr><td>String</td><td>rust::String</td><td></td></tr>
+<tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-<tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td></td><td></td><td></td></tr>
 </table>
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 500ee3a..b975e88 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -3,13 +3,13 @@
 #include <iostream>
 
 namespace org {
-namespace rust {
+namespace example {
 
 ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::RustStr appname) {
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
@@ -17,5 +17,5 @@ const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
 void do_thing(SharedThing state) { print_r(*state.y); }
 
-} // namespace rust
+} // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 417edfb..a579986 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -4,7 +4,7 @@
 #include <string>
 
 namespace org {
-namespace rust {
+namespace example {
 
 class ThingC {
 public:
@@ -16,9 +16,9 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(cxxbridge::RustStr appname);
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
-} // namespace rust
+} // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index dba4727..66dfc79 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -1,4 +1,4 @@
-#[cxx::bridge(namespace = org::rust)]
+#[cxx::bridge(namespace = org::example)]
 mod ffi {
     struct SharedThing {
         z: i32,
diff --git a/gen/write.rs b/gen/write.rs
index 9034a16..a2c1b7a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -21,21 +21,11 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
     write_includes(out, types);
     write_include_cxxbridge(out, types);
 
-    if !header {
-        out.next_section();
-        write_namespace_alias(out, types);
-    }
-
     out.next_section();
     for name in &namespace {
         writeln!(out, "namespace {} {{", name);
     }
 
-    if header {
-        out.next_section();
-        write_namespace_alias(out, types);
-    }
-
     out.next_section();
     for api in apis {
         match api {
@@ -125,7 +115,8 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
 
-    out.begin_block("namespace cxxbridge01");
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge01");
     if needs_rust_box {
         writeln!(out, "// #include \"cxxbridge.h\"");
         for line in include::get("CXXBRIDGE01_RUST_BOX").lines() {
@@ -135,20 +126,7 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
     out.end_block();
-}
-
-fn write_namespace_alias(out: &mut OutFile, types: &Types) {
-    let mut needs_namespace_alias = false;
-    for ty in types {
-        if let Type::RustBox(_) = ty {
-            needs_namespace_alias = true;
-            break;
-        }
-    }
-
-    if needs_namespace_alias {
-        writeln!(out, "namespace cxxbridge = cxxbridge01;");
-    }
+    out.end_block();
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
@@ -365,7 +343,7 @@ fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types)
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::cxxbridge::RustStr::Repr "),
+        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -377,7 +355,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::cxxbridge::RustStr::Repr "),
+        Type::Str(_) => write!(out, "::rust::Str::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -401,11 +379,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
             Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::cxxbridge::RustString"),
+            Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
-            write!(out, "::cxxbridge::RustBox<");
+            write!(out, "::rust::Box<");
             write_type(out, &ty.inner);
             write!(out, ">");
         }
@@ -422,7 +400,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, " &");
         }
         Type::Str(_) => {
-            write!(out, "::cxxbridge::RustStr");
+            write!(out, "::rust::Str");
         }
     }
 }
@@ -458,7 +436,8 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     }
     out.end_block();
 
-    out.begin_block("namespace cxxbridge01");
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge01");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -467,6 +446,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         }
     }
     out.end_block();
+    out.end_block();
 }
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
@@ -482,27 +462,27 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$uninit(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$set_raw(::cxxbridge::RustBox<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$rust_box${}$set_raw(::rust::Box<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$drop(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "void cxxbridge01$rust_box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge01$rust_box${}$deref(const ::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$rust_box${}$deref(const ::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge01$rust_box${}$deref_mut(::cxxbridge::RustBox<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$rust_box${}$deref_mut(::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
@@ -518,7 +498,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let instance = inner.replace("::", "$");
 
     writeln!(out, "template <>");
-    writeln!(out, "void RustBox<{}>::uninit() noexcept {{", inner);
+    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$uninit(this);",
@@ -529,7 +509,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "void RustBox<{}>::set_raw({} *raw) noexcept {{",
+        "void Box<{}>::set_raw({} *raw) noexcept {{",
         inner, inner,
     );
     writeln!(
@@ -540,7 +520,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "void RustBox<{}>::drop() noexcept {{", inner);
+    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$drop(this);",
@@ -551,7 +531,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "const {} *RustBox<{}>::deref() const noexcept {{",
+        "const {} *Box<{}>::deref() const noexcept {{",
         inner, inner,
     );
     writeln!(
@@ -562,11 +542,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(
-        out,
-        "{} *RustBox<{}>::deref_mut() noexcept {{",
-        inner, inner,
-    );
+    writeln!(out, "{} *Box<{}>::deref_mut() noexcept {{", inner, inner);
     writeln!(
         out,
         "  return cxxbridge01$rust_box${}$deref_mut(this);",
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 8061c28..a668a66 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -4,21 +4,19 @@
 #include <iostream>
 #include <string>
 
-namespace cxxbridge01 {}
-namespace cxxbridge = cxxbridge01;
+namespace rust {
+inline namespace cxxbridge01 {
 
-namespace cxxbridge01 {
-
-class RustString final {
+class String final {
 public:
-  RustString() noexcept;
-  RustString(const RustString &other) noexcept;
-  RustString(RustString &&other) noexcept;
-  RustString(const char *s);
-  RustString(const std::string &s);
-  RustString &operator=(const RustString &other) noexcept;
-  RustString &operator=(RustString &&other) noexcept;
-  ~RustString() noexcept;
+  String() noexcept;
+  String(const String &other) noexcept;
+  String(String &&other) noexcept;
+  String(const char *s);
+  String(const std::string &s);
+  String &operator=(const String &other) noexcept;
+  String &operator=(String &&other) noexcept;
+  ~String() noexcept;
   operator std::string() const;
 
   // Note: no null terminator.
@@ -31,14 +29,14 @@ private:
   std::array<uintptr_t, 3> repr;
 };
 
-class RustStr final {
+class Str final {
 public:
-  RustStr() noexcept;
-  RustStr(const char *s);
-  RustStr(const std::string &s);
-  RustStr(std::string &&s) = delete;
-  RustStr(const RustStr &other) noexcept;
-  RustStr &operator=(RustStr other) noexcept;
+  Str() noexcept;
+  Str(const char *s);
+  Str(const std::string &s);
+  Str(std::string &&s) = delete;
+  Str(const Str &other) noexcept;
+  Str &operator=(Str other) noexcept;
   operator std::string() const;
 
   // Note: no null terminator.
@@ -54,7 +52,7 @@ public:
     const char *ptr;
     size_t len;
   };
-  RustStr(Repr repr) noexcept;
+  Str(Repr repr) noexcept;
   operator Repr() noexcept;
 
 private:
@@ -63,15 +61,15 @@ private:
 
 #ifndef CXXBRIDGE01_RUST_BOX
 #define CXXBRIDGE01_RUST_BOX
-template <typename T> class RustBox final {
+template <typename T> class Box final {
 public:
-  RustBox(const RustBox &other) : RustBox(*other) {}
-  RustBox(RustBox &&other) noexcept : repr(other.repr) { other.repr = 0; }
-  RustBox(const T &val) {
+  Box(const Box &other) : Box(*other) {}
+  Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
+  Box(const T &val) {
     this->uninit();
     ::new (this->deref_mut()) T(val);
   }
-  RustBox &operator=(const RustBox &other) {
+  Box &operator=(const Box &other) {
     if (this != &other) {
       if (this->repr) {
         **this = *other;
@@ -82,7 +80,7 @@ public:
     }
     return *this;
   }
-  RustBox &operator=(RustBox &&other) noexcept {
+  Box &operator=(Box &&other) noexcept {
     if (this->repr) {
       this->drop();
     }
@@ -90,7 +88,7 @@ public:
     other.repr = 0;
     return *this;
   }
-  ~RustBox() noexcept {
+  ~Box() noexcept {
     if (this->repr) {
       this->drop();
     }
@@ -103,8 +101,8 @@ public:
 
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
-  static RustBox from_raw(T *raw) noexcept {
-    RustBox box;
+  static Box from_raw(T *raw) noexcept {
+    Box box;
     box.set_raw(raw);
     return box;
   }
@@ -116,7 +114,7 @@ public:
   }
 
 private:
-  RustBox() noexcept {}
+  Box() noexcept {}
   void uninit() noexcept;
   void set_raw(T *) noexcept;
   T *get_raw() noexcept;
@@ -127,7 +125,8 @@ private:
 };
 #endif // CXXBRIDGE01_RUST_BOX
 
-std::ostream &operator<<(std::ostream &os, const RustString &s);
-std::ostream &operator<<(std::ostream &os, const RustStr &s);
+std::ostream &operator<<(std::ostream &os, const String &s);
+std::ostream &operator<<(std::ostream &os, const Str &s);
 
-} // namespace cxxbridge01
+} // inline namespace cxxbridge01
+} // namespace rust
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index a502d20..c139688 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -3,8 +3,6 @@
 #include <memory>
 #include <stdexcept>
 
-namespace cxxbridge = cxxbridge01;
-
 extern "C" {
 const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -14,56 +12,57 @@ size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
-// RustString
-void cxxbridge01$rust_string$new(cxxbridge::RustString *self) noexcept;
-void cxxbridge01$rust_string$clone(cxxbridge::RustString *self,
-                                   const cxxbridge::RustString &other) noexcept;
-bool cxxbridge01$rust_string$from(cxxbridge::RustString *self, const char *ptr,
+// rust::String
+void cxxbridge01$rust_string$new(rust::String *self) noexcept;
+void cxxbridge01$rust_string$clone(rust::String *self,
+                                   const rust::String &other) noexcept;
+bool cxxbridge01$rust_string$from(rust::String *self, const char *ptr,
                                   size_t len) noexcept;
-void cxxbridge01$rust_string$drop(cxxbridge::RustString *self) noexcept;
+void cxxbridge01$rust_string$drop(rust::String *self) noexcept;
 const char *
-cxxbridge01$rust_string$ptr(const cxxbridge::RustString *self) noexcept;
-size_t cxxbridge01$rust_string$len(const cxxbridge::RustString *self) noexcept;
+cxxbridge01$rust_string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge01$rust_string$len(const rust::String *self) noexcept;
 
-// RustStr
+// rust::Str
 bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
-namespace cxxbridge01 {
+namespace rust {
+inline namespace cxxbridge01 {
 
-RustString::RustString() noexcept { cxxbridge01$rust_string$new(this); }
+String::String() noexcept { cxxbridge01$rust_string$new(this); }
 
-RustString::RustString(const RustString &other) noexcept {
+String::String(const String &other) noexcept {
   cxxbridge01$rust_string$clone(this, other);
 }
 
-RustString::RustString(RustString &&other) noexcept {
+String::String(String &&other) noexcept {
   this->repr = other.repr;
   cxxbridge01$rust_string$new(&other);
 }
 
-RustString::RustString(const char *s) {
+String::String(const char *s) {
   auto len = strlen(s);
   if (!cxxbridge01$rust_string$from(this, s, len)) {
-    throw std::invalid_argument("data for RustString is not utf-8");
+    throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
-RustString::RustString(const std::string &s) {
+String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
   if (!cxxbridge01$rust_string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for RustString is not utf-8");
+    throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
-RustString::~RustString() noexcept { cxxbridge01$rust_string$drop(this); }
+String::~String() noexcept { cxxbridge01$rust_string$drop(this); }
 
-RustString::operator std::string() const {
+String::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-RustString &RustString::operator=(const RustString &other) noexcept {
+String &String::operator=(const String &other) noexcept {
   if (this != &other) {
     cxxbridge01$rust_string$drop(this);
     cxxbridge01$rust_string$clone(this, other);
@@ -71,7 +70,7 @@ RustString &RustString::operator=(const RustString &other) noexcept {
   return *this;
 }
 
-RustString &RustString::operator=(RustString &&other) noexcept {
+String &String::operator=(String &&other) noexcept {
   if (this != &other) {
     cxxbridge01$rust_string$drop(this);
     this->repr = other.repr;
@@ -80,65 +79,66 @@ RustString &RustString::operator=(RustString &&other) noexcept {
   return *this;
 }
 
-const char *RustString::data() const noexcept {
+const char *String::data() const noexcept {
   return cxxbridge01$rust_string$ptr(this);
 }
 
-size_t RustString::size() const noexcept {
+size_t String::size() const noexcept {
   return cxxbridge01$rust_string$len(this);
 }
 
-size_t RustString::length() const noexcept {
+size_t String::length() const noexcept {
   return cxxbridge01$rust_string$len(this);
 }
 
-std::ostream &operator<<(std::ostream &os, const RustString &s) {
+std::ostream &operator<<(std::ostream &os, const String &s) {
   os.write(s.data(), s.size());
   return os;
 }
 
-RustStr::RustStr() noexcept
+Str::Str() noexcept
     : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
-RustStr::RustStr(const char *s) : repr(Repr{s, strlen(s)}) {
+Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for RustStr is not utf-8");
+    throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
-RustStr::RustStr(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for RustStr is not utf-8");
+    throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
-RustStr::RustStr(const RustStr &) noexcept = default;
+Str::Str(const Str &) noexcept = default;
 
-RustStr &RustStr::operator=(RustStr other) noexcept {
+Str &Str::operator=(Str other) noexcept {
   this->repr = other.repr;
   return *this;
 }
 
-RustStr::operator std::string() const {
+Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-const char *RustStr::data() const noexcept { return this->repr.ptr; }
+const char *Str::data() const noexcept { return this->repr.ptr; }
 
-size_t RustStr::size() const noexcept { return this->repr.len; }
+size_t Str::size() const noexcept { return this->repr.len; }
 
-size_t RustStr::length() const noexcept { return this->repr.len; }
+size_t Str::length() const noexcept { return this->repr.len; }
 
-RustStr::RustStr(Repr repr_) noexcept : repr(repr_) {}
+Str::Str(Repr repr_) noexcept : repr(repr_) {}
 
-RustStr::operator Repr() noexcept { return this->repr; }
+Str::operator Repr() noexcept { return this->repr; }
 
-std::ostream &operator<<(std::ostream &os, const RustStr &s) {
+std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;
 }
 
-} // namespace cxxbridge01
+} // inline namespace cxxbridge01
+} // namespace rust
 
 extern "C" {
 void cxxbridge01$unique_ptr$std$string$null(
diff --git a/src/lib.rs b/src/lib.rs
index 4c0f3c9..006159a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -302,10 +302,10 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
-//! <tr><td>String</td><td>cxxbridge::RustString</td><td></td></tr>
-//! <tr><td>&amp;str</td><td>cxxbridge::RustStr</td><td></td></tr>
+//! <tr><td>String</td><td>rust::String</td><td></td></tr>
+//! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
-//! <tr><td>Box&lt;T&gt;</td><td>cxxbridge::RustBox&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d27df41..65640df 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -19,12 +19,12 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
-cxxbridge::RustStr c_return_str(const Shared &shared) {
+rust::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
 
-cxxbridge::RustString c_return_rust_string() { return "2020"; }
+rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
@@ -42,7 +42,7 @@ void c_take_shared(Shared shared) {
   }
 }
 
-void c_take_box(cxxbridge::RustBox<R> r) {
+void c_take_box(rust::Box<R> r) {
   (void)r;
   cxx_test_suite_set_correct();
 }
@@ -61,13 +61,13 @@ void c_take_ref_c(const C &c) {
   }
 }
 
-void c_take_str(cxxbridge::RustStr s) {
+void c_take_str(rust::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_rust_string(cxxbridge::RustString s) {
+void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -99,8 +99,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
-  r_take_str(cxxbridge::RustStr("2020"));
-  // TODO r_take_rust_string(cxxbridge::RustString("2020"));
+  r_take_str(rust::Str("2020"));
+  // TODO r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 87aac67..f41cc5e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,21 +19,21 @@ private:
 
 size_t c_return_primitive();
 Shared c_return_shared();
-cxxbridge::RustBox<R> c_return_box();
+rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
-cxxbridge::RustStr c_return_str(const Shared &shared);
-cxxbridge::RustString c_return_rust_string();
+rust::Str c_return_str(const Shared &shared);
+rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
-void c_take_box(cxxbridge::RustBox<R> r);
+void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
-void c_take_str(cxxbridge::RustStr s);
-void c_take_rust_string(cxxbridge::RustString s);
+void c_take_str(rust::Str s);
+void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
 } // namespace tests

From 69fe4c25ec4162b2a5cedd26ce9013cec756ddd2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:05:01 +0000
Subject: [PATCH 74/2232] Format with clang-format


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index a668a66..3107668 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -128,5 +128,5 @@ private:
 std::ostream &operator<<(std::ostream &os, const String &s);
 std::ostream &operator<<(std::ostream &os, const Str &s);
 
-} // inline namespace cxxbridge01
+} // namespace cxxbridge01
 } // namespace rust
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index c139688..2952f92 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -19,8 +19,7 @@ void cxxbridge01$rust_string$clone(rust::String *self,
 bool cxxbridge01$rust_string$from(rust::String *self, const char *ptr,
                                   size_t len) noexcept;
 void cxxbridge01$rust_string$drop(rust::String *self) noexcept;
-const char *
-cxxbridge01$rust_string$ptr(const rust::String *self) noexcept;
+const char *cxxbridge01$rust_string$ptr(const rust::String *self) noexcept;
 size_t cxxbridge01$rust_string$len(const rust::String *self) noexcept;
 
 // rust::Str
@@ -96,8 +95,7 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept
-    : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
+Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
 Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
@@ -137,7 +135,7 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
-} // inline namespace cxxbridge01
+} // namespace cxxbridge01
 } // namespace rust
 
 extern "C" {

From 9ad1fbc47843a13550438c1a3d26a24b8ccb0c87 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:05:01 +0000
Subject: [PATCH 75/2232] Pass ending comment to end_block


Clang-format doesn't always like the same ending comment as the start of
the block. In particular it wants:

    inline namespace cxxbridge01 {
      ...
    } // namespace cxxbridge01

---

diff --git a/gen/out.rs b/gen/out.rs
index 8d7499b..506ce6c 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -5,8 +5,7 @@ pub(crate) struct OutFile {
     pub header: bool,
     content: Vec<u8>,
     section_pending: bool,
-    blocks: Vec<&'static str>,
-    blocks_pending: usize,
+    blocks_pending: Vec<&'static str>,
 }
 
 impl OutFile {
@@ -16,8 +15,7 @@ impl OutFile {
             header,
             content: Vec::new(),
             section_pending: false,
-            blocks: Vec::new(),
-            blocks_pending: 0,
+            blocks_pending: Vec::new(),
         }
     }
 
@@ -27,17 +25,13 @@ impl OutFile {
     }
 
     pub fn begin_block(&mut self, block: &'static str) {
-        self.blocks.push(block);
-        self.blocks_pending += 1;
+        self.blocks_pending.push(block);
     }
 
-    pub fn end_block(&mut self) {
-        if self.blocks_pending > 0 {
-            self.blocks_pending -= 1;
-        } else {
+    pub fn end_block(&mut self, block: &'static str) {
+        if self.blocks_pending.pop().is_none() {
             self.content.extend_from_slice(b"} // ");
-            self.content
-                .extend_from_slice(self.blocks.pop().unwrap().as_bytes());
+            self.content.extend_from_slice(block.as_bytes());
             self.content.push(b'\n');
             self.section_pending = true;
         }
@@ -51,13 +45,12 @@ impl OutFile {
 impl Write for OutFile {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         if !s.is_empty() {
-            if self.blocks_pending > 0 {
+            if !self.blocks_pending.is_empty() {
                 self.content.push(b'\n');
-                for block in &self.blocks[self.blocks.len() - self.blocks_pending..] {
+                for block in self.blocks_pending.drain(..) {
                     self.content.extend_from_slice(block.as_bytes());
                     self.content.extend_from_slice(b" {\n");
                 }
-                self.blocks_pending = 0;
                 self.section_pending = false;
             } else if self.section_pending {
                 self.content.push(b'\n');
diff --git a/gen/write.rs b/gen/write.rs
index a2c1b7a..99ea418 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -54,7 +54,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
             out.next_section();
             write(out, efn, types);
         }
-        out.end_block();
+        out.end_block("extern \"C\"");
     }
 
     for api in apis {
@@ -125,8 +125,8 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block();
-    out.end_block();
+    out.end_block("namespace cxxbridge01");
+    out.end_block("namespace rust");
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
@@ -434,7 +434,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block();
+    out.end_block("extern \"C\"");
 
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge01");
@@ -445,8 +445,8 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block();
-    out.end_block();
+    out.end_block("namespace cxxbridge01");
+    out.end_block("namespace rust");
 }
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {

From 3b0c98805944aaaa404208e1cd66bec8c6216636 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:08:57 +0000
Subject: [PATCH 76/2232] Expose snake case type aliases


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 3107668..4fc1bf9 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -128,5 +128,10 @@ private:
 std::ostream &operator<<(std::ostream &os, const String &s);
 std::ostream &operator<<(std::ostream &os, const Str &s);
 
+// Snake case aliases for use in code that uses this style for type names.
+using string = String;
+using str = Str;
+template <class T> using box = Box<T>;
+
 } // namespace cxxbridge01
 } // namespace rust

From c2db0e83f2e5745276a76c16a82750b9369d6e29 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:09:19 +0000
Subject: [PATCH 77/2232] Demonstrate that snake case type aliases work


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index b975e88..e6a5d08 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,7 +9,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
+std::unique_ptr<ThingC> make_demo(rust::str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index a579986..9a3bcd0 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -16,7 +16,7 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
+std::unique_ptr<ThingC> make_demo(rust::str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 65640df..ecc4488 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -19,12 +19,12 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
-rust::Str c_return_str(const Shared &shared) {
+rust::str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
 
-rust::String c_return_rust_string() { return "2020"; }
+rust::string c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
@@ -42,7 +42,7 @@ void c_take_shared(Shared shared) {
   }
 }
 
-void c_take_box(rust::Box<R> r) {
+void c_take_box(rust::box<R> r) {
   (void)r;
   cxx_test_suite_set_correct();
 }
@@ -61,13 +61,13 @@ void c_take_ref_c(const C &c) {
   }
 }
 
-void c_take_str(rust::Str s) {
+void c_take_str(rust::str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_rust_string(rust::String s) {
+void c_take_rust_string(rust::string s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -99,8 +99,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
-  r_take_str(rust::Str("2020"));
-  // TODO r_take_rust_string(rust::String("2020"));
+  r_take_str(rust::str("2020"));
+  // TODO r_take_rust_string(rust::string("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index f41cc5e..3bb5095 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,21 +19,21 @@ private:
 
 size_t c_return_primitive();
 Shared c_return_shared();
-rust::Box<R> c_return_box();
+rust::box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
-rust::Str c_return_str(const Shared &shared);
-rust::String c_return_rust_string();
+rust::str c_return_str(const Shared &shared);
+rust::string c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
-void c_take_box(rust::Box<R> r);
+void c_take_box(rust::box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
-void c_take_str(rust::Str s);
-void c_take_rust_string(rust::String s);
+void c_take_str(rust::str s);
+void c_take_rust_string(rust::string s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
 } // namespace tests

From 92d12f3993921b33c83a9cdb32f962297f5fb11d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:13:50 +0000
Subject: [PATCH 78/2232] Revert "Demonstrate that snake case type aliases work"


This reverts commit c2db0e83f2e5745276a76c16a82750b9369d6e29.

---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index e6a5d08..b975e88 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,7 +9,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(rust::str appname) {
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(appname));
 }
 
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 9a3bcd0..a579986 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -16,7 +16,7 @@ public:
 
 struct SharedThing;
 
-std::unique_ptr<ThingC> make_demo(rust::str appname);
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index ecc4488..65640df 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -19,12 +19,12 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
-rust::str c_return_str(const Shared &shared) {
+rust::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
 }
 
-rust::string c_return_rust_string() { return "2020"; }
+rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
@@ -42,7 +42,7 @@ void c_take_shared(Shared shared) {
   }
 }
 
-void c_take_box(rust::box<R> r) {
+void c_take_box(rust::Box<R> r) {
   (void)r;
   cxx_test_suite_set_correct();
 }
@@ -61,13 +61,13 @@ void c_take_ref_c(const C &c) {
   }
 }
 
-void c_take_str(rust::str s) {
+void c_take_str(rust::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_rust_string(rust::string s) {
+void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
   }
@@ -99,8 +99,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
-  r_take_str(rust::str("2020"));
-  // TODO r_take_rust_string(rust::string("2020"));
+  r_take_str(rust::Str("2020"));
+  // TODO r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3bb5095..f41cc5e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,21 +19,21 @@ private:
 
 size_t c_return_primitive();
 Shared c_return_shared();
-rust::box<R> c_return_box();
+rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
-rust::str c_return_str(const Shared &shared);
-rust::string c_return_rust_string();
+rust::Str c_return_str(const Shared &shared);
+rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
-void c_take_box(rust::box<R> r);
+void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
-void c_take_str(rust::str s);
-void c_take_rust_string(rust::string s);
+void c_take_str(rust::Str s);
+void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
 } // namespace tests

From da2b9045308b76ca5f5fe89be64b021db138cce1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 01 2020 22:42:19 +0000
Subject: [PATCH 79/2232] Merge pull request #50 from dtolnay/snake


Expose snake case type aliases
---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 3107668..4fc1bf9 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -128,5 +128,10 @@ private:
 std::ostream &operator<<(std::ostream &os, const String &s);
 std::ostream &operator<<(std::ostream &os, const Str &s);
 
+// Snake case aliases for use in code that uses this style for type names.
+using string = String;
+using str = Str;
+template <class T> using box = Box<T>;
+
 } // namespace cxxbridge01
 } // namespace rust

From 9081beb1a01f4150937bd97efdec631cf1ad03bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 03:52:09 +0000
Subject: [PATCH 80/2232] Remove redundant prefix from mangled Box related symbols


---

diff --git a/gen/write.rs b/gen/write.rs
index 99ea418..381800b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -462,27 +462,27 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge01$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$set_raw(::rust::Box<{}> *ptr, {} *raw) noexcept;",
+        "void cxxbridge01$box${}$set_raw(::rust::Box<{}> *ptr, {} *raw) noexcept;",
         instance, inner, inner
     );
     writeln!(
         out,
-        "void cxxbridge01$rust_box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge01$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge01$rust_box${}$deref(const ::rust::Box<{}> *ptr) noexcept;",
+        "const {} *cxxbridge01$box${}$deref(const ::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(
         out,
-        "{} *cxxbridge01$rust_box${}$deref_mut(::rust::Box<{}> *ptr) noexcept;",
+        "{} *cxxbridge01$box${}$deref_mut(::rust::Box<{}> *ptr) noexcept;",
         inner, instance, inner,
     );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
@@ -499,11 +499,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge01$rust_box${}$uninit(this);",
-        instance
-    );
+    writeln!(out, "  return cxxbridge01$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
@@ -514,18 +510,14 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "  return cxxbridge01$rust_box${}$set_raw(this, raw);",
+        "  return cxxbridge01$box${}$set_raw(this, raw);",
         instance
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge01$rust_box${}$drop(this);",
-        instance
-    );
+    writeln!(out, "  return cxxbridge01$box${}$drop(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
@@ -534,18 +526,14 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
         "const {} *Box<{}>::deref() const noexcept {{",
         inner, inner,
     );
-    writeln!(
-        out,
-        "  return cxxbridge01$rust_box${}$deref(this);",
-        instance
-    );
+    writeln!(out, "  return cxxbridge01$box${}$deref(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "{} *Box<{}>::deref_mut() noexcept {{", inner, inner);
     writeln!(
         out,
-        "  return cxxbridge01$rust_box${}$deref_mut(this);",
+        "  return cxxbridge01$box${}$deref_mut(this);",
         instance
     );
     writeln!(out, "}}");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index bcd02f1..1896a13 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -293,7 +293,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge01$rust_box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge01$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_set_raw = format!("{}set_raw", link_prefix);
     let link_drop = format!("{}drop", link_prefix);

From 001102af7137959a85af9ba0c802a97502bf879e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:05:04 +0000
Subject: [PATCH 81/2232] Use iosfwd for forward declared ostream insertion operators


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 4fc1bf9..c8f85a9 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -1,7 +1,7 @@
 #pragma once
 #include <array>
 #include <cstdint>
-#include <iostream>
+#include <iosfwd>
 #include <string>
 
 namespace rust {
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 2952f92..7991bfe 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -1,5 +1,6 @@
 #include "../include/cxxbridge.h"
 #include <cstring>
+#include <iostream>
 #include <memory>
 #include <stdexcept>
 

From 83a5a11b9a5b3bf64969fc9ce544d0aafd2f6037 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:18:37 +0000
Subject: [PATCH 82/2232] Merge pull request #55 from dtolnay/iosfwd


Use iosfwd for forward declared ostream insertion operators
---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 4fc1bf9..c8f85a9 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -1,7 +1,7 @@
 #pragma once
 #include <array>
 #include <cstdint>
-#include <iostream>
+#include <iosfwd>
 #include <string>
 
 namespace rust {
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 2952f92..7991bfe 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -1,5 +1,6 @@
 #include "../include/cxxbridge.h"
 #include <cstring>
+#include <iostream>
 #include <memory>
 #include <stdexcept>
 

From 404d689e953cfe3e221a242e762f6eaa8b02f18e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:19:41 +0000
Subject: [PATCH 83/2232] Change string cast operators to explicit


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index b975e88..04287b8 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -10,7 +10,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::unique_ptr<ThingC>(new ThingC(appname));
+  return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index c8f85a9..b5a6451 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -17,7 +17,7 @@ public:
   String &operator=(const String &other) noexcept;
   String &operator=(String &&other) noexcept;
   ~String() noexcept;
-  operator std::string() const;
+  explicit operator std::string() const;
 
   // Note: no null terminator.
   const char *data() const noexcept;
@@ -37,7 +37,7 @@ public:
   Str(std::string &&s) = delete;
   Str(const Str &other) noexcept;
   Str &operator=(Str other) noexcept;
-  operator std::string() const;
+  explicit operator std::string() const;
 
   // Note: no null terminator.
   const char *data() const noexcept;

From baae443ae2af1cf14c613389c33f5a0f015348d6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:20:10 +0000
Subject: [PATCH 84/2232] Change Str to Repr operator to explicit


---

diff --git a/gen/write.rs b/gen/write.rs
index 381800b..e0396c9 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -191,8 +191,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "(");
     } else if let Some(ret) = &efn.ret {
         write!(out, "return ");
-        if let Type::Ref(_) = ret {
-            write!(out, "&");
+        match ret {
+            Type::Ref(_) => write!(out, "&"),
+            Type::Str(_) => write!(out, "::rust::Str::Repr("),
+            _ => {}
         }
     }
     write!(out, "{}$(", efn.ident);
@@ -216,6 +218,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::Str(_)) => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -293,13 +296,16 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             if i > 0 {
                 write!(out, ", ");
             }
-            if types.needs_indirect_abi(&arg.ty) {
-                write!(out, "&");
+            match &arg.ty {
+                Type::Str(_) => write!(out, "::rust::Str::Repr("),
+                ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+                _ => {}
             }
             write!(out, "{}", arg.ident);
             match arg.ty {
                 Type::RustBox(_) => write!(out, ".into_raw()"),
                 Type::UniquePtr(_) => write!(out, ".release()"),
+                Type::Str(_) => write!(out, ")"),
                 _ => {}
             }
         }
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index b5a6451..a0c0b07 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -53,7 +53,7 @@ public:
     size_t len;
   };
   Str(Repr repr) noexcept;
-  operator Repr() noexcept;
+  explicit operator Repr() noexcept;
 
 private:
   Repr repr;

From 133d9d5d9d8910d1071470d0cd1ac187a0ee9671 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:36:12 +0000
Subject: [PATCH 85/2232] Merge pull request #56 from dtolnay/cast


Change cast operators to explicit
---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index b975e88..04287b8 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -10,7 +10,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::unique_ptr<ThingC>(new ThingC(appname));
+  return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
diff --git a/gen/write.rs b/gen/write.rs
index 381800b..e0396c9 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -191,8 +191,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "(");
     } else if let Some(ret) = &efn.ret {
         write!(out, "return ");
-        if let Type::Ref(_) = ret {
-            write!(out, "&");
+        match ret {
+            Type::Ref(_) => write!(out, "&"),
+            Type::Str(_) => write!(out, "::rust::Str::Repr("),
+            _ => {}
         }
     }
     write!(out, "{}$(", efn.ident);
@@ -216,6 +218,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::Str(_)) => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -293,13 +296,16 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             if i > 0 {
                 write!(out, ", ");
             }
-            if types.needs_indirect_abi(&arg.ty) {
-                write!(out, "&");
+            match &arg.ty {
+                Type::Str(_) => write!(out, "::rust::Str::Repr("),
+                ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+                _ => {}
             }
             write!(out, "{}", arg.ident);
             match arg.ty {
                 Type::RustBox(_) => write!(out, ".into_raw()"),
                 Type::UniquePtr(_) => write!(out, ".release()"),
+                Type::Str(_) => write!(out, ")"),
                 _ => {}
             }
         }
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index c8f85a9..a0c0b07 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -17,7 +17,7 @@ public:
   String &operator=(const String &other) noexcept;
   String &operator=(String &&other) noexcept;
   ~String() noexcept;
-  operator std::string() const;
+  explicit operator std::string() const;
 
   // Note: no null terminator.
   const char *data() const noexcept;
@@ -37,7 +37,7 @@ public:
   Str(std::string &&s) = delete;
   Str(const Str &other) noexcept;
   Str &operator=(Str other) noexcept;
-  operator std::string() const;
+  explicit operator std::string() const;
 
   // Note: no null terminator.
   const char *data() const noexcept;
@@ -53,7 +53,7 @@ public:
     size_t len;
   };
   Str(Repr repr) noexcept;
-  operator Repr() noexcept;
+  explicit operator Repr() noexcept;
 
 private:
   Repr repr;

From d9c4ac955f835eae3c7bbaf6feedf13b027e58bb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 04:36:21 +0000
Subject: [PATCH 86/2232] Organize string constructors


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index a0c0b07..984eca2 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -10,13 +10,16 @@ inline namespace cxxbridge01 {
 class String final {
 public:
   String() noexcept;
-  String(const String &other) noexcept;
-  String(String &&other) noexcept;
-  String(const char *s);
-  String(const std::string &s);
-  String &operator=(const String &other) noexcept;
-  String &operator=(String &&other) noexcept;
+  String(const String &) noexcept;
+  String(String &&) noexcept;
   ~String() noexcept;
+
+  String(const std::string &);
+  String(const char *);
+
+  String &operator=(const String &) noexcept;
+  String &operator=(String &&) noexcept;
+
   explicit operator std::string() const;
 
   // Note: no null terminator.
@@ -32,11 +35,14 @@ private:
 class Str final {
 public:
   Str() noexcept;
-  Str(const char *s);
+  Str(const Str &) noexcept;
+
   Str(const std::string &s);
+  Str(const char *s);
   Str(std::string &&s) = delete;
-  Str(const Str &other) noexcept;
-  Str &operator=(Str other) noexcept;
+
+  Str &operator=(Str) noexcept;
+
   explicit operator std::string() const;
 
   // Note: no null terminator.
@@ -52,7 +58,7 @@ public:
     const char *ptr;
     size_t len;
   };
-  Str(Repr repr) noexcept;
+  Str(Repr) noexcept;
   explicit operator Repr() noexcept;
 
 private:
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 7991bfe..1f7c8dd 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -41,12 +41,7 @@ String::String(String &&other) noexcept {
   cxxbridge01$rust_string$new(&other);
 }
 
-String::String(const char *s) {
-  auto len = strlen(s);
-  if (!cxxbridge01$rust_string$from(this, s, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
-  }
-}
+String::~String() noexcept { cxxbridge01$rust_string$drop(this); }
 
 String::String(const std::string &s) {
   auto ptr = s.data();
@@ -56,10 +51,11 @@ String::String(const std::string &s) {
   }
 }
 
-String::~String() noexcept { cxxbridge01$rust_string$drop(this); }
-
-String::operator std::string() const {
-  return std::string(this->data(), this->size());
+String::String(const char *s) {
+  auto len = strlen(s);
+  if (!cxxbridge01$rust_string$from(this, s, len)) {
+    throw std::invalid_argument("data for rust::String is not utf-8");
+  }
 }
 
 String &String::operator=(const String &other) noexcept {
@@ -79,6 +75,10 @@ String &String::operator=(String &&other) noexcept {
   return *this;
 }
 
+String::operator std::string() const {
+  return std::string(this->data(), this->size());
+}
+
 const char *String::data() const noexcept {
   return cxxbridge01$rust_string$ptr(this);
 }
@@ -98,20 +98,20 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 
 Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
-Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
+Str::Str(const Str &) noexcept = default;
+
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
   if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const Str &) noexcept = default;
-
 Str &Str::operator=(Str other) noexcept {
   this->repr = other.repr;
   return *this;

From f6292378c714cd727e31bf6fc22d1233305ca4c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 05:09:11 +0000
Subject: [PATCH 87/2232] Add rust::Box member type aliases


---

diff --git a/gen/write.rs b/gen/write.rs
index e0396c9..e6fb4e9 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -79,6 +79,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
 
 fn write_includes(out: &mut OutFile, types: &Types) {
     let mut has_int = false;
+    let mut has_box = false;
     let mut has_unique_ptr = false;
     let mut has_string = false;
 
@@ -90,6 +91,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(CxxString) => has_string = true,
                 Some(Bool) | Some(RustString) | None => {}
             },
+            Type::RustBox(_) => has_box = true,
             Type::UniquePtr(_) => has_unique_ptr = true,
             _ => {}
         }
@@ -104,6 +106,9 @@ fn write_includes(out: &mut OutFile, types: &Types) {
     if has_string {
         writeln!(out, "#include <string>");
     }
+    if has_box {
+        writeln!(out, "#include <type_traits>");
+    }
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 984eca2..fe2f5be 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -3,6 +3,7 @@
 #include <cstdint>
 #include <iosfwd>
 #include <string>
+#include <type_traits>
 
 namespace rust {
 inline namespace cxxbridge01 {
@@ -69,6 +70,10 @@ private:
 #define CXXBRIDGE01_RUST_BOX
 template <typename T> class Box final {
 public:
+  using value_type = T;
+  using const_pointer = std::add_pointer_t<std::add_const_t<value_type>>;
+  using pointer = std::add_pointer_t<value_type>;
+
   Box(const Box &other) : Box(*other) {}
   Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
   Box(const T &val) {

From 9f9213709d6cd9091aa7d1a9763611307093ff40 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 05:09:40 +0000
Subject: [PATCH 88/2232] Backport type aliases to c++11


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index fe2f5be..d0cf8c2 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -71,8 +71,9 @@ private:
 template <typename T> class Box final {
 public:
   using value_type = T;
-  using const_pointer = std::add_pointer_t<std::add_const_t<value_type>>;
-  using pointer = std::add_pointer_t<value_type>;
+  using const_pointer = typename std::add_pointer<
+      typename std::add_const<value_type>::type>::type;
+  using pointer = typename std::add_pointer<value_type>::type;
 
   Box(const Box &other) : Box(*other) {}
   Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }

From 2248c3064e9654dddd8eb8f4fa4bf187354b19bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 05:13:32 +0000
Subject: [PATCH 89/2232] Write Box internals in terms of type aliases


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index d0cf8c2..aa78c2b 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -128,11 +128,11 @@ public:
 private:
   Box() noexcept {}
   void uninit() noexcept;
-  void set_raw(T *) noexcept;
-  T *get_raw() noexcept;
+  void set_raw(pointer) noexcept;
+  pointer get_raw() noexcept;
   void drop() noexcept;
-  const T *deref() const noexcept;
-  T *deref_mut() noexcept;
+  const_pointer deref() const noexcept;
+  pointer deref_mut() noexcept;
   uintptr_t repr;
 };
 #endif // CXXBRIDGE01_RUST_BOX

From 851677c4cc3a5c71c35f518f06187a488e3b510c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 07:49:46 +0000
Subject: [PATCH 90/2232] Remove insignificant parameter names from header


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index aa78c2b..d759c9d 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -38,9 +38,9 @@ public:
   Str() noexcept;
   Str(const Str &) noexcept;
 
-  Str(const std::string &s);
-  Str(const char *s);
-  Str(std::string &&s) = delete;
+  Str(const std::string &);
+  Str(const char *);
+  Str(std::string &&) = delete;
 
   Str &operator=(Str) noexcept;
 
@@ -137,8 +137,8 @@ private:
 };
 #endif // CXXBRIDGE01_RUST_BOX
 
-std::ostream &operator<<(std::ostream &os, const String &s);
-std::ostream &operator<<(std::ostream &os, const Str &s);
+std::ostream &operator<<(std::ostream &, const String &);
+std::ostream &operator<<(std::ostream &, const Str &);
 
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;

From 4590d2af81b0b80af55ee6d9825397d106b63723 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 08:03:25 +0000
Subject: [PATCH 91/2232] Delete unused get_raw member from Box


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index d759c9d..1701f4d 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -129,7 +129,6 @@ private:
   Box() noexcept {}
   void uninit() noexcept;
   void set_raw(pointer) noexcept;
-  pointer get_raw() noexcept;
   void drop() noexcept;
   const_pointer deref() const noexcept;
   pointer deref_mut() noexcept;

From 6c089108e4a1e7fd0cf3e8c61f2d8bf2cdc9bb2f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 02 2020 08:23:05 +0000
Subject: [PATCH 92/2232] Remove prefix from mangled string symbols


---

diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index 1f7c8dd..c58b7c5 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -14,63 +14,63 @@ size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
 }
 
 // rust::String
-void cxxbridge01$rust_string$new(rust::String *self) noexcept;
-void cxxbridge01$rust_string$clone(rust::String *self,
-                                   const rust::String &other) noexcept;
-bool cxxbridge01$rust_string$from(rust::String *self, const char *ptr,
-                                  size_t len) noexcept;
-void cxxbridge01$rust_string$drop(rust::String *self) noexcept;
-const char *cxxbridge01$rust_string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge01$rust_string$len(const rust::String *self) noexcept;
+void cxxbridge01$string$new(rust::String *self) noexcept;
+void cxxbridge01$string$clone(rust::String *self,
+                              const rust::String &other) noexcept;
+bool cxxbridge01$string$from(rust::String *self, const char *ptr,
+                             size_t len) noexcept;
+void cxxbridge01$string$drop(rust::String *self) noexcept;
+const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge01$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge01$rust_str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
 inline namespace cxxbridge01 {
 
-String::String() noexcept { cxxbridge01$rust_string$new(this); }
+String::String() noexcept { cxxbridge01$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge01$rust_string$clone(this, other);
+  cxxbridge01$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge01$rust_string$new(&other);
+  cxxbridge01$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge01$rust_string$drop(this); }
+String::~String() noexcept { cxxbridge01$string$drop(this); }
 
 String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
-  if (!cxxbridge01$rust_string$from(this, ptr, len)) {
+  if (!cxxbridge01$string$from(this, ptr, len)) {
     throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
 String::String(const char *s) {
   auto len = strlen(s);
-  if (!cxxbridge01$rust_string$from(this, s, len)) {
+  if (!cxxbridge01$string$from(this, s, len)) {
     throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge01$rust_string$drop(this);
-    cxxbridge01$rust_string$clone(this, other);
+    cxxbridge01$string$drop(this);
+    cxxbridge01$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge01$rust_string$drop(this);
+    cxxbridge01$string$drop(this);
     this->repr = other.repr;
-    cxxbridge01$rust_string$new(&other);
+    cxxbridge01$string$new(&other);
   }
   return *this;
 }
@@ -80,16 +80,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge01$rust_string$ptr(this);
+  return cxxbridge01$string$ptr(this);
 }
 
-size_t String::size() const noexcept {
-  return cxxbridge01$rust_string$len(this);
-}
+size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
 
-size_t String::length() const noexcept {
-  return cxxbridge01$rust_string$len(this);
-}
+size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
 
 std::ostream &operator<<(std::ostream &os, const String &s) {
   os.write(s.data(), s.size());
@@ -101,13 +97,13 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 Str::Str(const Str &) noexcept = default;
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
-  if (!cxxbridge01$rust_str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 59a7784..3d8a9f0 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -23,7 +23,7 @@ impl RustStr {
     }
 }
 
-#[export_name = "cxxbridge01$rust_str$valid"]
+#[export_name = "cxxbridge01$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 250a46f..43cd5a6 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -26,17 +26,17 @@ impl RustString {
     }
 }
 
-#[export_name = "cxxbridge01$rust_string$new"]
+#[export_name = "cxxbridge01$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge01$rust_string$clone"]
+#[export_name = "cxxbridge01$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge01$rust_string$from"]
+#[export_name = "cxxbridge01$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -52,17 +52,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge01$rust_string$drop"]
+#[export_name = "cxxbridge01$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge01$rust_string$ptr"]
+#[export_name = "cxxbridge01$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge01$rust_string$len"]
+#[export_name = "cxxbridge01$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }

From 40226ab58adb35ed90ff9c313fefbca8e3c4ae2c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 03 2020 08:05:35 +0000
Subject: [PATCH 93/2232] Implement passing ownership of string to Rust


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1896a13..16dab26 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -233,21 +233,17 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     let args = efn.args.iter().map(|arg| expand_extern_arg(arg, types));
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let var = if types.needs_indirect_abi(&arg.ty) {
-            quote!(::std::ptr::read(#ident))
-        } else {
-            quote!(#ident)
-        };
         match &arg.ty {
-            Type::Ident(ident) if ident == "String" => quote!(#var.into_string()),
-            Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#var)),
-            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#var)),
+            Type::Ident(i) if i == "String" => quote!(::std::mem::take((*#ident).as_mut_string())),
+            Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
+            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == "String" => quote!(#var.as_string()),
-                _ => var,
+                Type::Ident(i) if i == "String" => quote!(#ident.as_string()),
+                _ => quote!(#ident),
             },
-            Type::Str(_) => quote!(#var.as_str()),
-            _ => var,
+            Type::Str(_) => quote!(#ident.as_str()),
+            ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
+            _ => quote!(#ident),
         }
     });
     let mut outparam = None;
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 43cd5a6..345d969 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -24,6 +24,10 @@ impl RustString {
     pub fn as_string(&self) -> &String {
         &self.repr
     }
+
+    pub fn as_mut_string(&mut self) -> &mut String {
+        &mut self.repr
+    }
 }
 
 #[export_name = "cxxbridge01$string$new"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 65640df..c94e34d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -100,7 +100,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  // TODO r_take_rust_string(rust::String("2020"));
+  r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 

From 39d575fb04b235af187f786dbb04680fd77f9c9c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 03 2020 20:47:43 +0000
Subject: [PATCH 94/2232] Separate the two uses of expand_extern_arg


These are going to need to diverge shortly. Indirect args can pass from
Rust to C++ as *const T from which C++ will do an unsafe ptr::read, but
need to pass from C++ to Rust as *mut T to leave a zero value in the old
location for when the C++ destructor runs.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 16dab26..3d6eee0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,6 +1,6 @@
 use crate::namespace::Namespace;
 use crate::syntax::atom::Atom;
-use crate::syntax::{self, check, Api, ExternFn, ExternType, Struct, Type, Types, Var};
+use crate::syntax::{self, check, Api, ExternFn, ExternType, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
 use syn::{Error, ItemMod, Result, Token};
@@ -123,7 +123,15 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let args = efn.args.iter().map(|arg| expand_extern_arg(arg, types));
+    let args = efn.args.iter().map(|arg| {
+        let ident = &arg.ident;
+        let ty = expand_extern_type(&arg.ty);
+        if types.needs_indirect_abi(&arg.ty) {
+            quote!(#ident: *mut #ty)
+        } else {
+            quote!(#ident: #ty)
+        }
+    });
     let ret = expand_extern_return_type(&efn.ret, types);
     let mut outparam = None;
     if indirect_return(&efn.ret, types) {
@@ -230,7 +238,15 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let args = efn.args.iter().map(|arg| expand_extern_arg(arg, types));
+    let args = efn.args.iter().map(|arg| {
+        let ident = &arg.ident;
+        let ty = expand_extern_type(&arg.ty);
+        if types.needs_indirect_abi(&arg.ty) {
+            quote!(#ident: *mut #ty)
+        } else {
+            quote!(#ident: #ty)
+        }
+    });
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
@@ -444,13 +460,3 @@ fn expand_extern_return_type(ret: &Option<Type>, types: &Types) -> TokenStream {
     let ty = expand_extern_type(ret);
     quote!(-> #ty)
 }
-
-fn expand_extern_arg(arg: &Var, types: &Types) -> TokenStream {
-    let ident = &arg.ident;
-    let ty = expand_extern_type(&arg.ty);
-    if types.needs_indirect_abi(&arg.ty) {
-        quote!(#ident: *mut #ty)
-    } else {
-        quote!(#ident: #ty)
-    }
-}

From ba5eb2de8cbd6fd2b033203b4c3c2d87e8b9f534 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:15:52 +0000
Subject: [PATCH 95/2232] Add PartialEq impls for comparison against specific atoms


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index 57325d8..903f561 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -1,3 +1,4 @@
+use crate::syntax::Type;
 use proc_macro2::Ident;
 
 #[derive(Copy, Clone, PartialEq)]
@@ -38,3 +39,18 @@ impl Atom {
         }
     }
 }
+
+impl PartialEq<Atom> for Ident {
+    fn eq(&self, atom: &Atom) -> bool {
+        Atom::from(self) == Some(*atom)
+    }
+}
+
+impl PartialEq<Atom> for Type {
+    fn eq(&self, atom: &Atom) -> bool {
+        match self {
+            Type::Ident(ident) => ident == atom,
+            _ => false,
+        }
+    }
+}

From 438e26034c8b62dcadb0f83e2ea32cdd7bd05d8f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:21:35 +0000
Subject: [PATCH 96/2232] Make PartialEq work with reference lhs


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index 903f561..9fb6554 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -54,3 +54,15 @@ impl PartialEq<Atom> for Type {
         }
     }
 }
+
+impl PartialEq<Atom> for &Ident {
+    fn eq(&self, atom: &Atom) -> bool {
+        *self == atom
+    }
+}
+
+impl PartialEq<Atom> for &Type {
+    fn eq(&self, atom: &Atom) -> bool {
+        *self == atom
+    }
+}

From a52602b8afb63e85db3a0b28df32dfcb7f430766 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:24:34 +0000
Subject: [PATCH 97/2232] Use PartialEq<Atom> for some ident comparisons


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3d6eee0..1237892 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,5 @@
 use crate::namespace::Namespace;
-use crate::syntax::atom::Atom;
+use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{self, check, Api, ExternFn, ExternType, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
@@ -156,13 +156,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
-            Type::Ident(ident) if ident == "String" => {
+            Type::Ident(ident) if ident == RustString => {
                 quote!(#var.as_mut_ptr() as *mut ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == "String" => {
+                Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
                 }
                 _ => quote!(#var),
@@ -204,11 +204,11 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         .ret
         .as_ref()
         .and_then(|ret| match ret {
-            Type::Ident(ident) if ident == "String" => Some(quote!(#call.into_string())),
+            Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == "String" => Some(quote!(#call.as_string())),
+                Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
@@ -250,11 +250,11 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
-            Type::Ident(i) if i == "String" => quote!(::std::mem::take((*#ident).as_mut_string())),
+            Type::Ident(i) if i == RustString => quote!(::std::mem::take((*#ident).as_mut_string())),
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i == "String" => quote!(#ident.as_string()),
+                Type::Ident(i) if i == RustString => quote!(#ident.as_string()),
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -270,13 +270,13 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         .ret
         .as_ref()
         .and_then(|ret| match ret {
-            Type::Ident(ident) if ident == "String" => {
+            Type::Ident(ident) if ident == RustString => {
                 Some(quote!(::cxx::private::RustString::from(#call)))
             }
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == "String" => {
+                Type::Ident(ident) if ident == RustString => {
                     Some(quote!(::cxx::private::RustString::from_ref(#call)))
                 }
                 _ => None,
@@ -438,13 +438,13 @@ fn indirect_return(ret: &Option<Type>, types: &Types) -> bool {
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
     match ty {
-        Type::Ident(ident) if ident == "String" => quote!(::cxx::private::RustString),
+        Type::Ident(ident) if ident == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
             let inner = &ty.inner;
             quote!(*mut #inner)
         }
         Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident == "String" => quote!(&::cxx::private::RustString),
+            Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
             _ => quote!(#ty),
         },
         Type::Str(_) => quote!(::cxx::private::RustStr),
diff --git a/syntax/check.rs b/syntax/check.rs
index c2c6d41..df633de 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -96,7 +96,7 @@ fn is_unsized(ty: &Type, types: &Types) -> bool {
         Type::Ident(ident) => ident,
         _ => return false,
     };
-    ident == "CxxString" || types.cxx.contains(ident) || types.rust.contains(ident)
+    ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
 }
 
 fn check_mut_return_restriction(efn: &ExternFn) -> Result<()> {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index f553207..e97509b 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,3 +1,4 @@
+use crate::syntax::atom::Atom::*;
 use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -7,7 +8,7 @@ impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
             Type::Ident(ident) => {
-                if ident == "CxxString" {
+                if ident == CxxString {
                     let span = ident.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }

From d1e2efc8472f37e6de4fc59b05205b5b45449999 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:25:50 +0000
Subject: [PATCH 98/2232] Begin to introduce Rust-style move for C++ objects


---

diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 1701f4d..1ac3133 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -8,6 +8,8 @@
 namespace rust {
 inline namespace cxxbridge01 {
 
+struct unsafe_bitcopy_t;
+
 class String final {
 public:
   String() noexcept;
@@ -28,6 +30,9 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  // Internal API only intended for the cxxbridge code generator.
+  String(unsafe_bitcopy_t, const String &) noexcept;
+
 private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
@@ -144,5 +149,10 @@ using string = String;
 using str = Str;
 template <class T> using box = Box<T>;
 
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+
 } // namespace cxxbridge01
 } // namespace rust
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
index c58b7c5..b44204d 100644
--- a/src/cxxbridge.cc
+++ b/src/cxxbridge.cc
@@ -87,6 +87,9 @@ size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
 
 size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
 
+String::String(unsafe_bitcopy_t, const String &bits) noexcept
+    : repr(bits.repr) {}
+
 std::ostream &operator<<(std::ostream &os, const String &s) {
   os.write(s.data(), s.size());
   return os;

From a46a237fe7a9391a21b8251b3ff8ab4ceef2f461 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:28:15 +0000
Subject: [PATCH 99/2232] Make passing String by value to C++ const


---

diff --git a/gen/write.rs b/gen/write.rs
index e6fb4e9..33898ce 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -169,6 +169,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if i > 0 {
             write!(out, ", ");
         }
+        if arg.ty == RustString {
+            write!(out, "const ");
+        }
         write_extern_arg(out, arg, types);
     }
     if indirect_return {
@@ -213,6 +216,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         } else if let Type::UniquePtr(_) = &arg.ty {
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
+        } else if arg.ty == RustString {
+            write!(out, "::rust::String(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
             write!(out, "::std::move(*{})", arg.ident);
         } else {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1237892..9ebb623 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -126,7 +126,9 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
-        if types.needs_indirect_abi(&arg.ty) {
+        if arg.ty == RustString {
+            quote!(#ident: *const #ty)
+        } else if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
             quote!(#ident: #ty)
@@ -157,7 +159,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         let var = &arg.ident;
         match &arg.ty {
             Type::Ident(ident) if ident == RustString => {
-                quote!(#var.as_mut_ptr() as *mut ::cxx::private::RustString)
+                quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),

From cc3767f0ed74a4e1d4c06a408c8f5ce3eca59b5c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 18:42:02 +0000
Subject: [PATCH 100/2232] Format with rustfmt 2019-10-07


---

diff --git a/gen/write.rs b/gen/write.rs
index 33898ce..68f0315 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -217,7 +217,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
         } else if arg.ty == RustString {
-            write!(out, "::rust::String(::rust::unsafe_bitcopy, *{})", arg.ident);
+            write!(
+                out,
+                "::rust::String(::rust::unsafe_bitcopy, *{})",
+                arg.ident,
+            );
         } else if types.needs_indirect_abi(&arg.ty) {
             write!(out, "::std::move(*{})", arg.ident);
         } else {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9ebb623..dd5ab6e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -252,7 +252,9 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     let vars = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
-            Type::Ident(i) if i == RustString => quote!(::std::mem::take((*#ident).as_mut_string())),
+            Type::Ident(i) if i == RustString => {
+                quote!(::std::mem::take((*#ident).as_mut_string()))
+            }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {

From 9c68b1a0c67cb2830eeca0e5206f97b4a710ae7a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 19:27:29 +0000
Subject: [PATCH 101/2232] Lazily compute include set


---

diff --git a/gen/include.rs b/gen/include.rs
index ef741af..e34d9d0 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,3 +1,5 @@
+use std::fmt::{self, Display};
+
 pub static HEADER: &str = include_str!("include/cxxbridge.h");
 
 pub fn get(guard: &str) -> &'static str {
@@ -11,3 +13,43 @@ pub fn get(guard: &str) -> &'static str {
         panic!("not found in cxxbridge.h header: {}", guard)
     }
 }
+
+#[derive(Default)]
+pub struct Includes {
+    custom: Vec<String>,
+    pub cstdint: bool,
+    pub memory: bool,
+    pub string: bool,
+    pub type_traits: bool,
+}
+
+impl Includes {
+    pub fn new() -> Self {
+        Includes::default()
+    }
+
+    pub fn insert(&mut self, include: String) {
+        self.custom.push(include);
+    }
+}
+
+impl Display for Includes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for include in &self.custom {
+            writeln!(f, "#include \"{}\"", include.escape_default())?;
+        }
+        if self.cstdint {
+            writeln!(f, "#include <cstdint>")?;
+        }
+        if self.memory {
+            writeln!(f, "#include <memory>")?;
+        }
+        if self.string {
+            writeln!(f, "#include <string>")?;
+        }
+        if self.type_traits {
+            writeln!(f, "#include <type_traits>")?;
+        }
+        Ok(())
+    }
+}
diff --git a/gen/out.rs b/gen/out.rs
index 506ce6c..124816f 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,8 +1,10 @@
+use crate::gen::include::Includes;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
     pub namespace: Vec<String>,
     pub header: bool,
+    pub include: Includes,
     content: Vec<u8>,
     section_pending: bool,
     blocks_pending: Vec<&'static str>,
@@ -13,6 +15,7 @@ impl OutFile {
         OutFile {
             namespace,
             header,
+            include: Includes::new(),
             content: Vec::new(),
             section_pending: false,
             blocks_pending: Vec::new(),
@@ -37,6 +40,10 @@ impl OutFile {
         }
     }
 
+    pub fn prepend(&mut self, section: String) {
+        self.content.splice(..0, section.into_bytes());
+    }
+
     pub fn write_fmt(&mut self, args: Arguments) {
         Write::write_fmt(self, args).unwrap();
     }
diff --git a/gen/write.rs b/gen/write.rs
index 68f0315..24c9c09 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -14,7 +14,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
 
     for api in apis {
         if let Api::Include(include) = api {
-            writeln!(out, "#include \"{}\"", include.value().escape_default());
+            out.include.insert(include.value());
         }
     }
 
@@ -74,41 +74,25 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
         write_generic_instantiations(out, types);
     }
 
+    out.prepend(out.include.to_string());
+
     out_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {
-    let mut has_int = false;
-    let mut has_box = false;
-    let mut has_unique_ptr = false;
-    let mut has_string = false;
-
     for ty in types {
         match ty {
             Type::Ident(ident) => match Atom::from(ident) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-                | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => has_int = true,
-                Some(CxxString) => has_string = true,
+                | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
+                Some(CxxString) => out.include.string = true,
                 Some(Bool) | Some(RustString) | None => {}
             },
-            Type::RustBox(_) => has_box = true,
-            Type::UniquePtr(_) => has_unique_ptr = true,
+            Type::RustBox(_) => out.include.type_traits = true,
+            Type::UniquePtr(_) => out.include.memory = true,
             _ => {}
         }
     }
-
-    if has_int {
-        writeln!(out, "#include <cstdint>");
-    }
-    if has_unique_ptr {
-        writeln!(out, "#include <memory>");
-    }
-    if has_string {
-        writeln!(out, "#include <string>");
-    }
-    if has_box {
-        writeln!(out, "#include <type_traits>");
-    }
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {

From 33169bdd595cc3acbcb306bddde9a28b637e8ad2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 21:10:58 +0000
Subject: [PATCH 102/2232] Safe to assume more about the Box representation


https://doc.rust-lang.org/std/boxed/index.html:
So long as T: Sized, a Box<T> is guaranteed to be represented as a
single pointer and is also ABI-compatible with C pointers (i.e. the C
type T*).

---

diff --git a/gen/write.rs b/gen/write.rs
index 24c9c09..2bd6d3d 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -471,24 +471,9 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "void cxxbridge01$box${}$set_raw(::rust::Box<{}> *ptr, {} *raw) noexcept;",
-        instance, inner, inner
-    );
-    writeln!(
-        out,
         "void cxxbridge01$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(
-        out,
-        "const {} *cxxbridge01$box${}$deref(const ::rust::Box<{}> *ptr) noexcept;",
-        inner, instance, inner,
-    );
-    writeln!(
-        out,
-        "{} *cxxbridge01$box${}$deref_mut(::rust::Box<{}> *ptr) noexcept;",
-        inner, instance, inner,
-    );
     writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
 }
 
@@ -507,40 +492,9 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(
-        out,
-        "void Box<{}>::set_raw({} *raw) noexcept {{",
-        inner, inner,
-    );
-    writeln!(
-        out,
-        "  return cxxbridge01$box${}$set_raw(this, raw);",
-        instance
-    );
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(out, "  return cxxbridge01$box${}$drop(this);", instance);
     writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(
-        out,
-        "const {} *Box<{}>::deref() const noexcept {{",
-        inner, inner,
-    );
-    writeln!(out, "  return cxxbridge01$box${}$deref(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "{} *Box<{}>::deref_mut() noexcept {{", inner, inner);
-    writeln!(
-        out,
-        "  return cxxbridge01$box${}$deref_mut(this);",
-        instance
-    );
-    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
index 1ac3133..81bdad5 100644
--- a/include/cxxbridge.h
+++ b/include/cxxbridge.h
@@ -81,63 +81,60 @@ public:
   using pointer = typename std::add_pointer<value_type>::type;
 
   Box(const Box &other) : Box(*other) {}
-  Box(Box &&other) noexcept : repr(other.repr) { other.repr = 0; }
+  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
   Box(const T &val) {
     this->uninit();
-    ::new (this->deref_mut()) T(val);
+    ::new (this->ptr) T(val);
   }
   Box &operator=(const Box &other) {
     if (this != &other) {
-      if (this->repr) {
+      if (this->ptr) {
         **this = *other;
       } else {
         this->uninit();
-        ::new (this->deref_mut()) T(*other);
+        ::new (this->ptr) T(*other);
       }
     }
     return *this;
   }
   Box &operator=(Box &&other) noexcept {
-    if (this->repr) {
+    if (this->ptr) {
       this->drop();
     }
-    this->repr = other.repr;
-    other.repr = 0;
+    this->ptr = other.ptr;
+    other.ptr = nullptr;
     return *this;
   }
   ~Box() noexcept {
-    if (this->repr) {
+    if (this->ptr) {
       this->drop();
     }
   }
 
-  const T *operator->() const noexcept { return this->deref(); }
-  const T &operator*() const noexcept { return *this->deref(); }
-  T *operator->() noexcept { return this->deref_mut(); }
-  T &operator*() noexcept { return *this->deref_mut(); }
+  const T *operator->() const noexcept { return this->ptr; }
+  const T &operator*() const noexcept { return *this->ptr; }
+  T *operator->() noexcept { return this->ptr; }
+  T &operator*() noexcept { return *this->ptr; }
 
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
   static Box from_raw(T *raw) noexcept {
     Box box;
-    box.set_raw(raw);
+    box.ptr = raw;
     return box;
   }
 
   T *into_raw() noexcept {
-    T *raw = this->deref_mut();
-    this->repr = 0;
+    T *raw = this->ptr;
+    this->ptr = nullptr;
     return raw;
   }
 
 private:
   Box() noexcept {}
   void uninit() noexcept;
-  void set_raw(pointer) noexcept;
   void drop() noexcept;
-  const_pointer deref() const noexcept;
-  pointer deref_mut() noexcept;
-  uintptr_t repr;
+  T *ptr;
 };
 #endif // CXXBRIDGE01_RUST_BOX
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index dd5ab6e..8519c1e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -311,17 +311,11 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_prefix = format!("cxxbridge01$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
-    let link_set_raw = format!("{}set_raw", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
-    let link_deref = format!("{}deref", link_prefix);
-    let link_deref_mut = format!("{}deref_mut", link_prefix);
 
     let local_prefix = format_ident!("{}__box_", ident);
     let local_uninit = format_ident!("{}uninit", local_prefix);
-    let local_set_raw = format_ident!("{}set_raw", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
-    let local_deref = format_ident!("{}deref", local_prefix);
-    let local_deref_mut = format_ident!("{}deref_mut", local_prefix);
 
     let span = ident.span();
     quote_spanned! {span=>
@@ -336,32 +330,10 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
             );
         }
         #[doc(hidden)]
-        #[export_name = #link_set_raw]
-        unsafe extern "C" fn #local_set_raw(
-            this: *mut ::std::boxed::Box<#ident>,
-            raw: *mut #ident,
-        ) {
-            ::std::ptr::write(this, ::std::boxed::Box::from_raw(raw));
-        }
-        #[doc(hidden)]
         #[export_name = #link_drop]
         unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
             ::std::ptr::drop_in_place(this);
         }
-        #[doc(hidden)]
-        #[export_name = #link_deref]
-        unsafe extern "C" fn #local_deref(
-            this: *const ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
-        ) -> *const ::std::mem::MaybeUninit<#ident> {
-            &**this
-        }
-        #[doc(hidden)]
-        #[export_name = #link_deref_mut]
-        unsafe extern "C" fn #local_deref_mut(
-            this: *mut ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
-        ) -> *mut ::std::mem::MaybeUninit<#ident> {
-            &mut **this
-        }
     }
 }
 

From f51447e2b9a0fba982d17abf2401c1f3f0af7525 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 22:22:00 +0000
Subject: [PATCH 103/2232] Implement moving ownership of struct arguments to Rust


---

diff --git a/gen/write.rs b/gen/write.rs
index 2bd6d3d..187bf5e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -19,7 +19,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
     }
 
     write_includes(out, types);
-    write_include_cxxbridge(out, types);
+    write_include_cxxbridge(out, apis, types);
 
     out.next_section();
     for name in &namespace {
@@ -95,7 +95,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
     }
 }
 
-fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
+fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_box = false;
     for ty in types {
         if let Type::RustBox(_) = ty {
@@ -104,16 +104,47 @@ fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {
         }
     }
 
+    let mut needs_manually_drop = false;
+    'outer: for api in apis {
+        if let Api::RustFunction(efn) = api {
+            for arg in &efn.args {
+                if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                    needs_manually_drop = true;
+                    break 'outer;
+                }
+            }
+        }
+    }
+
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge01");
-    if needs_rust_box {
+
+    if needs_rust_box || needs_manually_drop {
         writeln!(out, "// #include \"cxxbridge.h\"");
+    }
+
+    if needs_rust_box {
+        out.next_section();
         for line in include::get("CXXBRIDGE01_RUST_BOX").lines() {
             if !line.trim_start().starts_with("//") {
                 writeln!(out, "{}", line);
             }
         }
     }
+
+    if needs_manually_drop {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union ManuallyDrop {{");
+        writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
+        );
+        writeln!(out, "  ~ManuallyDrop() {{}}");
+        writeln!(out, "}};");
+    }
+
     out.end_block("namespace cxxbridge01");
     out.end_block("namespace rust");
 }
@@ -274,6 +305,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, ";");
     } else {
         writeln!(out, " {{");
+        for arg in &efn.args {
+            if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                write!(out, "  ::rust::ManuallyDrop<");
+                write_type(out, &arg.ty);
+                writeln!(out, "> {}$(::std::move({0}));", arg.ident);
+            }
+        }
         write!(out, "  ");
         if indirect_return {
             write!(out, "char return$[sizeof(");
@@ -300,10 +338,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 _ => {}
             }
             write!(out, "{}", arg.ident);
-            match arg.ty {
+            match &arg.ty {
                 Type::RustBox(_) => write!(out, ".into_raw()"),
                 Type::UniquePtr(_) => write!(out, ".release()"),
                 Type::Str(_) => write!(out, ")"),
+                ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
                 _ => {}
             }
         }

From 09011c304b2c1f532b21e68c22443d467d5f56e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 22:46:46 +0000
Subject: [PATCH 104/2232] Fix alignment of by-value returns from Rust


---

diff --git a/gen/write.rs b/gen/write.rs
index 187bf5e..f0bcaf9 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -105,12 +105,18 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     let mut needs_manually_drop = false;
-    'outer: for api in apis {
+    let mut needs_maybe_uninit = false;
+    for api in apis {
         if let Api::RustFunction(efn) = api {
             for arg in &efn.args {
                 if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
                     needs_manually_drop = true;
-                    break 'outer;
+                    break;
+                }
+            }
+            if let Some(ret) = &efn.ret {
+                if types.needs_indirect_abi(ret) {
+                    needs_maybe_uninit = true;
                 }
             }
         }
@@ -119,7 +125,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge01");
 
-    if needs_rust_box || needs_manually_drop {
+    if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
         writeln!(out, "// #include \"cxxbridge.h\"");
     }
 
@@ -145,6 +151,16 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
+    if needs_maybe_uninit {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union MaybeUninit {{");
+        writeln!(out, "  T value;");
+        writeln!(out, "  MaybeUninit() {{}}");
+        writeln!(out, "  ~MaybeUninit() {{}}");
+        writeln!(out, "}};");
+    }
+
     out.end_block("namespace cxxbridge01");
     out.end_block("namespace rust");
 }
@@ -314,9 +330,9 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         write!(out, "  ");
         if indirect_return {
-            write!(out, "char return$[sizeof(");
+            write!(out, "::rust::MaybeUninit<");
             write_type(out, efn.ret.as_ref().unwrap());
-            writeln!(out, ")];");
+            writeln!(out, "> return$;");
             write!(out, "  ");
         } else if let Some(ret) = &efn.ret {
             write!(out, "return ");
@@ -350,17 +366,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             if !efn.args.is_empty() {
                 write!(out, ", ");
             }
-            write!(out, "reinterpret_cast<");
-            write_return_type(out, &efn.ret);
-            write!(out, "*>(return$)");
+            write!(out, "&return$.value");
         }
         writeln!(out, ");");
         if indirect_return {
-            write!(out, "  return ");
-            write_type(out, efn.ret.as_ref().unwrap());
-            write!(out, "(*reinterpret_cast<");
-            write_return_type(out, &efn.ret);
-            writeln!(out, "*>(return$));");
+            writeln!(out, "  return ::std::move(return$.value);");
         }
         writeln!(out, "}}");
     }

From be13d8ad2c42f951f7b4e11dfa91451c8fc99464 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 23:50:24 +0000
Subject: [PATCH 105/2232] Test Box returned from C++ to Rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 098253a..d1b33c2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -13,7 +13,7 @@ pub mod ffi {
 
         fn c_return_primitive() -> usize;
         fn c_return_shared() -> Shared;
-        //TODO fn c_return_box() -> Box<R>;
+        fn c_return_box() -> Box<R>;
         fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_str(shared: &Shared) -> &str;
@@ -55,7 +55,7 @@ pub mod ffi {
     }
 }
 
-type R = ();
+pub type R = usize;
 
 fn r_return_primitive() -> usize {
     2020
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c94e34d..adbf945 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -2,6 +2,7 @@
 #include "tests/ffi/lib.rs"
 
 extern "C" void cxx_test_suite_set_correct();
+extern "C" tests::R *cxx_test_suite_get_box();
 
 namespace tests {
 
@@ -13,6 +14,10 @@ size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
 
+rust::Box<R> c_return_box() {
+  return rust::Box<R>::from_raw(cxx_test_suite_get_box());
+}
+
 std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
diff --git a/tests/test.rs b/tests/test.rs
index 28e5c3b..eb06481 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -25,6 +25,7 @@ fn test_c_return() {
 
     assert_eq!(2020, ffi::c_return_primitive());
     assert_eq!(2020, ffi::c_return_shared().z);
+    assert_eq!(2020, *ffi::c_return_box());
     ffi::c_return_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
@@ -45,7 +46,7 @@ fn test_c_take() {
 
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
-    check!(ffi::c_take_box(Box::new(())));
+    check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
     check!(ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
@@ -69,3 +70,8 @@ fn test_c_call_r() {
     }
     check!(cxx_run_test());
 }
+
+#[no_mangle]
+extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
+    Box::into_raw(Box::new(2020usize))
+}

From a7d00e82810c09c65c1d9256aeea363a9c4ed3fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 06 2020 23:53:33 +0000
Subject: [PATCH 106/2232] Test &R passed from Rust to C++


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d1b33c2..e21a62c 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -24,7 +24,7 @@ pub mod ffi {
         fn c_take_shared(shared: Shared);
         fn c_take_box(r: Box<R>);
         fn c_take_unique_ptr(c: UniquePtr<C>);
-        //TODO fn c_take_ref_r(r: &R);
+        fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
         fn c_take_rust_string(s: String);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index adbf945..7b77c07 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -3,6 +3,7 @@
 
 extern "C" void cxx_test_suite_set_correct();
 extern "C" tests::R *cxx_test_suite_get_box();
+extern "C" bool cxx_test_suite_r_is_correct(const tests::R *);
 
 namespace tests {
 
@@ -48,8 +49,9 @@ void c_take_shared(Shared shared) {
 }
 
 void c_take_box(rust::Box<R> r) {
-  (void)r;
-  cxx_test_suite_set_correct();
+  if (cxx_test_suite_r_is_correct(&*r)) {
+    cxx_test_suite_set_correct();
+  }
 }
 
 void c_take_unique_ptr(std::unique_ptr<C> c) {
@@ -58,7 +60,11 @@ void c_take_unique_ptr(std::unique_ptr<C> c) {
   }
 }
 
-void c_take_ref_r(const R &r) { (void)r; }
+void c_take_ref_r(const R &r) {
+  if (cxx_test_suite_r_is_correct(&r)) {
+    cxx_test_suite_set_correct();
+  }
+}
 
 void c_take_ref_c(const C &c) {
   if (c.get() == 2020) {
diff --git a/tests/test.rs b/tests/test.rs
index eb06481..a30aefb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -75,3 +75,8 @@ fn test_c_call_r() {
 extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
     Box::into_raw(Box::new(2020usize))
 }
+
+#[no_mangle]
+unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
+    *r == 2020
+}

From 5cd8d61f9d01d92d71d254178614340804112fed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 00:18:44 +0000
Subject: [PATCH 107/2232] Implement returning Box from Rust to C++


---

diff --git a/gen/write.rs b/gen/write.rs
index f0bcaf9..7dc625e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -336,8 +336,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             write!(out, "  ");
         } else if let Some(ret) = &efn.ret {
             write!(out, "return ");
-            if let Type::Ref(_) = ret {
-                write!(out, "*");
+            match ret {
+                Type::RustBox(_) => {
+                    write_type(out, ret);
+                    write!(out, "::from_raw(");
+                }
+                Type::Ref(_) => write!(out, "*"),
+                _ => {}
             }
         }
         for name in out.namespace.clone() {
@@ -368,7 +373,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
             write!(out, "&return$.value");
         }
-        writeln!(out, ");");
+        write!(out, ")");
+        if let Some(ret) = &efn.ret {
+            if let Type::RustBox(_) = ret {
+                write!(out, ")");
+            }
+        }
+        writeln!(out, ";");
         if indirect_return {
             writeln!(out, "  return ::std::move(return$.value);");
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e21a62c..4c4f41c 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -36,7 +36,7 @@ pub mod ffi {
 
         fn r_return_primitive() -> usize;
         fn r_return_shared() -> Shared;
-        //TODO fn r_return_box() -> Box<R>;
+        fn r_return_box() -> Box<R>;
         //TODO fn r_return_unique_ptr() -> UniquePtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_str(shared: &Shared) -> &str;
@@ -65,6 +65,10 @@ fn r_return_shared() -> ffi::Shared {
     ffi::Shared { z: 2020 }
 }
 
+fn r_return_box() -> Box<R> {
+    Box::new(2020)
+}
+
 fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7b77c07..3d30ebe 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -102,6 +102,7 @@ extern "C" const char *cxx_run_test() noexcept {
 
   ASSERT(r_return_primitive() == 2020);
   ASSERT(r_return_shared().z == 2020);
+  ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));
   ASSERT(r_return_ref(Shared{2020}) == 2020);
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");

From 4b3a66edf1eb1d2b4fa648048969a3916e133fa7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 00:22:14 +0000
Subject: [PATCH 108/2232] Implement returning unique_ptr from Rust to C++


---

diff --git a/gen/write.rs b/gen/write.rs
index 7dc625e..601f7ef 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -341,6 +341,10 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                     write_type(out, ret);
                     write!(out, "::from_raw(");
                 }
+                Type::UniquePtr(_) => {
+                    write_type(out, ret);
+                    write!(out, "(");
+                }
                 Type::Ref(_) => write!(out, "*"),
                 _ => {}
             }
@@ -375,7 +379,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         write!(out, ")");
         if let Some(ret) = &efn.ret {
-            if let Type::RustBox(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
                 write!(out, ")");
             }
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4c4f41c..2df3337 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -37,7 +37,7 @@ pub mod ffi {
         fn r_return_primitive() -> usize;
         fn r_return_shared() -> Shared;
         fn r_return_box() -> Box<R>;
-        //TODO fn r_return_unique_ptr() -> UniquePtr<C>;
+        fn r_return_unique_ptr() -> UniquePtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
@@ -69,6 +69,13 @@ fn r_return_box() -> Box<R> {
     Box::new(2020)
 }
 
+fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
+    extern "C" {
+        fn cxx_test_suite_get_unique_ptr() -> *mut ffi::C;
+    }
+    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
+}
+
 fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3d30ebe..245cfbe 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -90,6 +90,10 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+extern "C" C *cxx_test_suite_get_unique_ptr() {
+  return std::unique_ptr<C>(new C{2020}).release();
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
@@ -103,6 +107,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r_return_primitive() == 2020);
   ASSERT(r_return_shared().z == 2020);
   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));
+  ASSERT(r_return_unique_ptr()->get() == 2020);
   ASSERT(r_return_ref(Shared{2020}) == 2020);
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");

From 2fe58c670c2307518751f55df9531c0eb8832ef3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 00:23:09 +0000
Subject: [PATCH 109/2232] Declare test suite helpers noexcept


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 245cfbe..c7d3c87 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,9 +1,9 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
 
-extern "C" void cxx_test_suite_set_correct();
-extern "C" tests::R *cxx_test_suite_get_box();
-extern "C" bool cxx_test_suite_r_is_correct(const tests::R *);
+extern "C" void cxx_test_suite_set_correct() noexcept;
+extern "C" tests::R *cxx_test_suite_get_box() noexcept;
+extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
 
 namespace tests {
 
@@ -90,7 +90,7 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
-extern "C" C *cxx_test_suite_get_unique_ptr() {
+extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
 

From 85db2486255239a1c35beaf8047a65140758ec35 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 00:26:46 +0000
Subject: [PATCH 110/2232] Test returning unique_ptr<string> from Rust to C++


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2df3337..c709678 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -41,7 +41,7 @@ pub mod ffi {
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
-        //TODO fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
+        fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -89,6 +89,13 @@ fn r_return_rust_string() -> String {
     "2020".to_owned()
 }
 
+fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
+    extern "C" {
+        fn cxx_test_suite_get_unique_ptr_string() -> *mut CxxString;
+    }
+    unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c7d3c87..350cd7d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -94,6 +94,10 @@ extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
 
+extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
+  return std::unique_ptr<std::string>(new std::string("2020")).release();
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
@@ -111,6 +115,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r_return_ref(Shared{2020}) == 2020);
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");
+  ASSERT(*r_return_unique_ptr_string() == "2020");
 
   r_take_primitive(2020);
   r_take_shared(Shared{2020});

From 68e5e26e81d69c98279fcb6fbbac5158f97ed399 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 19:16:11 +0000
Subject: [PATCH 111/2232] Exclude some unneeded directories from published crate


---

diff --git a/Cargo.toml b/Cargo.toml
index fdfadc8..886e01b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,6 +9,7 @@ description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
 readme = "README.md"
+exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 
 [badges]
 travis-ci = { repository = "dtolnay/cxx" }

From 5e93c89e32b4dd1f2e62cea290df4b3075d8b0b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 19:18:11 +0000
Subject: [PATCH 112/2232] Link license files into subcrate packages


---

diff --git a/cmd/LICENSE-APACHE b/cmd/LICENSE-APACHE
new file mode 120000
index 0000000..965b606
--- /dev/null
+++ b/cmd/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE
\ No newline at end of file
diff --git a/cmd/LICENSE-MIT b/cmd/LICENSE-MIT
new file mode 120000
index 0000000..76219eb
--- /dev/null
+++ b/cmd/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT
\ No newline at end of file
diff --git a/macro/LICENSE-APACHE b/macro/LICENSE-APACHE
new file mode 120000
index 0000000..965b606
--- /dev/null
+++ b/macro/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE
\ No newline at end of file
diff --git a/macro/LICENSE-MIT b/macro/LICENSE-MIT
new file mode 120000
index 0000000..76219eb
--- /dev/null
+++ b/macro/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT
\ No newline at end of file

From f370ea46c7487051f23cc97e6b76b41c643c93d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 07 2020 19:48:52 +0000
Subject: [PATCH 113/2232] Force cargo metadata to include dependencies on cmd


---

diff --git a/cmd/src/lib.rs b/cmd/src/lib.rs
new file mode 100644
index 0000000..8b1a393
--- /dev/null
+++ b/cmd/src/lib.rs
@@ -0,0 +1 @@
+// empty

From eb87f6541003447aa627f7cc1179ec883cf2adf9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 08 2020 03:47:50 +0000
Subject: [PATCH 114/2232] Update to bazelbuild/rules_rust master branch


---

diff --git a/WORKSPACE b/WORKSPACE
index 2feb345..3e3baed 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "b7ac870f4cab1cd7e56fd2cbe303f63d78d21cc1a6e3922f21887d373c090e20",
-    strip_prefix = "rules_rust-5a679d418955a122798f42c7bb67c55ca68a2493",
-    # Master branch as of 2020-02-24
-    url = "https://github.com/dtolnay/rules_rust/archive/5a679d418955a122798f42c7bb67c55ca68a2493.tar.gz",
+    sha256 = "abc75a5b6c8eda46a3d141921841e3577e9707b32d4d5b5cc156f7b8b28631ad",
+    strip_prefix = "rules_rust-d97f99628439df8bec89f5b7bc439f9d43d1586b",
+    # Master branch as of 2020-03-07
+    url = "https://github.com/bazelbuild/rules_rust/archive/d97f99628439df8bec89f5b7bc439f9d43d1586b.tar.gz",
 )
 
 http_archive(

From 736cbcad40735bc6a64a4fbe1609f8c372c93746 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 11 2020 23:51:38 +0000
Subject: [PATCH 115/2232] Move header include path to rust/cxx.h


---

diff --git a/BUCK b/BUCK
index 2d12753..2f80c9b 100644
--- a/BUCK
+++ b/BUCK
@@ -38,11 +38,11 @@ rust_binary(
 
 cxx_library(
     name = "core",
-    srcs = ["src/cxxbridge.cc"],
+    srcs = ["src/cxx.cc"],
     visibility = ["PUBLIC"],
-    header_namespace = "cxxbridge",
+    header_namespace = "rust",
     exported_headers = {
-        "cxxbridge.h": "include/cxxbridge.h",
+        "cxx.h": "include/cxx.h",
     },
     exported_linker_flags = ["-lstdc++"],
 )
diff --git a/BUILD b/BUILD
index 0405df1..db22203 100644
--- a/BUILD
+++ b/BUILD
@@ -3,7 +3,7 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
-    data = ["src/gen/include/cxxbridge.h"],
+    data = ["src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
@@ -23,7 +23,7 @@ rust_library(
 rust_binary(
     name = "codegen",
     srcs = glob(["cmd/src/**/*.rs"]),
-    data = ["cmd/src/gen/include/cxxbridge.h"],
+    data = ["cmd/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
@@ -39,16 +39,16 @@ rust_binary(
 
 cc_library(
     name = "core",
-    hdrs = ["include/cxxbridge.h"],
-    include_prefix = "cxxbridge",
+    hdrs = ["include/cxx.h"],
+    include_prefix = "rust",
     strip_include_prefix = "include",
     visibility = ["//visibility:public"],
 )
 
 cc_library(
     name = "core-lib",
-    srcs = ["src/cxxbridge.cc"],
-    hdrs = ["include/cxxbridge.h"],
+    srcs = ["src/cxx.cc"],
+    hdrs = ["include/cxx.h"],
 )
 
 rust_library(
diff --git a/README.md b/README.md
index 07ea91e..2886082 100644
--- a/README.md
+++ b/README.md
@@ -306,9 +306,9 @@ of functions.
 <tr><td></td><td></td><td></td></tr>
 </table>
 
-The C++ API of the `cxxbridge` namespace is defined by the *include/cxxbridge.h*
-file in this repo. You will need to include this header in your C++ code when
-working with those types.
+The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
+this repo. You will need to include this header in your C++ code when working
+with those types.
 
 The following types are intended to be supported "soon" but are just not
 implemented yet. I don't expect any of these to be hard to make work but it's a
diff --git a/build.rs b/build.rs
index ea562c2..bdda779 100644
--- a/build.rs
+++ b/build.rs
@@ -1,8 +1,8 @@
 fn main() {
     cc::Build::new()
-        .file("src/cxxbridge.cc")
+        .file("src/cxx.cc")
         .flag("-std=c++11")
         .compile("cxxbridge01");
-    println!("cargo:rerun-if-changed=src/cxxbridge.cc");
-    println!("cargo:rerun-if-changed=include/cxxbridge.h");
+    println!("cargo:rerun-if-changed=src/cxx.cc");
+    println!("cargo:rerun-if-changed=include/cxx.h");
 }
diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 26b6ef6..06b3bbe 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -14,7 +14,7 @@ use structopt::StructOpt;
     usage = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout
     cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit cxxbridge.h header to stdout",
+    cxxbridge --header                Emit rust/cxx.h header to stdout",
     help_message = "Print help information",
     version_message = "Print version information"
 )]
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index a579986..fafc474 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "cxxbridge/cxxbridge.h"
+#include "rust/cxx.h"
 #include <memory>
 #include <string>
 
diff --git a/gen/include.rs b/gen/include.rs
index e34d9d0..a4b416a 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,6 +1,6 @@
 use std::fmt::{self, Display};
 
-pub static HEADER: &str = include_str!("include/cxxbridge.h");
+pub static HEADER: &str = include_str!("include/cxx.h");
 
 pub fn get(guard: &str) -> &'static str {
     let ifndef = format!("#ifndef {}", guard);
@@ -10,7 +10,7 @@ pub fn get(guard: &str) -> &'static str {
     if let (Some(begin), Some(end)) = (begin, end) {
         &HEADER[begin..end + endif.len()]
     } else {
-        panic!("not found in cxxbridge.h header: {}", guard)
+        panic!("not found in cxx.h header: {}", guard)
     }
 }
 
diff --git a/gen/write.rs b/gen/write.rs
index 601f7ef..9ab98fa 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -126,7 +126,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.begin_block("inline namespace cxxbridge01");
 
     if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
-        writeln!(out, "// #include \"cxxbridge.h\"");
+        writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
     if needs_rust_box {
diff --git a/include/cxx.h b/include/cxx.h
new file mode 100644
index 0000000..81bdad5
--- /dev/null
+++ b/include/cxx.h
@@ -0,0 +1,155 @@
+#pragma once
+#include <array>
+#include <cstdint>
+#include <iosfwd>
+#include <string>
+#include <type_traits>
+
+namespace rust {
+inline namespace cxxbridge01 {
+
+struct unsafe_bitcopy_t;
+
+class String final {
+public:
+  String() noexcept;
+  String(const String &) noexcept;
+  String(String &&) noexcept;
+  ~String() noexcept;
+
+  String(const std::string &);
+  String(const char *);
+
+  String &operator=(const String &) noexcept;
+  String &operator=(String &&) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+
+  // Internal API only intended for the cxxbridge code generator.
+  String(unsafe_bitcopy_t, const String &) noexcept;
+
+private:
+  // Size and alignment statically verified by rust_string.rs.
+  std::array<uintptr_t, 3> repr;
+};
+
+class Str final {
+public:
+  Str() noexcept;
+  Str(const Str &) noexcept;
+
+  Str(const std::string &);
+  Str(const char *);
+  Str(std::string &&) = delete;
+
+  Str &operator=(Str) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+
+  // Repr is PRIVATE; must not be used other than by our generated code.
+  //
+  // Not necessarily ABI compatible with &str. Codegen will translate to
+  // cxx::rust_str::RustStr which matches this layout.
+  struct Repr {
+    const char *ptr;
+    size_t len;
+  };
+  Str(Repr) noexcept;
+  explicit operator Repr() noexcept;
+
+private:
+  Repr repr;
+};
+
+#ifndef CXXBRIDGE01_RUST_BOX
+#define CXXBRIDGE01_RUST_BOX
+template <typename T> class Box final {
+public:
+  using value_type = T;
+  using const_pointer = typename std::add_pointer<
+      typename std::add_const<value_type>::type>::type;
+  using pointer = typename std::add_pointer<value_type>::type;
+
+  Box(const Box &other) : Box(*other) {}
+  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
+  Box(const T &val) {
+    this->uninit();
+    ::new (this->ptr) T(val);
+  }
+  Box &operator=(const Box &other) {
+    if (this != &other) {
+      if (this->ptr) {
+        **this = *other;
+      } else {
+        this->uninit();
+        ::new (this->ptr) T(*other);
+      }
+    }
+    return *this;
+  }
+  Box &operator=(Box &&other) noexcept {
+    if (this->ptr) {
+      this->drop();
+    }
+    this->ptr = other.ptr;
+    other.ptr = nullptr;
+    return *this;
+  }
+  ~Box() noexcept {
+    if (this->ptr) {
+      this->drop();
+    }
+  }
+
+  const T *operator->() const noexcept { return this->ptr; }
+  const T &operator*() const noexcept { return *this->ptr; }
+  T *operator->() noexcept { return this->ptr; }
+  T &operator*() noexcept { return *this->ptr; }
+
+  // Important: requires that `raw` came from an into_raw call. Do not pass a
+  // pointer from `new` or any other source.
+  static Box from_raw(T *raw) noexcept {
+    Box box;
+    box.ptr = raw;
+    return box;
+  }
+
+  T *into_raw() noexcept {
+    T *raw = this->ptr;
+    this->ptr = nullptr;
+    return raw;
+  }
+
+private:
+  Box() noexcept {}
+  void uninit() noexcept;
+  void drop() noexcept;
+  T *ptr;
+};
+#endif // CXXBRIDGE01_RUST_BOX
+
+std::ostream &operator<<(std::ostream &, const String &);
+std::ostream &operator<<(std::ostream &, const Str &);
+
+// Snake case aliases for use in code that uses this style for type names.
+using string = String;
+using str = Str;
+template <class T> using box = Box<T>;
+
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+
+} // namespace cxxbridge01
+} // namespace rust
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
deleted file mode 100644
index 81bdad5..0000000
--- a/include/cxxbridge.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#pragma once
-#include <array>
-#include <cstdint>
-#include <iosfwd>
-#include <string>
-#include <type_traits>
-
-namespace rust {
-inline namespace cxxbridge01 {
-
-struct unsafe_bitcopy_t;
-
-class String final {
-public:
-  String() noexcept;
-  String(const String &) noexcept;
-  String(String &&) noexcept;
-  ~String() noexcept;
-
-  String(const std::string &);
-  String(const char *);
-
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
-
-  explicit operator std::string() const;
-
-  // Note: no null terminator.
-  const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
-
-  // Internal API only intended for the cxxbridge code generator.
-  String(unsafe_bitcopy_t, const String &) noexcept;
-
-private:
-  // Size and alignment statically verified by rust_string.rs.
-  std::array<uintptr_t, 3> repr;
-};
-
-class Str final {
-public:
-  Str() noexcept;
-  Str(const Str &) noexcept;
-
-  Str(const std::string &);
-  Str(const char *);
-  Str(std::string &&) = delete;
-
-  Str &operator=(Str) noexcept;
-
-  explicit operator std::string() const;
-
-  // Note: no null terminator.
-  const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
-
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
-  // Not necessarily ABI compatible with &str. Codegen will translate to
-  // cxx::rust_str::RustStr which matches this layout.
-  struct Repr {
-    const char *ptr;
-    size_t len;
-  };
-  Str(Repr) noexcept;
-  explicit operator Repr() noexcept;
-
-private:
-  Repr repr;
-};
-
-#ifndef CXXBRIDGE01_RUST_BOX
-#define CXXBRIDGE01_RUST_BOX
-template <typename T> class Box final {
-public:
-  using value_type = T;
-  using const_pointer = typename std::add_pointer<
-      typename std::add_const<value_type>::type>::type;
-  using pointer = typename std::add_pointer<value_type>::type;
-
-  Box(const Box &other) : Box(*other) {}
-  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  Box(const T &val) {
-    this->uninit();
-    ::new (this->ptr) T(val);
-  }
-  Box &operator=(const Box &other) {
-    if (this != &other) {
-      if (this->ptr) {
-        **this = *other;
-      } else {
-        this->uninit();
-        ::new (this->ptr) T(*other);
-      }
-    }
-    return *this;
-  }
-  Box &operator=(Box &&other) noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-    this->ptr = other.ptr;
-    other.ptr = nullptr;
-    return *this;
-  }
-  ~Box() noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-  }
-
-  const T *operator->() const noexcept { return this->ptr; }
-  const T &operator*() const noexcept { return *this->ptr; }
-  T *operator->() noexcept { return this->ptr; }
-  T &operator*() noexcept { return *this->ptr; }
-
-  // Important: requires that `raw` came from an into_raw call. Do not pass a
-  // pointer from `new` or any other source.
-  static Box from_raw(T *raw) noexcept {
-    Box box;
-    box.ptr = raw;
-    return box;
-  }
-
-  T *into_raw() noexcept {
-    T *raw = this->ptr;
-    this->ptr = nullptr;
-    return raw;
-  }
-
-private:
-  Box() noexcept {}
-  void uninit() noexcept;
-  void drop() noexcept;
-  T *ptr;
-};
-#endif // CXXBRIDGE01_RUST_BOX
-
-std::ostream &operator<<(std::ostream &, const String &);
-std::ostream &operator<<(std::ostream &, const Str &);
-
-// Snake case aliases for use in code that uses this style for type names.
-using string = String;
-using str = Str;
-template <class T> using box = Box<T>;
-
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-
-} // namespace cxxbridge01
-} // namespace rust
diff --git a/src/cxx.cc b/src/cxx.cc
new file mode 100644
index 0000000..f7b02ec
--- /dev/null
+++ b/src/cxx.cc
@@ -0,0 +1,166 @@
+#include "../include/cxx.h"
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+
+extern "C" {
+const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
+  return s.data();
+}
+
+size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
+  return s.length();
+}
+
+// rust::String
+void cxxbridge01$string$new(rust::String *self) noexcept;
+void cxxbridge01$string$clone(rust::String *self,
+                              const rust::String &other) noexcept;
+bool cxxbridge01$string$from(rust::String *self, const char *ptr,
+                             size_t len) noexcept;
+void cxxbridge01$string$drop(rust::String *self) noexcept;
+const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge01$string$len(const rust::String *self) noexcept;
+
+// rust::Str
+bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
+} // extern "C"
+
+namespace rust {
+inline namespace cxxbridge01 {
+
+String::String() noexcept { cxxbridge01$string$new(this); }
+
+String::String(const String &other) noexcept {
+  cxxbridge01$string$clone(this, other);
+}
+
+String::String(String &&other) noexcept {
+  this->repr = other.repr;
+  cxxbridge01$string$new(&other);
+}
+
+String::~String() noexcept { cxxbridge01$string$drop(this); }
+
+String::String(const std::string &s) {
+  auto ptr = s.data();
+  auto len = s.length();
+  if (!cxxbridge01$string$from(this, ptr, len)) {
+    throw std::invalid_argument("data for rust::String is not utf-8");
+  }
+}
+
+String::String(const char *s) {
+  auto len = strlen(s);
+  if (!cxxbridge01$string$from(this, s, len)) {
+    throw std::invalid_argument("data for rust::String is not utf-8");
+  }
+}
+
+String &String::operator=(const String &other) noexcept {
+  if (this != &other) {
+    cxxbridge01$string$drop(this);
+    cxxbridge01$string$clone(this, other);
+  }
+  return *this;
+}
+
+String &String::operator=(String &&other) noexcept {
+  if (this != &other) {
+    cxxbridge01$string$drop(this);
+    this->repr = other.repr;
+    cxxbridge01$string$new(&other);
+  }
+  return *this;
+}
+
+String::operator std::string() const {
+  return std::string(this->data(), this->size());
+}
+
+const char *String::data() const noexcept {
+  return cxxbridge01$string$ptr(this);
+}
+
+size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
+
+size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
+
+String::String(unsafe_bitcopy_t, const String &bits) noexcept
+    : repr(bits.repr) {}
+
+std::ostream &operator<<(std::ostream &os, const String &s) {
+  os.write(s.data(), s.size());
+  return os;
+}
+
+Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
+
+Str::Str(const Str &) noexcept = default;
+
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+    throw std::invalid_argument("data for rust::Str is not utf-8");
+  }
+}
+
+Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+    throw std::invalid_argument("data for rust::Str is not utf-8");
+  }
+}
+
+Str &Str::operator=(Str other) noexcept {
+  this->repr = other.repr;
+  return *this;
+}
+
+Str::operator std::string() const {
+  return std::string(this->data(), this->size());
+}
+
+const char *Str::data() const noexcept { return this->repr.ptr; }
+
+size_t Str::size() const noexcept { return this->repr.len; }
+
+size_t Str::length() const noexcept { return this->repr.len; }
+
+Str::Str(Repr repr_) noexcept : repr(repr_) {}
+
+Str::operator Repr() noexcept { return this->repr; }
+
+std::ostream &operator<<(std::ostream &os, const Str &s) {
+  os.write(s.data(), s.size());
+  return os;
+}
+
+} // namespace cxxbridge01
+} // namespace rust
+
+extern "C" {
+void cxxbridge01$unique_ptr$std$string$null(
+    std::unique_ptr<std::string> *ptr) noexcept {
+  new (ptr) std::unique_ptr<std::string>();
+}
+void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
+                                           std::string *value) noexcept {
+  new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
+}
+void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+                                           std::string *raw) noexcept {
+  new (ptr) std::unique_ptr<std::string>(raw);
+}
+const std::string *cxxbridge01$unique_ptr$std$string$get(
+    const std::unique_ptr<std::string> &ptr) noexcept {
+  return ptr.get();
+}
+std::string *cxxbridge01$unique_ptr$std$string$release(
+    std::unique_ptr<std::string> &ptr) noexcept {
+  return ptr.release();
+}
+void cxxbridge01$unique_ptr$std$string$drop(
+    std::unique_ptr<std::string> *ptr) noexcept {
+  ptr->~unique_ptr();
+}
+} // extern "C"
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
deleted file mode 100644
index b44204d..0000000
--- a/src/cxxbridge.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-#include "../include/cxxbridge.h"
-#include <cstring>
-#include <iostream>
-#include <memory>
-#include <stdexcept>
-
-extern "C" {
-const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
-  return s.data();
-}
-
-size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
-  return s.length();
-}
-
-// rust::String
-void cxxbridge01$string$new(rust::String *self) noexcept;
-void cxxbridge01$string$clone(rust::String *self,
-                              const rust::String &other) noexcept;
-bool cxxbridge01$string$from(rust::String *self, const char *ptr,
-                             size_t len) noexcept;
-void cxxbridge01$string$drop(rust::String *self) noexcept;
-const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge01$string$len(const rust::String *self) noexcept;
-
-// rust::Str
-bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
-} // extern "C"
-
-namespace rust {
-inline namespace cxxbridge01 {
-
-String::String() noexcept { cxxbridge01$string$new(this); }
-
-String::String(const String &other) noexcept {
-  cxxbridge01$string$clone(this, other);
-}
-
-String::String(String &&other) noexcept {
-  this->repr = other.repr;
-  cxxbridge01$string$new(&other);
-}
-
-String::~String() noexcept { cxxbridge01$string$drop(this); }
-
-String::String(const std::string &s) {
-  auto ptr = s.data();
-  auto len = s.length();
-  if (!cxxbridge01$string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
-  }
-}
-
-String::String(const char *s) {
-  auto len = strlen(s);
-  if (!cxxbridge01$string$from(this, s, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
-  }
-}
-
-String &String::operator=(const String &other) noexcept {
-  if (this != &other) {
-    cxxbridge01$string$drop(this);
-    cxxbridge01$string$clone(this, other);
-  }
-  return *this;
-}
-
-String &String::operator=(String &&other) noexcept {
-  if (this != &other) {
-    cxxbridge01$string$drop(this);
-    this->repr = other.repr;
-    cxxbridge01$string$new(&other);
-  }
-  return *this;
-}
-
-String::operator std::string() const {
-  return std::string(this->data(), this->size());
-}
-
-const char *String::data() const noexcept {
-  return cxxbridge01$string$ptr(this);
-}
-
-size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
-
-size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
-
-String::String(unsafe_bitcopy_t, const String &bits) noexcept
-    : repr(bits.repr) {}
-
-std::ostream &operator<<(std::ostream &os, const String &s) {
-  os.write(s.data(), s.size());
-  return os;
-}
-
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
-
-Str::Str(const Str &) noexcept = default;
-
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
-  }
-}
-
-Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
-  }
-}
-
-Str &Str::operator=(Str other) noexcept {
-  this->repr = other.repr;
-  return *this;
-}
-
-Str::operator std::string() const {
-  return std::string(this->data(), this->size());
-}
-
-const char *Str::data() const noexcept { return this->repr.ptr; }
-
-size_t Str::size() const noexcept { return this->repr.len; }
-
-size_t Str::length() const noexcept { return this->repr.len; }
-
-Str::Str(Repr repr_) noexcept : repr(repr_) {}
-
-Str::operator Repr() noexcept { return this->repr; }
-
-std::ostream &operator<<(std::ostream &os, const Str &s) {
-  os.write(s.data(), s.size());
-  return os;
-}
-
-} // namespace cxxbridge01
-} // namespace rust
-
-extern "C" {
-void cxxbridge01$unique_ptr$std$string$null(
-    std::unique_ptr<std::string> *ptr) noexcept {
-  new (ptr) std::unique_ptr<std::string>();
-}
-void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
-                                           std::string *value) noexcept {
-  new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
-}
-void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
-                                           std::string *raw) noexcept {
-  new (ptr) std::unique_ptr<std::string>(raw);
-}
-const std::string *cxxbridge01$unique_ptr$std$string$get(
-    const std::unique_ptr<std::string> &ptr) noexcept {
-  return ptr.get();
-}
-std::string *cxxbridge01$unique_ptr$std$string$release(
-    std::unique_ptr<std::string> &ptr) noexcept {
-  return ptr.release();
-}
-void cxxbridge01$unique_ptr$std$string$drop(
-    std::unique_ptr<std::string> *ptr) noexcept {
-  ptr->~unique_ptr();
-}
-} // extern "C"
diff --git a/src/lib.rs b/src/lib.rs
index 006159a..316918f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -310,9 +310,9 @@
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
 //!
-//! The C++ API of the `cxxbridge` namespace is defined by the
-//! *include/cxxbridge.h* file in https://github.com/dtolnay/cxx. You will need
-//! to include this header in your C++ code when working with those types.
+//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
+//! in https://github.com/dtolnay/cxx. You will need to include this header in
+//! your C++ code when working with those types.
 //!
 //! The following types are intended to be supported "soon" but are just not
 //! implemented yet. I don't expect any of these to be hard to make work but
@@ -463,10 +463,10 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let mut build = paths::cc_build();
     build.file(&bridge_path);
 
-    let ref cxxbridge_h = paths::include_dir()?.join("cxxbridge").join("cxxbridge.h");
-    let _ = fs::create_dir_all(cxxbridge_h.parent().unwrap());
-    let _ = fs::remove_file(cxxbridge_h);
-    let _ = fs::write(cxxbridge_h, gen::include::HEADER);
+    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
+    let _ = fs::remove_file(cxx_h);
+    let _ = fs::write(cxx_h, gen::include::HEADER);
 
     Ok(build)
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index f41cc5e..7cff6fa 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "cxxbridge/cxxbridge.h"
+#include "rust/cxx.h"
 #include <memory>
 #include <string>
 

From 77c18a0f731d0cd9c8d424839e78cba39edfdde1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 12 2020 00:04:31 +0000
Subject: [PATCH 116/2232] Merge pull request #62 from dtolnay/include


Move header include path to rust/cxx.h
---

diff --git a/BUCK b/BUCK
index 2d12753..2f80c9b 100644
--- a/BUCK
+++ b/BUCK
@@ -38,11 +38,11 @@ rust_binary(
 
 cxx_library(
     name = "core",
-    srcs = ["src/cxxbridge.cc"],
+    srcs = ["src/cxx.cc"],
     visibility = ["PUBLIC"],
-    header_namespace = "cxxbridge",
+    header_namespace = "rust",
     exported_headers = {
-        "cxxbridge.h": "include/cxxbridge.h",
+        "cxx.h": "include/cxx.h",
     },
     exported_linker_flags = ["-lstdc++"],
 )
diff --git a/BUILD b/BUILD
index 0405df1..db22203 100644
--- a/BUILD
+++ b/BUILD
@@ -3,7 +3,7 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
-    data = ["src/gen/include/cxxbridge.h"],
+    data = ["src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
@@ -23,7 +23,7 @@ rust_library(
 rust_binary(
     name = "codegen",
     srcs = glob(["cmd/src/**/*.rs"]),
-    data = ["cmd/src/gen/include/cxxbridge.h"],
+    data = ["cmd/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
@@ -39,16 +39,16 @@ rust_binary(
 
 cc_library(
     name = "core",
-    hdrs = ["include/cxxbridge.h"],
-    include_prefix = "cxxbridge",
+    hdrs = ["include/cxx.h"],
+    include_prefix = "rust",
     strip_include_prefix = "include",
     visibility = ["//visibility:public"],
 )
 
 cc_library(
     name = "core-lib",
-    srcs = ["src/cxxbridge.cc"],
-    hdrs = ["include/cxxbridge.h"],
+    srcs = ["src/cxx.cc"],
+    hdrs = ["include/cxx.h"],
 )
 
 rust_library(
diff --git a/README.md b/README.md
index 07ea91e..2886082 100644
--- a/README.md
+++ b/README.md
@@ -306,9 +306,9 @@ of functions.
 <tr><td></td><td></td><td></td></tr>
 </table>
 
-The C++ API of the `cxxbridge` namespace is defined by the *include/cxxbridge.h*
-file in this repo. You will need to include this header in your C++ code when
-working with those types.
+The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
+this repo. You will need to include this header in your C++ code when working
+with those types.
 
 The following types are intended to be supported "soon" but are just not
 implemented yet. I don't expect any of these to be hard to make work but it's a
diff --git a/build.rs b/build.rs
index ea562c2..bdda779 100644
--- a/build.rs
+++ b/build.rs
@@ -1,8 +1,8 @@
 fn main() {
     cc::Build::new()
-        .file("src/cxxbridge.cc")
+        .file("src/cxx.cc")
         .flag("-std=c++11")
         .compile("cxxbridge01");
-    println!("cargo:rerun-if-changed=src/cxxbridge.cc");
-    println!("cargo:rerun-if-changed=include/cxxbridge.h");
+    println!("cargo:rerun-if-changed=src/cxx.cc");
+    println!("cargo:rerun-if-changed=include/cxx.h");
 }
diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 26b6ef6..06b3bbe 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -14,7 +14,7 @@ use structopt::StructOpt;
     usage = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout
     cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit cxxbridge.h header to stdout",
+    cxxbridge --header                Emit rust/cxx.h header to stdout",
     help_message = "Print help information",
     version_message = "Print version information"
 )]
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index a579986..fafc474 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "cxxbridge/cxxbridge.h"
+#include "rust/cxx.h"
 #include <memory>
 #include <string>
 
diff --git a/gen/include.rs b/gen/include.rs
index e34d9d0..a4b416a 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,6 +1,6 @@
 use std::fmt::{self, Display};
 
-pub static HEADER: &str = include_str!("include/cxxbridge.h");
+pub static HEADER: &str = include_str!("include/cxx.h");
 
 pub fn get(guard: &str) -> &'static str {
     let ifndef = format!("#ifndef {}", guard);
@@ -10,7 +10,7 @@ pub fn get(guard: &str) -> &'static str {
     if let (Some(begin), Some(end)) = (begin, end) {
         &HEADER[begin..end + endif.len()]
     } else {
-        panic!("not found in cxxbridge.h header: {}", guard)
+        panic!("not found in cxx.h header: {}", guard)
     }
 }
 
diff --git a/gen/write.rs b/gen/write.rs
index 601f7ef..9ab98fa 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -126,7 +126,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.begin_block("inline namespace cxxbridge01");
 
     if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
-        writeln!(out, "// #include \"cxxbridge.h\"");
+        writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
     if needs_rust_box {
diff --git a/include/cxx.h b/include/cxx.h
new file mode 100644
index 0000000..81bdad5
--- /dev/null
+++ b/include/cxx.h
@@ -0,0 +1,155 @@
+#pragma once
+#include <array>
+#include <cstdint>
+#include <iosfwd>
+#include <string>
+#include <type_traits>
+
+namespace rust {
+inline namespace cxxbridge01 {
+
+struct unsafe_bitcopy_t;
+
+class String final {
+public:
+  String() noexcept;
+  String(const String &) noexcept;
+  String(String &&) noexcept;
+  ~String() noexcept;
+
+  String(const std::string &);
+  String(const char *);
+
+  String &operator=(const String &) noexcept;
+  String &operator=(String &&) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+
+  // Internal API only intended for the cxxbridge code generator.
+  String(unsafe_bitcopy_t, const String &) noexcept;
+
+private:
+  // Size and alignment statically verified by rust_string.rs.
+  std::array<uintptr_t, 3> repr;
+};
+
+class Str final {
+public:
+  Str() noexcept;
+  Str(const Str &) noexcept;
+
+  Str(const std::string &);
+  Str(const char *);
+  Str(std::string &&) = delete;
+
+  Str &operator=(Str) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+
+  // Repr is PRIVATE; must not be used other than by our generated code.
+  //
+  // Not necessarily ABI compatible with &str. Codegen will translate to
+  // cxx::rust_str::RustStr which matches this layout.
+  struct Repr {
+    const char *ptr;
+    size_t len;
+  };
+  Str(Repr) noexcept;
+  explicit operator Repr() noexcept;
+
+private:
+  Repr repr;
+};
+
+#ifndef CXXBRIDGE01_RUST_BOX
+#define CXXBRIDGE01_RUST_BOX
+template <typename T> class Box final {
+public:
+  using value_type = T;
+  using const_pointer = typename std::add_pointer<
+      typename std::add_const<value_type>::type>::type;
+  using pointer = typename std::add_pointer<value_type>::type;
+
+  Box(const Box &other) : Box(*other) {}
+  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
+  Box(const T &val) {
+    this->uninit();
+    ::new (this->ptr) T(val);
+  }
+  Box &operator=(const Box &other) {
+    if (this != &other) {
+      if (this->ptr) {
+        **this = *other;
+      } else {
+        this->uninit();
+        ::new (this->ptr) T(*other);
+      }
+    }
+    return *this;
+  }
+  Box &operator=(Box &&other) noexcept {
+    if (this->ptr) {
+      this->drop();
+    }
+    this->ptr = other.ptr;
+    other.ptr = nullptr;
+    return *this;
+  }
+  ~Box() noexcept {
+    if (this->ptr) {
+      this->drop();
+    }
+  }
+
+  const T *operator->() const noexcept { return this->ptr; }
+  const T &operator*() const noexcept { return *this->ptr; }
+  T *operator->() noexcept { return this->ptr; }
+  T &operator*() noexcept { return *this->ptr; }
+
+  // Important: requires that `raw` came from an into_raw call. Do not pass a
+  // pointer from `new` or any other source.
+  static Box from_raw(T *raw) noexcept {
+    Box box;
+    box.ptr = raw;
+    return box;
+  }
+
+  T *into_raw() noexcept {
+    T *raw = this->ptr;
+    this->ptr = nullptr;
+    return raw;
+  }
+
+private:
+  Box() noexcept {}
+  void uninit() noexcept;
+  void drop() noexcept;
+  T *ptr;
+};
+#endif // CXXBRIDGE01_RUST_BOX
+
+std::ostream &operator<<(std::ostream &, const String &);
+std::ostream &operator<<(std::ostream &, const Str &);
+
+// Snake case aliases for use in code that uses this style for type names.
+using string = String;
+using str = Str;
+template <class T> using box = Box<T>;
+
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+
+} // namespace cxxbridge01
+} // namespace rust
diff --git a/include/cxxbridge.h b/include/cxxbridge.h
deleted file mode 100644
index 81bdad5..0000000
--- a/include/cxxbridge.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#pragma once
-#include <array>
-#include <cstdint>
-#include <iosfwd>
-#include <string>
-#include <type_traits>
-
-namespace rust {
-inline namespace cxxbridge01 {
-
-struct unsafe_bitcopy_t;
-
-class String final {
-public:
-  String() noexcept;
-  String(const String &) noexcept;
-  String(String &&) noexcept;
-  ~String() noexcept;
-
-  String(const std::string &);
-  String(const char *);
-
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
-
-  explicit operator std::string() const;
-
-  // Note: no null terminator.
-  const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
-
-  // Internal API only intended for the cxxbridge code generator.
-  String(unsafe_bitcopy_t, const String &) noexcept;
-
-private:
-  // Size and alignment statically verified by rust_string.rs.
-  std::array<uintptr_t, 3> repr;
-};
-
-class Str final {
-public:
-  Str() noexcept;
-  Str(const Str &) noexcept;
-
-  Str(const std::string &);
-  Str(const char *);
-  Str(std::string &&) = delete;
-
-  Str &operator=(Str) noexcept;
-
-  explicit operator std::string() const;
-
-  // Note: no null terminator.
-  const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
-
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
-  // Not necessarily ABI compatible with &str. Codegen will translate to
-  // cxx::rust_str::RustStr which matches this layout.
-  struct Repr {
-    const char *ptr;
-    size_t len;
-  };
-  Str(Repr) noexcept;
-  explicit operator Repr() noexcept;
-
-private:
-  Repr repr;
-};
-
-#ifndef CXXBRIDGE01_RUST_BOX
-#define CXXBRIDGE01_RUST_BOX
-template <typename T> class Box final {
-public:
-  using value_type = T;
-  using const_pointer = typename std::add_pointer<
-      typename std::add_const<value_type>::type>::type;
-  using pointer = typename std::add_pointer<value_type>::type;
-
-  Box(const Box &other) : Box(*other) {}
-  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  Box(const T &val) {
-    this->uninit();
-    ::new (this->ptr) T(val);
-  }
-  Box &operator=(const Box &other) {
-    if (this != &other) {
-      if (this->ptr) {
-        **this = *other;
-      } else {
-        this->uninit();
-        ::new (this->ptr) T(*other);
-      }
-    }
-    return *this;
-  }
-  Box &operator=(Box &&other) noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-    this->ptr = other.ptr;
-    other.ptr = nullptr;
-    return *this;
-  }
-  ~Box() noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-  }
-
-  const T *operator->() const noexcept { return this->ptr; }
-  const T &operator*() const noexcept { return *this->ptr; }
-  T *operator->() noexcept { return this->ptr; }
-  T &operator*() noexcept { return *this->ptr; }
-
-  // Important: requires that `raw` came from an into_raw call. Do not pass a
-  // pointer from `new` or any other source.
-  static Box from_raw(T *raw) noexcept {
-    Box box;
-    box.ptr = raw;
-    return box;
-  }
-
-  T *into_raw() noexcept {
-    T *raw = this->ptr;
-    this->ptr = nullptr;
-    return raw;
-  }
-
-private:
-  Box() noexcept {}
-  void uninit() noexcept;
-  void drop() noexcept;
-  T *ptr;
-};
-#endif // CXXBRIDGE01_RUST_BOX
-
-std::ostream &operator<<(std::ostream &, const String &);
-std::ostream &operator<<(std::ostream &, const Str &);
-
-// Snake case aliases for use in code that uses this style for type names.
-using string = String;
-using str = Str;
-template <class T> using box = Box<T>;
-
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-
-} // namespace cxxbridge01
-} // namespace rust
diff --git a/src/cxx.cc b/src/cxx.cc
new file mode 100644
index 0000000..f7b02ec
--- /dev/null
+++ b/src/cxx.cc
@@ -0,0 +1,166 @@
+#include "../include/cxx.h"
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <stdexcept>
+
+extern "C" {
+const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
+  return s.data();
+}
+
+size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
+  return s.length();
+}
+
+// rust::String
+void cxxbridge01$string$new(rust::String *self) noexcept;
+void cxxbridge01$string$clone(rust::String *self,
+                              const rust::String &other) noexcept;
+bool cxxbridge01$string$from(rust::String *self, const char *ptr,
+                             size_t len) noexcept;
+void cxxbridge01$string$drop(rust::String *self) noexcept;
+const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge01$string$len(const rust::String *self) noexcept;
+
+// rust::Str
+bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
+} // extern "C"
+
+namespace rust {
+inline namespace cxxbridge01 {
+
+String::String() noexcept { cxxbridge01$string$new(this); }
+
+String::String(const String &other) noexcept {
+  cxxbridge01$string$clone(this, other);
+}
+
+String::String(String &&other) noexcept {
+  this->repr = other.repr;
+  cxxbridge01$string$new(&other);
+}
+
+String::~String() noexcept { cxxbridge01$string$drop(this); }
+
+String::String(const std::string &s) {
+  auto ptr = s.data();
+  auto len = s.length();
+  if (!cxxbridge01$string$from(this, ptr, len)) {
+    throw std::invalid_argument("data for rust::String is not utf-8");
+  }
+}
+
+String::String(const char *s) {
+  auto len = strlen(s);
+  if (!cxxbridge01$string$from(this, s, len)) {
+    throw std::invalid_argument("data for rust::String is not utf-8");
+  }
+}
+
+String &String::operator=(const String &other) noexcept {
+  if (this != &other) {
+    cxxbridge01$string$drop(this);
+    cxxbridge01$string$clone(this, other);
+  }
+  return *this;
+}
+
+String &String::operator=(String &&other) noexcept {
+  if (this != &other) {
+    cxxbridge01$string$drop(this);
+    this->repr = other.repr;
+    cxxbridge01$string$new(&other);
+  }
+  return *this;
+}
+
+String::operator std::string() const {
+  return std::string(this->data(), this->size());
+}
+
+const char *String::data() const noexcept {
+  return cxxbridge01$string$ptr(this);
+}
+
+size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
+
+size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
+
+String::String(unsafe_bitcopy_t, const String &bits) noexcept
+    : repr(bits.repr) {}
+
+std::ostream &operator<<(std::ostream &os, const String &s) {
+  os.write(s.data(), s.size());
+  return os;
+}
+
+Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
+
+Str::Str(const Str &) noexcept = default;
+
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+    throw std::invalid_argument("data for rust::Str is not utf-8");
+  }
+}
+
+Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
+  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+    throw std::invalid_argument("data for rust::Str is not utf-8");
+  }
+}
+
+Str &Str::operator=(Str other) noexcept {
+  this->repr = other.repr;
+  return *this;
+}
+
+Str::operator std::string() const {
+  return std::string(this->data(), this->size());
+}
+
+const char *Str::data() const noexcept { return this->repr.ptr; }
+
+size_t Str::size() const noexcept { return this->repr.len; }
+
+size_t Str::length() const noexcept { return this->repr.len; }
+
+Str::Str(Repr repr_) noexcept : repr(repr_) {}
+
+Str::operator Repr() noexcept { return this->repr; }
+
+std::ostream &operator<<(std::ostream &os, const Str &s) {
+  os.write(s.data(), s.size());
+  return os;
+}
+
+} // namespace cxxbridge01
+} // namespace rust
+
+extern "C" {
+void cxxbridge01$unique_ptr$std$string$null(
+    std::unique_ptr<std::string> *ptr) noexcept {
+  new (ptr) std::unique_ptr<std::string>();
+}
+void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
+                                           std::string *value) noexcept {
+  new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
+}
+void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+                                           std::string *raw) noexcept {
+  new (ptr) std::unique_ptr<std::string>(raw);
+}
+const std::string *cxxbridge01$unique_ptr$std$string$get(
+    const std::unique_ptr<std::string> &ptr) noexcept {
+  return ptr.get();
+}
+std::string *cxxbridge01$unique_ptr$std$string$release(
+    std::unique_ptr<std::string> &ptr) noexcept {
+  return ptr.release();
+}
+void cxxbridge01$unique_ptr$std$string$drop(
+    std::unique_ptr<std::string> *ptr) noexcept {
+  ptr->~unique_ptr();
+}
+} // extern "C"
diff --git a/src/cxxbridge.cc b/src/cxxbridge.cc
deleted file mode 100644
index b44204d..0000000
--- a/src/cxxbridge.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-#include "../include/cxxbridge.h"
-#include <cstring>
-#include <iostream>
-#include <memory>
-#include <stdexcept>
-
-extern "C" {
-const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
-  return s.data();
-}
-
-size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
-  return s.length();
-}
-
-// rust::String
-void cxxbridge01$string$new(rust::String *self) noexcept;
-void cxxbridge01$string$clone(rust::String *self,
-                              const rust::String &other) noexcept;
-bool cxxbridge01$string$from(rust::String *self, const char *ptr,
-                             size_t len) noexcept;
-void cxxbridge01$string$drop(rust::String *self) noexcept;
-const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge01$string$len(const rust::String *self) noexcept;
-
-// rust::Str
-bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
-} // extern "C"
-
-namespace rust {
-inline namespace cxxbridge01 {
-
-String::String() noexcept { cxxbridge01$string$new(this); }
-
-String::String(const String &other) noexcept {
-  cxxbridge01$string$clone(this, other);
-}
-
-String::String(String &&other) noexcept {
-  this->repr = other.repr;
-  cxxbridge01$string$new(&other);
-}
-
-String::~String() noexcept { cxxbridge01$string$drop(this); }
-
-String::String(const std::string &s) {
-  auto ptr = s.data();
-  auto len = s.length();
-  if (!cxxbridge01$string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
-  }
-}
-
-String::String(const char *s) {
-  auto len = strlen(s);
-  if (!cxxbridge01$string$from(this, s, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
-  }
-}
-
-String &String::operator=(const String &other) noexcept {
-  if (this != &other) {
-    cxxbridge01$string$drop(this);
-    cxxbridge01$string$clone(this, other);
-  }
-  return *this;
-}
-
-String &String::operator=(String &&other) noexcept {
-  if (this != &other) {
-    cxxbridge01$string$drop(this);
-    this->repr = other.repr;
-    cxxbridge01$string$new(&other);
-  }
-  return *this;
-}
-
-String::operator std::string() const {
-  return std::string(this->data(), this->size());
-}
-
-const char *String::data() const noexcept {
-  return cxxbridge01$string$ptr(this);
-}
-
-size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
-
-size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
-
-String::String(unsafe_bitcopy_t, const String &bits) noexcept
-    : repr(bits.repr) {}
-
-std::ostream &operator<<(std::ostream &os, const String &s) {
-  os.write(s.data(), s.size());
-  return os;
-}
-
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
-
-Str::Str(const Str &) noexcept = default;
-
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
-  }
-}
-
-Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
-  }
-}
-
-Str &Str::operator=(Str other) noexcept {
-  this->repr = other.repr;
-  return *this;
-}
-
-Str::operator std::string() const {
-  return std::string(this->data(), this->size());
-}
-
-const char *Str::data() const noexcept { return this->repr.ptr; }
-
-size_t Str::size() const noexcept { return this->repr.len; }
-
-size_t Str::length() const noexcept { return this->repr.len; }
-
-Str::Str(Repr repr_) noexcept : repr(repr_) {}
-
-Str::operator Repr() noexcept { return this->repr; }
-
-std::ostream &operator<<(std::ostream &os, const Str &s) {
-  os.write(s.data(), s.size());
-  return os;
-}
-
-} // namespace cxxbridge01
-} // namespace rust
-
-extern "C" {
-void cxxbridge01$unique_ptr$std$string$null(
-    std::unique_ptr<std::string> *ptr) noexcept {
-  new (ptr) std::unique_ptr<std::string>();
-}
-void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
-                                           std::string *value) noexcept {
-  new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
-}
-void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
-                                           std::string *raw) noexcept {
-  new (ptr) std::unique_ptr<std::string>(raw);
-}
-const std::string *cxxbridge01$unique_ptr$std$string$get(
-    const std::unique_ptr<std::string> &ptr) noexcept {
-  return ptr.get();
-}
-std::string *cxxbridge01$unique_ptr$std$string$release(
-    std::unique_ptr<std::string> &ptr) noexcept {
-  return ptr.release();
-}
-void cxxbridge01$unique_ptr$std$string$drop(
-    std::unique_ptr<std::string> *ptr) noexcept {
-  ptr->~unique_ptr();
-}
-} // extern "C"
diff --git a/src/lib.rs b/src/lib.rs
index 006159a..316918f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -310,9 +310,9 @@
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
 //!
-//! The C++ API of the `cxxbridge` namespace is defined by the
-//! *include/cxxbridge.h* file in https://github.com/dtolnay/cxx. You will need
-//! to include this header in your C++ code when working with those types.
+//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
+//! in https://github.com/dtolnay/cxx. You will need to include this header in
+//! your C++ code when working with those types.
 //!
 //! The following types are intended to be supported "soon" but are just not
 //! implemented yet. I don't expect any of these to be hard to make work but
@@ -463,10 +463,10 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let mut build = paths::cc_build();
     build.file(&bridge_path);
 
-    let ref cxxbridge_h = paths::include_dir()?.join("cxxbridge").join("cxxbridge.h");
-    let _ = fs::create_dir_all(cxxbridge_h.parent().unwrap());
-    let _ = fs::remove_file(cxxbridge_h);
-    let _ = fs::write(cxxbridge_h, gen::include::HEADER);
+    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
+    let _ = fs::remove_file(cxx_h);
+    let _ = fs::write(cxx_h, gen::include::HEADER);
 
     Ok(build)
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index f41cc5e..7cff6fa 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "cxxbridge/cxxbridge.h"
+#include "rust/cxx.h"
 #include <memory>
 #include <string>
 

From bfc8dced0cc9758fbf918b8e6a69dad39e01b1ee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 12 2020 07:48:04 +0000
Subject: [PATCH 117/2232] Set html_root_url


---

diff --git a/Cargo.toml b/Cargo.toml
index 886e01b..47a45fe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.1.2"
+version = "0.1.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge01"
diff --git a/src/lib.rs b/src/lib.rs
index 316918f..ffa8352 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -329,6 +329,7 @@
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! </table>
 
+#![doc(html_root_url = "https://docs.rs/cxx/0.1.2")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::large_enum_variant,

From d763f186265c680503b8630cfe19772af1397b87 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 12 2020 07:50:19 +0000
Subject: [PATCH 118/2232] Linkify some links to the github repo


---

diff --git a/src/lib.rs b/src/lib.rs
index ffa8352..47e5367 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -50,7 +50,7 @@
 //! # Example
 //!
 //! A runnable version of this example is provided under the *demo-rs* directory
-//! of https://github.com/dtolnay/cxx (with the C++ side of the implementation
+//! of [https://github.com/dtolnay/cxx] (with the C++ side of the implementation
 //! in the *demo-cxx* directory). To try it out, jump into demo-rs and run
 //! `cargo run`.
 //!
@@ -240,7 +240,7 @@
 //! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
 //! way of invoking the C++ code generator as a standalone command line tool.
 //! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
-//! built from the *cmd* directory of https://github.com/dtolnay/cxx.
+//! built from the *cmd* directory of [https://github.com/dtolnay/cxx].
 //!
 //! ```bash
 //! $ cargo install cxxbridge-cmd
@@ -311,7 +311,7 @@
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
-//! in https://github.com/dtolnay/cxx. You will need to include this header in
+//! in [https://github.com/dtolnay/cxx]. You will need to include this header in
 //! your C++ code when working with those types.
 //!
 //! The following types are intended to be supported "soon" but are just not
@@ -328,6 +328,8 @@
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! </table>
+//!
+//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![doc(html_root_url = "https://docs.rs/cxx/0.1.2")]
 #![deny(improper_ctypes)]
@@ -406,8 +408,9 @@ use std::process;
 /// ```
 ///
 /// A runnable working setup with this build script is shown in the
-/// *demo-rs* and *demo-cxx* directories of
-/// [https://github.com/dtolnay/cxx](https://github.com/dtolnay/cxx).
+/// *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
+///
+/// [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 ///
 /// <br>
 ///

From 75974b35c6c2cc42ac48728b173aad9ed87d5b47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 12 2020 07:50:23 +0000
Subject: [PATCH 119/2232] Update lockfile for next release


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 0a5063f..7dd18fe 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -67,7 +67,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.10/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.11/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -79,7 +79,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.10/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.11/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
@@ -107,7 +107,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    srcs = glob(["vendor/quote-1.0.3/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
diff --git a/third-party/BUILD b/third-party/BUILD
index 697c125..93e5426 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.10/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.11/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -84,7 +84,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.10/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.11/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
@@ -112,7 +112,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.2/src/**"]),
+    srcs = glob(["vendor/quote-1.0.3/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4e6cc7d..53cfa87 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -183,9 +183,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.10"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a857f7c61b149c868eb7e40311b48502fcc924744fb73191962748643336568"
+checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -196,9 +196,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.10"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "075d00534b62f176b55a48b68319be2f3fc05616d68ecd2bcb66bac0a49170e1"
+checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -218,9 +218,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
+checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
 dependencies = [
  "proc-macro2",
 ]
@@ -374,9 +374,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.23"
+version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26ff1b18659a2218332848d76ad1c867ce4c6ee37b085e6bc8de9a6d11401220"
+checksum = "24b4e093c5ed1a60b22557090120aa14f90ca801549c0949d775ea07c1407720"
 dependencies = [
  "glob",
  "lazy_static",

From f51dc4d0bdf5a878a3d3d378a57af58e04ce59bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 12 2020 07:50:40 +0000
Subject: [PATCH 120/2232] Release 0.2.0


---

diff --git a/Cargo.toml b/Cargo.toml
index 47a45fe..188eca3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.1.2" # remember to update html_root_url
+version = "0.2.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge01"
@@ -19,7 +19,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan = "0.7"
 codespan-reporting = "0.7"
-cxxbridge-macro = { version = "=0.1.2", path = "macro" }
+cxxbridge-macro = { version = "=0.2.0", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/README.md b/README.md
index 2886082..83be22e 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ can be 100% safe.
 
 ```toml
 [dependencies]
-cxx = "0.1"
+cxx = "0.2"
 ```
 
 *Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
@@ -300,9 +300,9 @@ of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td></td><td></td><td></td></tr>
 </table>
 
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index f39609a..4e83b81 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.1.2"
+version = "0.2.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 8159ec7..707a19b 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.1.2"
+version = "0.2.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -19,4 +19,4 @@ quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.1", path = ".." }
+cxx = { version = "0.2", path = ".." }
diff --git a/src/lib.rs b/src/lib.rs
index 47e5367..c65baf1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -304,9 +304,9 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.1/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td></td><td></td><td></td></tr>
 //! </table>
 //!
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 53cfa87..b0ac2a8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -75,7 +75,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.1.2"
+version = "0.2.0"
 dependencies = [
  "anyhow",
  "cc",
@@ -101,7 +101,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.1.2"
+version = "0.2.0"
 dependencies = [
  "anyhow",
  "codespan",
@@ -122,7 +122,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.1.2"
+version = "0.2.0"
 dependencies = [
  "cxx",
  "proc-macro2",

From 3383ae719f11cf25f13247ddcada4517fd819191 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 08:14:11 +0000
Subject: [PATCH 121/2232] Add f32 and f64 types


---

diff --git a/gen/write.rs b/gen/write.rs
index 9ab98fa..6ff04e5 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -86,7 +86,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
                 | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
                 Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(RustString) | None => {}
+                Some(Bool) | Some(F32) | Some(F64) | Some(RustString) | None => {}
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
@@ -446,6 +446,8 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I32) => write!(out, "int32_t"),
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
             Some(CxxString) => write!(out, "::std::string"),
             Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 9fb6554..0b3fd75 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -14,6 +14,8 @@ pub enum Atom {
     I32,
     I64,
     Isize,
+    F32,
+    F64,
     CxxString,
     RustString,
 }
@@ -32,6 +34,8 @@ impl Atom {
             "i16" => Some(I16),
             "i32" => Some(I32),
             "i64" => Some(I64),
+            "f32" => Some(F32),
+            "f64" => Some(F64),
             "isize" => Some(Isize),
             "CxxString" => Some(CxxString),
             "String" => Some(RustString),

From 2b719cb78ef80bf6203fbe9023e297554468c316 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 08:26:27 +0000
Subject: [PATCH 122/2232] Merge pull request #65 from dtolnay/float


Add f32 and f64 types
---

diff --git a/gen/write.rs b/gen/write.rs
index 9ab98fa..6ff04e5 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -86,7 +86,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
                 | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
                 Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(RustString) | None => {}
+                Some(Bool) | Some(F32) | Some(F64) | Some(RustString) | None => {}
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
@@ -446,6 +446,8 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I32) => write!(out, "int32_t"),
             Some(I64) => write!(out, "int64_t"),
             Some(Isize) => write!(out, "ssize_t"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
             Some(CxxString) => write!(out, "::std::string"),
             Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 9fb6554..0b3fd75 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -14,6 +14,8 @@ pub enum Atom {
     I32,
     I64,
     Isize,
+    F32,
+    F64,
     CxxString,
     RustString,
 }
@@ -32,6 +34,8 @@ impl Atom {
             "i16" => Some(I16),
             "i32" => Some(I32),
             "i64" => Some(I64),
+            "f32" => Some(F32),
+            "f64" => Some(F64),
             "isize" => Some(Isize),
             "CxxString" => Some(CxxString),
             "String" => Some(RustString),

From 8c7304998e302c8cb93487d85de326c0ef62ec9a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 08:29:23 +0000
Subject: [PATCH 123/2232] Bump inline namespace to match minor version


---

diff --git a/Cargo.toml b/Cargo.toml
index 188eca3..f81cdb9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "cxx"
 version = "0.2.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge01"
+links = "cxxbridge02"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
diff --git a/build.rs b/build.rs
index bdda779..5173658 100644
--- a/build.rs
+++ b/build.rs
@@ -2,7 +2,7 @@ fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
         .flag("-std=c++11")
-        .compile("cxxbridge01");
+        .compile("cxxbridge02");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
 }
diff --git a/gen/write.rs b/gen/write.rs
index 6ff04e5..f74fb74 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -123,7 +123,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge01");
+    out.begin_block("inline namespace cxxbridge02");
 
     if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
         writeln!(out, "// #include \"rust/cxx.h\"");
@@ -131,7 +131,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 
     if needs_rust_box {
         out.next_section();
-        for line in include::get("CXXBRIDGE01_RUST_BOX").lines() {
+        for line in include::get("CXXBRIDGE02_RUST_BOX").lines() {
             if !line.trim_start().starts_with("//") {
                 writeln!(out, "{}", line);
             }
@@ -161,7 +161,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace cxxbridge01");
+    out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
 
@@ -195,7 +195,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
-    write!(out, "cxxbridge01${}(", efn.ident);
+    write!(out, "cxxbridge02${}(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -278,7 +278,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
-    write!(out, "cxxbridge01${}(", efn.ident);
+    write!(out, "cxxbridge02${}(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -352,7 +352,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
         }
-        write!(out, "cxxbridge01${}(", efn.ident);
+        write!(out, "cxxbridge02${}(", efn.ident);
         for (i, arg) in efn.args.iter().enumerate() {
             if i > 0 {
                 write!(out, ", ");
@@ -507,7 +507,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("extern \"C\"");
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge01");
+    out.begin_block("inline namespace cxxbridge02");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -515,7 +515,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block("namespace cxxbridge01");
+    out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
 
@@ -528,19 +528,19 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE01_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE01_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge01$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge01$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE01_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
@@ -554,12 +554,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge01$box${}$uninit(this);", instance);
+    writeln!(out, "  return cxxbridge02$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge01$box${}$drop(this);", instance);
+    writeln!(out, "  return cxxbridge02$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 
@@ -572,8 +572,8 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE01_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE01_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(
         out,
         "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -586,14 +586,14 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+        "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
         instance, inner, inner,
     );
     writeln!(
@@ -604,31 +604,31 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge01$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge01$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge01$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE01_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index 81bdad5..e02145b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -6,7 +6,7 @@
 #include <type_traits>
 
 namespace rust {
-inline namespace cxxbridge01 {
+inline namespace cxxbridge02 {
 
 struct unsafe_bitcopy_t;
 
@@ -71,8 +71,8 @@ private:
   Repr repr;
 };
 
-#ifndef CXXBRIDGE01_RUST_BOX
-#define CXXBRIDGE01_RUST_BOX
+#ifndef CXXBRIDGE02_RUST_BOX
+#define CXXBRIDGE02_RUST_BOX
 template <typename T> class Box final {
 public:
   using value_type = T;
@@ -136,7 +136,7 @@ private:
   void drop() noexcept;
   T *ptr;
 };
-#endif // CXXBRIDGE01_RUST_BOX
+#endif // CXXBRIDGE02_RUST_BOX
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -151,5 +151,5 @@ struct unsafe_bitcopy_t {
 };
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 
-} // namespace cxxbridge01
+} // namespace cxxbridge02
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8519c1e..fcfa1d9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -140,7 +140,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = format!("{}cxxbridge01${}", namespace, ident);
+    let link_name = format!("{}cxxbridge02${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
@@ -295,7 +295,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         expr = quote!(::std::ptr::write(__return, #expr));
     }
     let ret = expand_extern_return_type(&efn.ret, types);
-    let link_name = format!("{}cxxbridge01${}", namespace, ident);
+    let link_name = format!("{}cxxbridge02${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     quote! {
@@ -309,7 +309,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge01$box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge02$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
@@ -338,7 +338,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let prefix = format!("cxxbridge01$unique_ptr${}{}$", namespace, ident);
+    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
diff --git a/src/cxx.cc b/src/cxx.cc
index f7b02ec..f55d062 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -5,72 +5,72 @@
 #include <stdexcept>
 
 extern "C" {
-const char *cxxbridge01$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge02$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge01$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge02$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
 // rust::String
-void cxxbridge01$string$new(rust::String *self) noexcept;
-void cxxbridge01$string$clone(rust::String *self,
+void cxxbridge02$string$new(rust::String *self) noexcept;
+void cxxbridge02$string$clone(rust::String *self,
                               const rust::String &other) noexcept;
-bool cxxbridge01$string$from(rust::String *self, const char *ptr,
+bool cxxbridge02$string$from(rust::String *self, const char *ptr,
                              size_t len) noexcept;
-void cxxbridge01$string$drop(rust::String *self) noexcept;
-const char *cxxbridge01$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge01$string$len(const rust::String *self) noexcept;
+void cxxbridge02$string$drop(rust::String *self) noexcept;
+const char *cxxbridge02$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge02$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge01$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge02$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge01 {
+inline namespace cxxbridge02 {
 
-String::String() noexcept { cxxbridge01$string$new(this); }
+String::String() noexcept { cxxbridge02$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge01$string$clone(this, other);
+  cxxbridge02$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge01$string$new(&other);
+  cxxbridge02$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge01$string$drop(this); }
+String::~String() noexcept { cxxbridge02$string$drop(this); }
 
 String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
-  if (!cxxbridge01$string$from(this, ptr, len)) {
+  if (!cxxbridge02$string$from(this, ptr, len)) {
     throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
 String::String(const char *s) {
   auto len = strlen(s);
-  if (!cxxbridge01$string$from(this, s, len)) {
+  if (!cxxbridge02$string$from(this, s, len)) {
     throw std::invalid_argument("data for rust::String is not utf-8");
   }
 }
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge01$string$drop(this);
-    cxxbridge01$string$clone(this, other);
+    cxxbridge02$string$drop(this);
+    cxxbridge02$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge01$string$drop(this);
+    cxxbridge02$string$drop(this);
     this->repr = other.repr;
-    cxxbridge01$string$new(&other);
+    cxxbridge02$string$new(&other);
   }
   return *this;
 }
@@ -80,12 +80,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge01$string$ptr(this);
+  return cxxbridge02$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge01$string$len(this); }
+size_t String::size() const noexcept { return cxxbridge02$string$len(this); }
 
-size_t String::length() const noexcept { return cxxbridge01$string$len(this); }
+size_t String::length() const noexcept { return cxxbridge02$string$len(this); }
 
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
@@ -100,13 +100,13 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 Str::Str(const Str &) noexcept = default;
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
-  if (!cxxbridge01$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }
 }
@@ -135,31 +135,31 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
-} // namespace cxxbridge01
+} // namespace cxxbridge02
 } // namespace rust
 
 extern "C" {
-void cxxbridge01$unique_ptr$std$string$null(
+void cxxbridge02$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge01$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
+void cxxbridge02$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
                                            std::string *value) noexcept {
   new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
 }
-void cxxbridge01$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+void cxxbridge02$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge01$unique_ptr$std$string$get(
+const std::string *cxxbridge02$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge01$unique_ptr$std$string$release(
+std::string *cxxbridge02$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge01$unique_ptr$std$string$drop(
+void cxxbridge02$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 40a1731..f2cca5b 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -4,9 +4,9 @@ use std::slice;
 use std::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge01$cxx_string$data"]
+    #[link_name = "cxxbridge02$cxx_string$data"]
     fn string_data(_: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge01$cxx_string$length"]
+    #[link_name = "cxxbridge02$cxx_string$length"]
     fn string_length(_: &CxxString) -> usize;
 }
 
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 3d8a9f0..5b8eaed 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -23,7 +23,7 @@ impl RustStr {
     }
 }
 
-#[export_name = "cxxbridge01$str$valid"]
+#[export_name = "cxxbridge02$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 345d969..258576d 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -30,17 +30,17 @@ impl RustString {
     }
 }
 
-#[export_name = "cxxbridge01$string$new"]
+#[export_name = "cxxbridge02$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge01$string$clone"]
+#[export_name = "cxxbridge02$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge01$string$from"]
+#[export_name = "cxxbridge02$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -56,17 +56,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge01$string$drop"]
+#[export_name = "cxxbridge02$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge01$string$ptr"]
+#[export_name = "cxxbridge02$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge01$string$len"]
+#[export_name = "cxxbridge02$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 19718bb..94b6e25 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -130,17 +130,17 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge01$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge01$unique_ptr$std$string$new"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$new"]
     fn unique_ptr_std_string_new(this: *mut *mut c_void, value: *mut CxxString);
-    #[link_name = "cxxbridge01$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge01$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge01$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge01$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 

From 218e237cac9cfda6982c52eda11d1d6d9be5b83e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 08:34:05 +0000
Subject: [PATCH 124/2232] Remove blank builtin types table row


---

diff --git a/README.md b/README.md
index 83be22e..41639c2 100644
--- a/README.md
+++ b/README.md
@@ -303,7 +303,6 @@ of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td></td><td></td><td></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/src/lib.rs b/src/lib.rs
index c65baf1..21d6a8b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -307,7 +307,6 @@
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-//! <tr><td></td><td></td><td></td></tr>
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file

From 239d05fac630bd8a8ea45ae0b39e7f47c7bb4573 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 08:36:52 +0000
Subject: [PATCH 125/2232] Add Arc and shared_ptr to tbd table


Closes #18.

---

diff --git a/README.md b/README.md
index 41639c2..801c14d 100644
--- a/README.md
+++ b/README.md
@@ -319,9 +319,11 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/src/lib.rs b/src/lib.rs
index 21d6a8b..14cc0cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -323,9 +323,11 @@
 //! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+//! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 //! </table>
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx

From 9542f227db088c5b0e98fdaa14f1bfef7f2441fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 13 2020 20:55:28 +0000
Subject: [PATCH 126/2232] Clean up Atom::from match arm order


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index 0b3fd75..eeea831 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -34,9 +34,9 @@ impl Atom {
             "i16" => Some(I16),
             "i32" => Some(I32),
             "i64" => Some(I64),
+            "isize" => Some(Isize),
             "f32" => Some(F32),
             "f64" => Some(F64),
-            "isize" => Some(Isize),
             "CxxString" => Some(CxxString),
             "String" => Some(RustString),
             _ => None,

From 2fb14e934be453c0d4ad4840ab0d5b8c85d00bed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:11:40 +0000
Subject: [PATCH 127/2232] Add Type::Void variant


Not currently usable as a function argument or explicit return value,
but will be required when we introduce Result for the case of fallible
void functions, whose return type will be Result<()>.

---

diff --git a/gen/write.rs b/gen/write.rs
index f74fb74..3cd3683 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -472,6 +472,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
+        Type::Void(_) => unreachable!(),
     }
 }
 
@@ -480,6 +481,7 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
         Type::Ref(_) => {}
+        Type::Void(_) => unreachable!(),
     }
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index df633de..81e1f05 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -161,6 +161,7 @@ fn describe(ty: &Type, types: &Types) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Void(_) => "()".to_owned(),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c5cc1de..1acb9a5 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -9,9 +9,11 @@ pub mod ident;
 mod impls;
 mod parse;
 pub mod set;
+mod span;
 mod tokens;
 pub mod types;
 
+use self::span::Span;
 use proc_macro2::Ident;
 use syn::{LitStr, Token};
 
@@ -70,6 +72,7 @@ pub enum Type {
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Void(Span),
 }
 
 pub struct Ty1 {
diff --git a/syntax/span.rs b/syntax/span.rs
new file mode 100644
index 0000000..c78567e
--- /dev/null
+++ b/syntax/span.rs
@@ -0,0 +1,16 @@
+use std::hash::{Hash, Hasher};
+
+#[derive(Copy, Clone)]
+pub struct Span(pub proc_macro2::Span);
+
+impl Hash for Span {
+    fn hash<H: Hasher>(&self, _state: &mut H) {}
+}
+
+impl Eq for Span {}
+
+impl PartialEq for Span {
+    fn eq(&self, _other: &Span) -> bool {
+        true
+    }
+}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index e97509b..4ddc1a6 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -16,6 +16,7 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Void(span) => tokens.extend(quote_spanned!(span.0=> ())),
         }
     }
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index 50f13b1..f9f87f3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -23,7 +23,7 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
             }

From fb134ed1be77395bd5ae5bd369a44d0b459e7925 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:17:48 +0000
Subject: [PATCH 128/2232] Implement parsing () type


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 1acb9a5..e702be0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,13 +13,13 @@ mod span;
 mod tokens;
 pub mod types;
 
-use self::span::Span;
 use proc_macro2::Ident;
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
 pub use self::parse::parse_items;
+pub use self::span::Span;
 pub use self::types::Types;
 
 pub enum Api {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index efe6ff8..1453b30 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Receiver, Ref, Struct, Ty1, Type, Var,
+    self, attrs, error, Api, Atom, Doc, ExternFn, ExternType, Receiver, Ref, Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::quote;
@@ -251,6 +251,9 @@ fn parse_type(ty: &RustType) -> Result<Type> {
                 }
             }
         }
+        RustType::Tuple(ty) if ty.elems.is_empty() => {
+            return Ok(Type::Void(syntax::Span(ty.paren_token.span)));
+        }
         _ => {}
     }
     Err(Error::new_spanned(ty, "unsupported type"))

From c21b20ac0fc30845ce1b25377b7c09d9d6aef300 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:25:34 +0000
Subject: [PATCH 129/2232] Handwrite boilerplate impls for Type


This allows dropping the Span wrapper that was only needed for the Eq
and Hash support.

---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8153f03..741431a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,36 @@
-use crate::syntax::{Ref, Ty1};
+use crate::syntax::{Ref, Ty1, Type};
 use std::hash::{Hash, Hasher};
+use std::mem;
+
+impl Hash for Type {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        mem::discriminant(self).hash(state);
+        match self {
+            Type::Ident(t) => t.hash(state),
+            Type::RustBox(t) => t.hash(state),
+            Type::UniquePtr(t) => t.hash(state),
+            Type::Ref(t) => t.hash(state),
+            Type::Str(t) => t.hash(state),
+            Type::Void(_) => {}
+        }
+    }
+}
+
+impl Eq for Type {}
+
+impl PartialEq for Type {
+    fn eq(&self, other: &Type) -> bool {
+        match (self, other) {
+            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
+            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
+            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
+            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
+            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::Void(_), Type::Void(_)) => true,
+            (_, _) => false,
+        }
+    }
+}
 
 impl Eq for Ty1 {}
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e702be0..39198cc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -65,7 +65,6 @@ pub struct Receiver {
     pub ident: Ident,
 }
 
-#[derive(Hash, Eq, PartialEq)]
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),

From d0bb3646cf05ce8b96bc3fb7378d71a2001c68d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:27:49 +0000
Subject: [PATCH 130/2232] Remove Span wrapper type


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 39198cc..8c7e5ca 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -9,17 +9,15 @@ pub mod ident;
 mod impls;
 mod parse;
 pub mod set;
-mod span;
 mod tokens;
 pub mod types;
 
-use proc_macro2::Ident;
+use proc_macro2::{Ident, Span};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
 pub use self::parse::parse_items;
-pub use self::span::Span;
 pub use self::types::Types;
 
 pub enum Api {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1453b30..e059ae5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    self, attrs, error, Api, Atom, Doc, ExternFn, ExternType, Receiver, Ref, Struct, Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Receiver, Ref, Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::quote;
@@ -252,7 +252,7 @@ fn parse_type(ty: &RustType) -> Result<Type> {
             }
         }
         RustType::Tuple(ty) if ty.elems.is_empty() => {
-            return Ok(Type::Void(syntax::Span(ty.paren_token.span)));
+            return Ok(Type::Void(ty.paren_token.span));
         }
         _ => {}
     }
diff --git a/syntax/span.rs b/syntax/span.rs
deleted file mode 100644
index c78567e..0000000
--- a/syntax/span.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use std::hash::{Hash, Hasher};
-
-#[derive(Copy, Clone)]
-pub struct Span(pub proc_macro2::Span);
-
-impl Hash for Span {
-    fn hash<H: Hasher>(&self, _state: &mut H) {}
-}
-
-impl Eq for Span {}
-
-impl PartialEq for Span {
-    fn eq(&self, _other: &Span) -> bool {
-        true
-    }
-}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 4ddc1a6..52c47d5 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -16,7 +16,7 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
-            Type::Void(span) => tokens.extend(quote_spanned!(span.0=> ())),
+            Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
 }

From 1fa1ae4cec168af342b63b7c2e30a25d7ce56075 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:39:58 +0000
Subject: [PATCH 131/2232] Implement restrictions on placement of ()


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 81e1f05..ef3faff 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
 use proc_macro2::Ident;
 use syn::{Error, Result};
 
@@ -40,6 +40,11 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                 }
                 errors.push(unsupported_unique_ptr_target(ptr));
             }
+            Type::Ref(ty) => {
+                if let Type::Void(_) = ty.inner {
+                    errors.push(unsupported_reference_type(ty));
+                }
+            }
             _ => {}
         }
     }
@@ -94,6 +99,7 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
 fn is_unsized(ty: &Type, types: &Types) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
+        Type::Void(_) => return true,
         _ => return false,
     };
     ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
@@ -169,6 +175,10 @@ fn unsupported_type(ident: &Ident) -> Error {
     Error::new(ident.span(), "unsupported type")
 }
 
+fn unsupported_reference_type(ty: &Ref) -> Error {
+    Error::new_spanned(ty, "unsupported reference type")
+}
+
 fn unsupported_cxx_type_in_box(unique_ptr: &Ty1) -> Error {
     Error::new_spanned(unique_ptr, error::BOX_CXX_TYPE.msg)
 }

From 64181b127ed91035a9608bdefb8cb0a151479c83 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:42:54 +0000
Subject: [PATCH 132/2232] Ignore Void in return position


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index e059ae5..67bb52b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -180,7 +180,10 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
     }
     let ret = match &foreign_fn.sig.output {
         ReturnType::Default => None,
-        ReturnType::Type(_, ty) => Some(parse_type(ty)?),
+        ReturnType::Type(_, ty) => match parse_type(ty)? {
+            Type::Void(_) => None,
+            ty => Some(ty),
+        },
     };
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;

From 993918b0cf69d755aef6504465e75c0eb768df98 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 06:54:39 +0000
Subject: [PATCH 133/2232] Merge pull request #69 from dtolnay/void


Add Type::Void variant
---

diff --git a/gen/write.rs b/gen/write.rs
index f74fb74..3cd3683 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -472,6 +472,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
+        Type::Void(_) => unreachable!(),
     }
 }
 
@@ -480,6 +481,7 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
         Type::Ref(_) => {}
+        Type::Void(_) => unreachable!(),
     }
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index df633de..ef3faff 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
 use proc_macro2::Ident;
 use syn::{Error, Result};
 
@@ -40,6 +40,11 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                 }
                 errors.push(unsupported_unique_ptr_target(ptr));
             }
+            Type::Ref(ty) => {
+                if let Type::Void(_) = ty.inner {
+                    errors.push(unsupported_reference_type(ty));
+                }
+            }
             _ => {}
         }
     }
@@ -94,6 +99,7 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
 fn is_unsized(ty: &Type, types: &Types) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
+        Type::Void(_) => return true,
         _ => return false,
     };
     ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
@@ -161,6 +167,7 @@ fn describe(ty: &Type, types: &Types) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Void(_) => "()".to_owned(),
     }
 }
 
@@ -168,6 +175,10 @@ fn unsupported_type(ident: &Ident) -> Error {
     Error::new(ident.span(), "unsupported type")
 }
 
+fn unsupported_reference_type(ty: &Ref) -> Error {
+    Error::new_spanned(ty, "unsupported reference type")
+}
+
 fn unsupported_cxx_type_in_box(unique_ptr: &Ty1) -> Error {
     Error::new_spanned(unique_ptr, error::BOX_CXX_TYPE.msg)
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8153f03..741431a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,36 @@
-use crate::syntax::{Ref, Ty1};
+use crate::syntax::{Ref, Ty1, Type};
 use std::hash::{Hash, Hasher};
+use std::mem;
+
+impl Hash for Type {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        mem::discriminant(self).hash(state);
+        match self {
+            Type::Ident(t) => t.hash(state),
+            Type::RustBox(t) => t.hash(state),
+            Type::UniquePtr(t) => t.hash(state),
+            Type::Ref(t) => t.hash(state),
+            Type::Str(t) => t.hash(state),
+            Type::Void(_) => {}
+        }
+    }
+}
+
+impl Eq for Type {}
+
+impl PartialEq for Type {
+    fn eq(&self, other: &Type) -> bool {
+        match (self, other) {
+            (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
+            (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
+            (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
+            (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
+            (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::Void(_), Type::Void(_)) => true,
+            (_, _) => false,
+        }
+    }
+}
 
 impl Eq for Ty1 {}
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c5cc1de..8c7e5ca 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -12,7 +12,7 @@ pub mod set;
 mod tokens;
 pub mod types;
 
-use proc_macro2::Ident;
+use proc_macro2::{Ident, Span};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
@@ -63,13 +63,13 @@ pub struct Receiver {
     pub ident: Ident,
 }
 
-#[derive(Hash, Eq, PartialEq)]
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Void(Span),
 }
 
 pub struct Ty1 {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index efe6ff8..67bb52b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -180,7 +180,10 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
     }
     let ret = match &foreign_fn.sig.output {
         ReturnType::Default => None,
-        ReturnType::Type(_, ty) => Some(parse_type(ty)?),
+        ReturnType::Type(_, ty) => match parse_type(ty)? {
+            Type::Void(_) => None,
+            ty => Some(ty),
+        },
     };
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
@@ -251,6 +254,9 @@ fn parse_type(ty: &RustType) -> Result<Type> {
                 }
             }
         }
+        RustType::Tuple(ty) if ty.elems.is_empty() => {
+            return Ok(Type::Void(ty.paren_token.span));
+        }
         _ => {}
     }
     Err(Error::new_spanned(ty, "unsupported type"))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index e97509b..52c47d5 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -16,6 +16,7 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index 50f13b1..f9f87f3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -23,7 +23,7 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
             }

From 30d214cca2f6cdd0f53d7548fbbd4439c314d7df Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 07:35:30 +0000
Subject: [PATCH 134/2232] Suppress some more clippy lints


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 06b3bbe..b2cde40 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -1,3 +1,10 @@
+#![allow(
+    clippy::inherent_to_string,
+    clippy::large_enum_variant,
+    clippy::new_without_default,
+    clippy::toplevel_ref_arg
+)]
+
 mod gen;
 mod syntax;
 
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index a211761..59433c1 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -1,4 +1,5 @@
 #![allow(
+    clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
     clippy::or_fun_call,
diff --git a/src/lib.rs b/src/lib.rs
index 14cc0cb..24c5eaf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -335,9 +335,11 @@
 #![doc(html_root_url = "https://docs.rs/cxx/0.1.2")]
 #![deny(improper_ctypes)]
 #![allow(
+    clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::missing_safety_doc,
     clippy::module_inception,
+    clippy::needless_doctest_main,
     clippy::new_without_default,
     clippy::or_fun_call,
     clippy::ptr_arg,

From 59b7edea2737cdbbf86ff06f23d416cd58111e77 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 07:36:15 +0000
Subject: [PATCH 135/2232] Parse Result return type


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8c7e5ca..5b51648 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -50,6 +50,7 @@ pub struct ExternFn {
     pub receiver: Option<Receiver>,
     pub args: Vec<Var>,
     pub ret: Option<Type>,
+    pub throws: bool,
     pub semi_token: Token![;],
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 67bb52b..7bae707 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -178,13 +178,34 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
             }
         }
     }
+
+    let mut throws = false;
     let ret = match &foreign_fn.sig.output {
         ReturnType::Default => None,
-        ReturnType::Type(_, ty) => match parse_type(ty)? {
-            Type::Void(_) => None,
-            ty => Some(ty),
-        },
+        ReturnType::Type(_, ret) => {
+            let mut ret = ret.as_ref();
+            if let RustType::Path(ty) = ret {
+                let path = &ty.path;
+                if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
+                    let segment = &path.segments[0];
+                    let ident = segment.ident.clone();
+                    if let PathArguments::AngleBracketed(generic) = &segment.arguments {
+                        if ident == "Result" && generic.args.len() == 1 {
+                            if let GenericArgument::Type(arg) = &generic.args[0] {
+                                ret = arg;
+                                throws = true;
+                            }
+                        }
+                    }
+                }
+            }
+            match parse_type(ret)? {
+                Type::Void(_) => None,
+                ty => Some(ty),
+            }
+        }
     };
+
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
@@ -196,12 +217,13 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
         receiver,
         args,
         ret,
+        throws,
         semi_token,
     })
 }
 
 fn parse_type(ty: &RustType) -> Result<Type> {
-    match &ty {
+    match ty {
         RustType::Reference(ty) => {
             let inner = parse_type(&ty.elem)?;
             let which = match &inner {

From c0a166d790d3494ce8e397c2f169463a66e66b26 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 07:40:15 +0000
Subject: [PATCH 136/2232] Add error message to say Result is not implemented yet


---

diff --git a/syntax/check.rs b/syntax/check.rs
index ef3faff..80937bb 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -69,6 +69,12 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         errors.push(return_by_value(ty, types));
                     }
                 }
+                if efn.throws {
+                    errors.push(Error::new_spanned(
+                        efn,
+                        "fallible functions are not implemented yet",
+                    ));
+                }
             }
             _ => {}
         }

From 3fe5e2c2204226ca2a60f7f93e57c7bb99ffa623 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 07:49:55 +0000
Subject: [PATCH 137/2232] Merge pull request #70 from dtolnay/result


Parse Result<T> return type
---

diff --git a/syntax/check.rs b/syntax/check.rs
index ef3faff..80937bb 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -69,6 +69,12 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         errors.push(return_by_value(ty, types));
                     }
                 }
+                if efn.throws {
+                    errors.push(Error::new_spanned(
+                        efn,
+                        "fallible functions are not implemented yet",
+                    ));
+                }
             }
             _ => {}
         }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8c7e5ca..5b51648 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -50,6 +50,7 @@ pub struct ExternFn {
     pub receiver: Option<Receiver>,
     pub args: Vec<Var>,
     pub ret: Option<Type>,
+    pub throws: bool,
     pub semi_token: Token![;],
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 67bb52b..7bae707 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -178,13 +178,34 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
             }
         }
     }
+
+    let mut throws = false;
     let ret = match &foreign_fn.sig.output {
         ReturnType::Default => None,
-        ReturnType::Type(_, ty) => match parse_type(ty)? {
-            Type::Void(_) => None,
-            ty => Some(ty),
-        },
+        ReturnType::Type(_, ret) => {
+            let mut ret = ret.as_ref();
+            if let RustType::Path(ty) = ret {
+                let path = &ty.path;
+                if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
+                    let segment = &path.segments[0];
+                    let ident = segment.ident.clone();
+                    if let PathArguments::AngleBracketed(generic) = &segment.arguments {
+                        if ident == "Result" && generic.args.len() == 1 {
+                            if let GenericArgument::Type(arg) = &generic.args[0] {
+                                ret = arg;
+                                throws = true;
+                            }
+                        }
+                    }
+                }
+            }
+            match parse_type(ret)? {
+                Type::Void(_) => None,
+                ty => Some(ty),
+            }
+        }
     };
+
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
@@ -196,12 +217,13 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
         receiver,
         args,
         ret,
+        throws,
         semi_token,
     })
 }
 
 fn parse_type(ty: &RustType) -> Result<Type> {
-    match &ty {
+    match ty {
         RustType::Reference(ty) => {
             let inner = parse_type(&ty.elem)?;
             let which = match &inner {

From b606ce367ee173045b0df5be311efd94f862853c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 08:17:58 +0000
Subject: [PATCH 138/2232] Add CI on stable 1.42


---

diff --git a/.travis.yml b/.travis.yml
index aa158b7..1cc7806 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ language: rust
 rust:
   - nightly
   - beta
+  - stable
 
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
diff --git a/README.md b/README.md
index 801c14d..ea82afb 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,7 @@ can be 100% safe.
 cxx = "0.2"
 ```
 
-*Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
-12)*
+*Compiler support: requires rustc 1.42+*
 
 <br>
 
diff --git a/WORKSPACE b/WORKSPACE
index 3e3baed..4357b70 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,17 +24,15 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_42_beta_linux",
+    name = "rust_1_42_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [],
-    iso_date = "2020-02-08",
-    version = "beta",
+    version = "1.42.0",
 )
 
 rust_repository_set(
-    name = "rust_1_42_beta_darwin",
+    name = "rust_1_42_darwin",
     exec_triple = "x86_64-apple-darwin",
     extra_target_triples = [],
-    iso_date = "2020-02-08",
-    version = "beta",
+    version = "1.42.0",
 )
diff --git a/src/lib.rs b/src/lib.rs
index 24c5eaf..48c3b72 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,8 +10,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
-//! 12)*
+//! *Compiler support: requires rustc 1.42+*
 //!
 //! <br>
 //!

From 2932c9f133273d0a0787d78aac7330b1b6c4a121 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 16 2020 08:31:20 +0000
Subject: [PATCH 139/2232] Merge pull request #71 from dtolnay/stable


Add CI on stable 1.42
---

diff --git a/.travis.yml b/.travis.yml
index aa158b7..1cc7806 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ language: rust
 rust:
   - nightly
   - beta
+  - stable
 
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
diff --git a/README.md b/README.md
index 801c14d..ea82afb 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,7 @@ can be 100% safe.
 cxx = "0.2"
 ```
 
-*Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
-12)*
+*Compiler support: requires rustc 1.42+*
 
 <br>
 
diff --git a/WORKSPACE b/WORKSPACE
index 3e3baed..4357b70 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,17 +24,15 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_42_beta_linux",
+    name = "rust_1_42_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [],
-    iso_date = "2020-02-08",
-    version = "beta",
+    version = "1.42.0",
 )
 
 rust_repository_set(
-    name = "rust_1_42_beta_darwin",
+    name = "rust_1_42_darwin",
     exec_triple = "x86_64-apple-darwin",
     extra_target_triples = [],
-    iso_date = "2020-02-08",
-    version = "beta",
+    version = "1.42.0",
 )
diff --git a/src/lib.rs b/src/lib.rs
index 24c5eaf..48c3b72 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,8 +10,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.42+ (beta on January 30, stable on March
-//! 12)*
+//! *Compiler support: requires rustc 1.42+*
 //!
 //! <br>
 //!

From da5bd272b6512cf70968497e7e4a6f1e2876bbc9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 04:53:22 +0000
Subject: [PATCH 140/2232] Add const assert macro for some static checks


---

diff --git a/src/assert.rs b/src/assert.rs
new file mode 100644
index 0000000..6159ce6
--- /dev/null
+++ b/src/assert.rs
@@ -0,0 +1,30 @@
+pub struct True;
+pub struct False;
+
+pub trait ToBool {
+    type Bool: Sized;
+    const BOOL: Self::Bool;
+}
+
+impl ToBool for [(); 0] {
+    type Bool = False;
+    const BOOL: Self::Bool = False;
+}
+
+impl ToBool for [(); 1] {
+    type Bool = True;
+    const BOOL: Self::Bool = True;
+}
+
+macro_rules! bool {
+    ($e:expr) => {{
+        const EXPR: bool = $e;
+        <[(); EXPR as usize] as $crate::assert::ToBool>::BOOL
+    }};
+}
+
+macro_rules! const_assert {
+    ($e:expr) => {
+        const _: $crate::assert::True = bool!($e);
+    };
+}
diff --git a/src/lib.rs b/src/lib.rs
index 48c3b72..3744bda 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,6 +349,9 @@
 
 extern crate link_cplusplus;
 
+#[macro_use]
+mod assert;
+
 mod cxx_string;
 mod error;
 mod gen;

From 792d02222acf3fd0374aa59df0d285b7e4ec56cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 04:57:49 +0000
Subject: [PATCH 141/2232] Add niche to RustStr


This will be useful for enabling fallible functions to return
Option<RustStr> as the error message if one occurred.

---

diff --git a/src/rust_str.rs b/src/rust_str.rs
index 5b8eaed..110889b 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -1,3 +1,5 @@
+use std::mem;
+use std::ptr::NonNull;
 use std::slice;
 use std::str;
 
@@ -5,20 +7,20 @@ use std::str;
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct RustStr {
-    ptr: *const u8,
+    ptr: NonNull<u8>,
     len: usize,
 }
 
 impl RustStr {
     pub fn from(s: &str) -> Self {
         RustStr {
-            ptr: s.as_ptr(),
+            ptr: NonNull::from(s).cast::<u8>(),
             len: s.len(),
         }
     }
 
     pub unsafe fn as_str<'a>(self) -> &'a str {
-        let slice = slice::from_raw_parts(self.ptr, self.len);
+        let slice = slice::from_raw_parts(self.ptr.as_ptr(), self.len);
         str::from_utf8_unchecked(slice)
     }
 }
@@ -28,3 +30,5 @@ unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
 }
+
+const_assert!(mem::size_of::<Option<RustStr>>() == mem::size_of::<RustStr>());

From bb07a4f9732cefadd9dfdceffc913bd26c92b5cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 06:04:00 +0000
Subject: [PATCH 142/2232] Use qualified name of strlen


---

diff --git a/src/cxx.cc b/src/cxx.cc
index f55d062..6fae0f9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -52,7 +52,7 @@ String::String(const std::string &s) {
 }
 
 String::String(const char *s) {
-  auto len = strlen(s);
+  auto len = std::strlen(s);
   if (!cxxbridge02$string$from(this, s, len)) {
     throw std::invalid_argument("data for rust::String is not utf-8");
   }
@@ -105,7 +105,7 @@ Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   }
 }
 
-Str::Str(const char *s) : repr(Repr{s, strlen(s)}) {
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
   if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
     throw std::invalid_argument("data for rust::Str is not utf-8");
   }

From 6cde49f694b293cabba4208dbacd4904cdf1e587 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 06:04:17 +0000
Subject: [PATCH 143/2232] Store language identifier inside ExternFn for diagnostics


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 5b51648..79a4a7b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -44,6 +44,7 @@ pub struct Struct {
 }
 
 pub struct ExternFn {
+    pub lang: Lang,
     pub doc: Doc,
     pub fn_token: Token![fn],
     pub ident: Ident,
@@ -87,6 +88,12 @@ pub struct Ref {
 }
 
 #[derive(Copy, Clone, PartialEq)]
+pub enum Lang {
+    Cxx,
+    Rust,
+}
+
+#[derive(Copy, Clone, PartialEq)]
 pub enum Derive {
     Clone,
     Copy,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7bae707..00ea15c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Receiver, Ref, Struct, Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::quote;
@@ -8,12 +8,6 @@ use syn::{
     ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
 };
 
-#[derive(Copy, Clone)]
-enum Lang {
-    Cxx,
-    Rust,
-}
-
 pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
     let mut apis = Vec::new();
     for item in items {
@@ -92,7 +86,7 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
                 items.push(api_type(ety));
             }
             ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign)?;
+                let efn = parse_extern_fn(foreign, lang)?;
                 items.push(api_function(efn));
             }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -133,7 +127,7 @@ fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
     })
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
+fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -211,6 +205,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn) -> Result<ExternFn> {
     let ident = foreign_fn.sig.ident.clone();
     let semi_token = foreign_fn.semi_token;
     Ok(ExternFn {
+        lang,
         doc,
         fn_token,
         ident,

From bb16d53057c9c87b0b79965f856176a154be73bc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 06:04:17 +0000
Subject: [PATCH 144/2232] Split the fallible function error message


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 80937bb..4c2fff3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Lang::*, Ref, Ty1, Type, Types, Var};
 use proc_macro2::Ident;
 use syn::{Error, Result};
 
@@ -69,10 +69,16 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         errors.push(return_by_value(ty, types));
                     }
                 }
-                if efn.throws {
+                if efn.throws && efn.lang == Cxx {
                     errors.push(Error::new_spanned(
                         efn,
-                        "fallible functions are not implemented yet",
+                        "fallible C++ functions are not implemented yet",
+                    ));
+                }
+                if efn.throws && efn.lang == Rust {
+                    errors.push(Error::new_spanned(
+                        efn,
+                        "fallible Rust functions are not implemented yet",
                     ));
                 }
             }

From 277e3ccdbada36096c6c0c0d40e01ff8d8806a61 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 07:11:01 +0000
Subject: [PATCH 145/2232] Factor out C++ indirect return predicate


---

diff --git a/gen/write.rs b/gen/write.rs
index 3cd3683..d57e21e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -187,10 +187,6 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let indirect_return = efn
-        .ret
-        .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret));
     write_extern_return_type(out, &efn.ret, types);
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
@@ -205,6 +201,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         write_extern_arg(out, arg, types);
     }
+    let indirect_return = indirect_return(efn, types);
     if indirect_return {
         if !efn.args.is_empty() {
             write!(out, ", ");
@@ -285,11 +282,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         write_extern_arg(out, arg, types);
     }
-    if efn
-        .ret
-        .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
-    {
+    if indirect_return(efn, types) {
         if !efn.args.is_empty() {
             write!(out, ", ");
         }
@@ -300,10 +293,6 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 }
 
 fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let indirect_return = efn
-        .ret
-        .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret));
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -329,6 +318,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         write!(out, "  ");
+        let indirect_return = indirect_return(efn, types);
         if indirect_return {
             write!(out, "::rust::MaybeUninit<");
             write_type(out, efn.ret.as_ref().unwrap());
@@ -398,6 +388,12 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
     }
 }
 
+fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
+    efn.ret
+        .as_ref()
+        .map_or(false, |ret| types.needs_indirect_abi(ret))
+}
+
 fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {

From 1e548174c31a12f82defcfb9fd131a69c42a394d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 07:15:48 +0000
Subject: [PATCH 146/2232] Implement fallible Rust functions


---

diff --git a/gen/write.rs b/gen/write.rs
index d57e21e..ccb5a0f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -271,7 +271,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    write_extern_return_type(out, &efn.ret, types);
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type(out, &efn.ret, types);
+    }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
@@ -305,7 +309,10 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
-    write!(out, ") noexcept");
+    write!(out, ")");
+    if !efn.throws {
+        write!(out, " noexcept");
+    }
     if out.header {
         writeln!(out, ";");
     } else {
@@ -339,6 +346,9 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 _ => {}
             }
         }
+        if efn.throws {
+            write!(out, "::rust::Str::Repr error$ = ");
+        }
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
         }
@@ -374,6 +384,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         writeln!(out, ";");
+        if efn.throws {
+            writeln!(out, "  if (error$.ptr) {{");
+            writeln!(out, "    throw ::rust::Error(error$);");
+            writeln!(out, "  }}");
+        }
         if indirect_return {
             writeln!(out, "  return ::std::move(return$.value);");
         }
@@ -391,7 +406,7 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
 fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
     efn.ret
         .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
diff --git a/include/cxx.h b/include/cxx.h
index e02145b..b48abb5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -138,6 +138,18 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+class Error final : std::exception {
+public:
+  Error(const Error &);
+  Error(Error &&) noexcept;
+  Error(Str::Repr) noexcept;
+  ~Error() noexcept;
+  const char *what() const noexcept override;
+
+private:
+  Str::Repr msg;
+};
+
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
@@ -145,6 +157,7 @@ std::ostream &operator<<(std::ostream &, const Str &);
 using string = String;
 using str = Str;
 template <class T> using box = Box<T>;
+using error = Error;
 
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fcfa1d9..defa565 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -136,7 +136,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     });
     let ret = expand_extern_return_type(&efn.ret, types);
     let mut outparam = None;
-    if indirect_return(&efn.ret, types) {
+    if indirect_return(efn, types) {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
@@ -154,7 +154,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let args = &efn.args;
     let ret = expand_return_type(&efn.ret);
-    let indirect_return = indirect_return(&efn.ret, types);
+    let indirect_return = indirect_return(efn, types);
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
@@ -267,9 +267,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         }
     });
     let mut outparam = None;
-    let call = quote! {
-        ::cxx::private::catch_unwind(__fn, move || super::#ident(#(#vars),*))
-    };
+    let call = quote!(super::#ident(#(#vars),*));
     let mut expr = efn
         .ret
         .as_ref()
@@ -289,12 +287,22 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => None,
         })
         .unwrap_or(call);
-    if indirect_return(&efn.ret, types) {
+    let indirect_return = indirect_return(efn, types);
+    if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
+    }
+    if efn.throws {
+        expr = quote!(::cxx::private::r#try(__return, #expr));
+    } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
-    let ret = expand_extern_return_type(&efn.ret, types);
+    expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
+    let ret = if efn.throws {
+        quote!(-> ::std::option::Option<::cxx::private::RustStr>)
+    } else {
+        expand_extern_return_type(&efn.ret, types)
+    };
     let link_name = format!("{}cxxbridge02${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
@@ -407,9 +415,10 @@ fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     }
 }
 
-fn indirect_return(ret: &Option<Type>, types: &Types) -> bool {
-    ret.as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
+    efn.ret
+        .as_ref()
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
diff --git a/src/cxx.cc b/src/cxx.cc
index 6fae0f9..0c1b8af 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -135,6 +135,32 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+extern "C" {
+const char *cxxbridge02$error(const char *ptr, size_t len) {
+  char *copy = new char[len];
+  strncpy(copy, ptr, len);
+  return copy;
+}
+} // extern "C"
+
+Error::Error(Str::Repr msg) noexcept : msg(msg) {}
+
+Error::Error(const Error &other) {
+  this->msg.ptr = cxxbridge02$error(other.msg.ptr, other.msg.len);
+  this->msg.len = other.msg.len;
+}
+
+Error::Error(Error &&other) noexcept {
+  delete[] this->msg.ptr;
+  this->msg = other.msg;
+  other.msg.ptr = nullptr;
+  other.msg.len = 0;
+}
+
+Error::~Error() noexcept { delete[] this->msg.ptr; }
+
+const char *Error::what() const noexcept { return this->msg.ptr; }
+
 } // namespace cxxbridge02
 } // namespace rust
 
diff --git a/src/exception.rs b/src/exception.rs
new file mode 100644
index 0000000..3f32b45
--- /dev/null
+++ b/src/exception.rs
@@ -0,0 +1,35 @@
+use crate::rust_str::RustStr;
+use std::fmt::Display;
+use std::ptr;
+use std::slice;
+use std::str;
+
+pub unsafe fn r#try<T, E>(ret: *mut T, result: Result<T, E>) -> Option<RustStr>
+where
+    E: Display,
+{
+    match result {
+        Ok(ok) => {
+            ptr::write(ret, ok);
+            None
+        }
+        Err(err) => Some(to_c_string(err.to_string())),
+    }
+}
+
+unsafe fn to_c_string(msg: String) -> RustStr {
+    let mut msg = msg;
+    msg.as_mut_vec().push(b'\0');
+    let ptr = msg.as_ptr();
+    let len = msg.len();
+
+    extern "C" {
+        #[link_name = "cxxbridge02$error"]
+        fn error(ptr: *const u8, len: usize) -> *const u8;
+    }
+
+    let copy = error(ptr, len);
+    let slice = slice::from_raw_parts(copy, len);
+    let string = str::from_utf8_unchecked(slice);
+    RustStr::from(string)
+}
diff --git a/src/lib.rs b/src/lib.rs
index 3744bda..109090c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,6 +354,7 @@ mod assert;
 
 mod cxx_string;
 mod error;
+mod exception;
 mod gen;
 mod opaque;
 mod paths;
@@ -370,6 +371,7 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::exception::r#try;
     pub use crate::opaque::Opaque;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
diff --git a/syntax/check.rs b/syntax/check.rs
index 4c2fff3..b781445 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -75,12 +75,6 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         "fallible C++ functions are not implemented yet",
                     ));
                 }
-                if efn.throws && efn.lang == Rust {
-                    errors.push(Error::new_spanned(
-                        efn,
-                        "fallible Rust functions are not implemented yet",
-                    ));
-                }
             }
             _ => {}
         }

From b6c5ea72339b88c53bbddc542fbc657439f42d20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 07:15:48 +0000
Subject: [PATCH 147/2232] Add Rust fallible test functions


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c709678..07221c2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,4 +1,5 @@
 use cxx::{CxxString, UniquePtr};
+use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
@@ -52,11 +53,25 @@ pub mod ffi {
         fn r_take_str(s: &str);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+
+        fn r_try_return_primitive() -> Result<usize>;
+        fn r_fail_return_primitive() -> Result<usize>;
     }
 }
 
 pub type R = usize;
 
+#[derive(Debug)]
+struct Error;
+
+impl std::error::Error for Error {}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("rust error")
+    }
+}
+
 fn r_return_primitive() -> usize {
     2020
 }
@@ -131,3 +146,11 @@ fn r_take_rust_string(s: String) {
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
+
+fn r_try_return_primitive() -> Result<usize, Error> {
+    Ok(2020)
+}
+
+fn r_fail_return_primitive() -> Result<usize, Error> {
+    Err(Error)
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 350cd7d..0ec2658 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,6 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
+#include <cstring>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -126,6 +127,14 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
+  ASSERT(r_try_return_primitive() == 2020);
+  try {
+    r_fail_return_primitive();
+    ASSERT(false);
+  } catch (const rust::Error &e) {
+    ASSERT(std::strcmp(e.what(), "rust error") == 0);
+  }
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 86b1723ed3695a3ebf1a27f160abafaa05f86efa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 08:11:47 +0000
Subject: [PATCH 148/2232] Avoid Option in ffi


Option seems to work fine on rustc 1.43+ but not 1.42.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index defa565..9c198be 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -299,7 +299,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     }
     expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
     let ret = if efn.throws {
-        quote!(-> ::std::option::Option<::cxx::private::RustStr>)
+        quote!(-> ::cxx::private::Error)
     } else {
         expand_extern_return_type(&efn.ret, types)
     };
diff --git a/src/exception.rs b/src/exception.rs
index 3f32b45..57ff552 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,23 +1,29 @@
-use crate::rust_str::RustStr;
 use std::fmt::Display;
 use std::ptr;
-use std::slice;
-use std::str;
 
-pub unsafe fn r#try<T, E>(ret: *mut T, result: Result<T, E>) -> Option<RustStr>
+#[repr(C)]
+pub struct Error {
+    ptr: *const u8,
+    len: usize,
+}
+
+pub unsafe fn r#try<T, E>(ret: *mut T, result: Result<T, E>) -> Error
 where
     E: Display,
 {
     match result {
         Ok(ok) => {
             ptr::write(ret, ok);
-            None
+            Error {
+                ptr: ptr::null(),
+                len: 0,
+            }
         }
-        Err(err) => Some(to_c_string(err.to_string())),
+        Err(err) => to_c_string(err.to_string()),
     }
 }
 
-unsafe fn to_c_string(msg: String) -> RustStr {
+unsafe fn to_c_string(msg: String) -> Error {
     let mut msg = msg;
     msg.as_mut_vec().push(b'\0');
     let ptr = msg.as_ptr();
@@ -29,7 +35,5 @@ unsafe fn to_c_string(msg: String) -> RustStr {
     }
 
     let copy = error(ptr, len);
-    let slice = slice::from_raw_parts(copy, len);
-    let string = str::from_utf8_unchecked(slice);
-    RustStr::from(string)
+    Error { ptr: copy, len }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 109090c..aa7e84f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -371,7 +371,7 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
-    pub use crate::exception::r#try;
+    pub use crate::exception::{r#try, Error};
     pub use crate::opaque::Opaque;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;

From 486b6ec592baba64ceefebd2237491053f2dda1d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 08:20:52 +0000
Subject: [PATCH 149/2232] Change fallible return type to Result union


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9c198be..b6bc099 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -299,7 +299,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     }
     expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
     let ret = if efn.throws {
-        quote!(-> ::cxx::private::Error)
+        quote!(-> ::cxx::private::Result)
     } else {
         expand_extern_return_type(&efn.ret, types)
     };
diff --git a/src/exception.rs b/src/exception.rs
deleted file mode 100644
index 57ff552..0000000
--- a/src/exception.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use std::fmt::Display;
-use std::ptr;
-
-#[repr(C)]
-pub struct Error {
-    ptr: *const u8,
-    len: usize,
-}
-
-pub unsafe fn r#try<T, E>(ret: *mut T, result: Result<T, E>) -> Error
-where
-    E: Display,
-{
-    match result {
-        Ok(ok) => {
-            ptr::write(ret, ok);
-            Error {
-                ptr: ptr::null(),
-                len: 0,
-            }
-        }
-        Err(err) => to_c_string(err.to_string()),
-    }
-}
-
-unsafe fn to_c_string(msg: String) -> Error {
-    let mut msg = msg;
-    msg.as_mut_vec().push(b'\0');
-    let ptr = msg.as_ptr();
-    let len = msg.len();
-
-    extern "C" {
-        #[link_name = "cxxbridge02$error"]
-        fn error(ptr: *const u8, len: usize) -> *const u8;
-    }
-
-    let copy = error(ptr, len);
-    Error { ptr: copy, len }
-}
diff --git a/src/lib.rs b/src/lib.rs
index aa7e84f..b985e1d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,10 +354,10 @@ mod assert;
 
 mod cxx_string;
 mod error;
-mod exception;
 mod gen;
 mod opaque;
 mod paths;
+mod result;
 mod rust_str;
 mod rust_string;
 mod syntax;
@@ -371,8 +371,8 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
-    pub use crate::exception::{r#try, Error};
     pub use crate::opaque::Opaque;
+    pub use crate::result::{r#try, Result};
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/result.rs b/src/result.rs
new file mode 100644
index 0000000..6d04a2d
--- /dev/null
+++ b/src/result.rs
@@ -0,0 +1,43 @@
+use crate::rust_str::RustStr;
+use std::fmt::Display;
+use std::ptr;
+use std::result::Result as StdResult;
+use std::slice;
+use std::str;
+
+#[repr(C)]
+pub union Result {
+    err: RustStr,
+    ok: *const u8, // null
+}
+
+pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
+where
+    E: Display,
+{
+    match result {
+        Ok(ok) => {
+            ptr::write(ret, ok);
+            Result { ok: ptr::null() }
+        }
+        Err(err) => to_c_error(err.to_string()),
+    }
+}
+
+unsafe fn to_c_error(msg: String) -> Result {
+    let mut msg = msg;
+    msg.as_mut_vec().push(b'\0');
+    let ptr = msg.as_ptr();
+    let len = msg.len();
+
+    extern "C" {
+        #[link_name = "cxxbridge02$error"]
+        fn error(ptr: *const u8, len: usize) -> *const u8;
+    }
+
+    let copy = error(ptr, len);
+    let slice = slice::from_raw_parts(copy, len);
+    let string = str::from_utf8_unchecked(slice);
+    let err = RustStr::from(string);
+    Result { err }
+}

From 8c1a558b4f733ff191c00a7299f7fa61bbf2b465 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 08:34:31 +0000
Subject: [PATCH 150/2232] Merge pull request #73 from dtolnay/result


Implement conversion of Result⟶exception
---

diff --git a/gen/write.rs b/gen/write.rs
index d57e21e..ccb5a0f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -271,7 +271,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    write_extern_return_type(out, &efn.ret, types);
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type(out, &efn.ret, types);
+    }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
@@ -305,7 +309,10 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
-    write!(out, ") noexcept");
+    write!(out, ")");
+    if !efn.throws {
+        write!(out, " noexcept");
+    }
     if out.header {
         writeln!(out, ";");
     } else {
@@ -339,6 +346,9 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 _ => {}
             }
         }
+        if efn.throws {
+            write!(out, "::rust::Str::Repr error$ = ");
+        }
         for name in out.namespace.clone() {
             write!(out, "{}$", name);
         }
@@ -374,6 +384,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         writeln!(out, ";");
+        if efn.throws {
+            writeln!(out, "  if (error$.ptr) {{");
+            writeln!(out, "    throw ::rust::Error(error$);");
+            writeln!(out, "  }}");
+        }
         if indirect_return {
             writeln!(out, "  return ::std::move(return$.value);");
         }
@@ -391,7 +406,7 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
 fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
     efn.ret
         .as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
diff --git a/include/cxx.h b/include/cxx.h
index e02145b..b48abb5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -138,6 +138,18 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+class Error final : std::exception {
+public:
+  Error(const Error &);
+  Error(Error &&) noexcept;
+  Error(Str::Repr) noexcept;
+  ~Error() noexcept;
+  const char *what() const noexcept override;
+
+private:
+  Str::Repr msg;
+};
+
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
@@ -145,6 +157,7 @@ std::ostream &operator<<(std::ostream &, const Str &);
 using string = String;
 using str = Str;
 template <class T> using box = Box<T>;
+using error = Error;
 
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fcfa1d9..b6bc099 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -136,7 +136,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     });
     let ret = expand_extern_return_type(&efn.ret, types);
     let mut outparam = None;
-    if indirect_return(&efn.ret, types) {
+    if indirect_return(efn, types) {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
@@ -154,7 +154,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let args = &efn.args;
     let ret = expand_return_type(&efn.ret);
-    let indirect_return = indirect_return(&efn.ret, types);
+    let indirect_return = indirect_return(efn, types);
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
@@ -267,9 +267,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         }
     });
     let mut outparam = None;
-    let call = quote! {
-        ::cxx::private::catch_unwind(__fn, move || super::#ident(#(#vars),*))
-    };
+    let call = quote!(super::#ident(#(#vars),*));
     let mut expr = efn
         .ret
         .as_ref()
@@ -289,12 +287,22 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => None,
         })
         .unwrap_or(call);
-    if indirect_return(&efn.ret, types) {
+    let indirect_return = indirect_return(efn, types);
+    if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
+    }
+    if efn.throws {
+        expr = quote!(::cxx::private::r#try(__return, #expr));
+    } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
-    let ret = expand_extern_return_type(&efn.ret, types);
+    expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
+    let ret = if efn.throws {
+        quote!(-> ::cxx::private::Result)
+    } else {
+        expand_extern_return_type(&efn.ret, types)
+    };
     let link_name = format!("{}cxxbridge02${}", namespace, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
@@ -407,9 +415,10 @@ fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     }
 }
 
-fn indirect_return(ret: &Option<Type>, types: &Types) -> bool {
-    ret.as_ref()
-        .map_or(false, |ret| types.needs_indirect_abi(ret))
+fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
+    efn.ret
+        .as_ref()
+        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
diff --git a/src/cxx.cc b/src/cxx.cc
index 6fae0f9..0c1b8af 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -135,6 +135,32 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+extern "C" {
+const char *cxxbridge02$error(const char *ptr, size_t len) {
+  char *copy = new char[len];
+  strncpy(copy, ptr, len);
+  return copy;
+}
+} // extern "C"
+
+Error::Error(Str::Repr msg) noexcept : msg(msg) {}
+
+Error::Error(const Error &other) {
+  this->msg.ptr = cxxbridge02$error(other.msg.ptr, other.msg.len);
+  this->msg.len = other.msg.len;
+}
+
+Error::Error(Error &&other) noexcept {
+  delete[] this->msg.ptr;
+  this->msg = other.msg;
+  other.msg.ptr = nullptr;
+  other.msg.len = 0;
+}
+
+Error::~Error() noexcept { delete[] this->msg.ptr; }
+
+const char *Error::what() const noexcept { return this->msg.ptr; }
+
 } // namespace cxxbridge02
 } // namespace rust
 
diff --git a/src/lib.rs b/src/lib.rs
index 3744bda..b985e1d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -357,6 +357,7 @@ mod error;
 mod gen;
 mod opaque;
 mod paths;
+mod result;
 mod rust_str;
 mod rust_string;
 mod syntax;
@@ -371,6 +372,7 @@ pub use cxxbridge_macro::bridge;
 #[doc(hidden)]
 pub mod private {
     pub use crate::opaque::Opaque;
+    pub use crate::result::{r#try, Result};
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/result.rs b/src/result.rs
new file mode 100644
index 0000000..6d04a2d
--- /dev/null
+++ b/src/result.rs
@@ -0,0 +1,43 @@
+use crate::rust_str::RustStr;
+use std::fmt::Display;
+use std::ptr;
+use std::result::Result as StdResult;
+use std::slice;
+use std::str;
+
+#[repr(C)]
+pub union Result {
+    err: RustStr,
+    ok: *const u8, // null
+}
+
+pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result
+where
+    E: Display,
+{
+    match result {
+        Ok(ok) => {
+            ptr::write(ret, ok);
+            Result { ok: ptr::null() }
+        }
+        Err(err) => to_c_error(err.to_string()),
+    }
+}
+
+unsafe fn to_c_error(msg: String) -> Result {
+    let mut msg = msg;
+    msg.as_mut_vec().push(b'\0');
+    let ptr = msg.as_ptr();
+    let len = msg.len();
+
+    extern "C" {
+        #[link_name = "cxxbridge02$error"]
+        fn error(ptr: *const u8, len: usize) -> *const u8;
+    }
+
+    let copy = error(ptr, len);
+    let slice = slice::from_raw_parts(copy, len);
+    let string = str::from_utf8_unchecked(slice);
+    let err = RustStr::from(string);
+    Result { err }
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index 4c2fff3..b781445 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -75,12 +75,6 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         "fallible C++ functions are not implemented yet",
                     ));
                 }
-                if efn.throws && efn.lang == Rust {
-                    errors.push(Error::new_spanned(
-                        efn,
-                        "fallible Rust functions are not implemented yet",
-                    ));
-                }
             }
             _ => {}
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c709678..07221c2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,4 +1,5 @@
 use cxx::{CxxString, UniquePtr};
+use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
@@ -52,11 +53,25 @@ pub mod ffi {
         fn r_take_str(s: &str);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+
+        fn r_try_return_primitive() -> Result<usize>;
+        fn r_fail_return_primitive() -> Result<usize>;
     }
 }
 
 pub type R = usize;
 
+#[derive(Debug)]
+struct Error;
+
+impl std::error::Error for Error {}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("rust error")
+    }
+}
+
 fn r_return_primitive() -> usize {
     2020
 }
@@ -131,3 +146,11 @@ fn r_take_rust_string(s: String) {
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
+
+fn r_try_return_primitive() -> Result<usize, Error> {
+    Ok(2020)
+}
+
+fn r_fail_return_primitive() -> Result<usize, Error> {
+    Err(Error)
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 350cd7d..0ec2658 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,6 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
+#include <cstring>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -126,6 +127,14 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
 
+  ASSERT(r_try_return_primitive() == 2020);
+  try {
+    r_fail_return_primitive();
+    ASSERT(false);
+  } catch (const rust::Error &e) {
+    ASSERT(std::strcmp(e.what(), "rust error") == 0);
+  }
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From cecada6d383ed2b42943cfa65b0ebd6c32fb78c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 08:46:07 +0000
Subject: [PATCH 151/2232] Fix fallible void return


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b6bc099..88fc812 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -293,7 +293,11 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
         outparam = Some(quote!(__return: *mut #ret));
     }
     if efn.throws {
-        expr = quote!(::cxx::private::r#try(__return, #expr));
+        let out = match efn.ret {
+            Some(_) => quote!(__return),
+            None => quote!(&mut ()),
+        };
+        expr = quote!(::cxx::private::r#try(#out, #expr));
     } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 07221c2..fd54654 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -54,6 +54,7 @@ pub mod ffi {
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
 
+        fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
         fn r_fail_return_primitive() -> Result<usize>;
     }
@@ -147,6 +148,10 @@ fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
 
+fn r_try_return_void() -> Result<(), Error> {
+    Ok(())
+}
+
 fn r_try_return_primitive() -> Result<usize, Error> {
     Ok(2020)
 }

From 13af5ccb767a0c9cd3ecbe563e1564af9f5c5131 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 17 2020 20:29:06 +0000
Subject: [PATCH 152/2232] Select a single docs.rs build target


---

diff --git a/Cargo.toml b/Cargo.toml
index f81cdb9..8432bc7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,3 +36,6 @@ trybuild = "1.0.21"
 
 [workspace]
 members = ["cmd", "demo-rs", "macro", "tests/ffi"]
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 4e83b81..7ee974c 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -23,3 +23,6 @@ quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0", features = ["full"] }
 thiserror = "1.0"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 707a19b..635d7cc 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -20,3 +20,6 @@ syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "0.2", path = ".." }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]

From ebef4a23a2dcf92f30eb8ce14a1275201a4a9a53 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 00:34:52 +0000
Subject: [PATCH 153/2232] Implement fallible C++ functions


---

diff --git a/gen/include.rs b/gen/include.rs
index a4b416a..da6678d 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -18,6 +18,7 @@ pub fn get(guard: &str) -> &'static str {
 pub struct Includes {
     custom: Vec<String>,
     pub cstdint: bool,
+    pub cstring: bool,
     pub memory: bool,
     pub string: bool,
     pub type_traits: bool,
@@ -41,6 +42,9 @@ impl Display for Includes {
         if self.cstdint {
             writeln!(f, "#include <cstdint>")?;
         }
+        if self.cstring {
+            writeln!(f, "#include <cstring>")?;
+        }
         if self.memory {
             writeln!(f, "#include <memory>")?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index ccb5a0f..3398f9a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -45,6 +45,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
 
     if !header {
         out.begin_block("extern \"C\"");
+        write_exception_glue(out, apis);
         for api in apis {
             let (efn, write): (_, fn(_, _, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
@@ -186,8 +187,32 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+    let mut has_cxx_throws = false;
+    for api in apis {
+        if let Api::CxxFunction(efn) = api {
+            if efn.throws {
+                has_cxx_throws = true;
+                break;
+            }
+        }
+    }
+
+    if has_cxx_throws {
+        out.next_section();
+        write!(
+            out,
+            "const char *cxxbridge02$exception(const char *, size_t);",
+        );
+    }
+}
+
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    write_extern_return_type(out, &efn.ret, types);
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type(out, &efn.ret, types);
+    }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
@@ -221,6 +246,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     writeln!(out, ") = {};", efn.ident);
     write!(out, "  ");
+    if efn.throws {
+        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "  try {{");
+        write!(out, "    ");
+    }
     if indirect_return {
         write!(out, "new (return$) ");
         write_type(out, efn.ret.as_ref().unwrap());
@@ -267,6 +297,19 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, ")");
     }
     writeln!(out, ";");
+    if efn.throws {
+        out.include.cstring = true;
+        writeln!(out, "    throw$.ptr = nullptr;");
+        writeln!(out, "  }} catch (const ::std::exception &catch$) {{");
+        writeln!(out, "    const char *return$ = catch$.what();");
+        writeln!(out, "    throw$.len = ::std::strlen(return$);");
+        writeln!(
+            out,
+            "    throw$.ptr = cxxbridge02$exception(return$, throw$.len);",
+        );
+        writeln!(out, "  }}");
+        writeln!(out, "  return throw$;");
+    }
     writeln!(out, "}}");
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 88fc812..e11b2d3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -134,7 +134,11 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
             quote!(#ident: #ty)
         }
     });
-    let ret = expand_extern_return_type(&efn.ret, types);
+    let ret = if efn.throws {
+        quote!(-> ::cxx::private::Result)
+    } else {
+        expand_extern_return_type(&efn.ret, types)
+    };
     let mut outparam = None;
     if indirect_return(efn, types) {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
@@ -153,7 +157,15 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let args = &efn.args;
-    let ret = expand_return_type(&efn.ret);
+    let ret = if efn.throws {
+        let ok = match &efn.ret {
+            Some(ret) => quote!(#ret),
+            None => quote!(()),
+        };
+        quote!(-> ::std::result::Result<#ok, ::cxx::Exception>)
+    } else {
+        expand_return_type(&efn.ret)
+    };
     let indirect_return = indirect_return(efn, types);
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
@@ -192,10 +204,21 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
-            #local_name(#(#vars,)* __return.as_mut_ptr());
         });
+        if efn.throws {
+            setup.extend(quote! {
+                #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
+            });
+            quote!(::std::result::Result::Ok(__return.assume_init()))
+        } else {
+            setup.extend(quote! {
+                #local_name(#(#vars,)* __return.as_mut_ptr());
+            });
+            quote!(__return.assume_init())
+        }
+    } else if efn.throws {
         quote! {
-            __return.assume_init()
+            #local_name(#(#vars),*).exception()
         }
     } else {
         quote! {
diff --git a/src/exception.rs b/src/exception.rs
new file mode 100644
index 0000000..c436196
--- /dev/null
+++ b/src/exception.rs
@@ -0,0 +1,29 @@
+use std::fmt::{self, Debug, Display};
+use std::slice;
+
+/// Exception thrown from an `extern "C"` function.
+#[derive(Debug)]
+pub struct Exception {
+    pub(crate) what: Box<str>,
+}
+
+impl Display for Exception {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(&self.what)
+    }
+}
+
+impl std::error::Error for Exception {}
+
+impl Exception {
+    pub fn what(&self) -> &str {
+        &self.what
+    }
+}
+
+#[export_name = "cxxbridge02$exception"]
+unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
+    let slice = slice::from_raw_parts(ptr, len);
+    let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
+    Box::leak(boxed).as_ptr()
+}
diff --git a/src/lib.rs b/src/lib.rs
index b985e1d..5dd2649 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,6 +354,7 @@ mod assert;
 
 mod cxx_string;
 mod error;
+mod exception;
 mod gen;
 mod opaque;
 mod paths;
@@ -365,6 +366,7 @@ mod unique_ptr;
 mod unwind;
 
 pub use crate::cxx_string::CxxString;
+pub use crate::exception::Exception;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 
diff --git a/src/result.rs b/src/result.rs
index 6d04a2d..047260b 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,5 +1,7 @@
+use crate::exception::Exception;
 use crate::rust_str::RustStr;
 use std::fmt::Display;
+use std::mem;
 use std::ptr;
 use std::result::Result as StdResult;
 use std::slice;
@@ -41,3 +43,18 @@ unsafe fn to_c_error(msg: String) -> Result {
     let err = RustStr::from(string);
     Result { err }
 }
+
+impl Result {
+    pub unsafe fn exception(self) -> StdResult<(), Exception> {
+        if self.ok.is_null() {
+            Ok(())
+        } else {
+            let err = self.err;
+            let slice = slice::from_raw_parts(err.ptr.as_ptr(), err.len);
+            let s = str::from_utf8_unchecked(slice);
+            Err(Exception {
+                what: mem::transmute::<*const str, Box<str>>(s),
+            })
+        }
+    }
+}
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 110889b..51e4835 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -7,8 +7,8 @@ use std::str;
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct RustStr {
-    ptr: NonNull<u8>,
-    len: usize,
+    pub(crate) ptr: NonNull<u8>,
+    pub(crate) len: usize,
 }
 
 impl RustStr {
diff --git a/syntax/check.rs b/syntax/check.rs
index b781445..ef3faff 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Lang::*, Ref, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
 use proc_macro2::Ident;
 use syn::{Error, Result};
 
@@ -69,12 +69,6 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         errors.push(return_by_value(ty, types));
                     }
                 }
-                if efn.throws && efn.lang == Cxx {
-                    errors.push(Error::new_spanned(
-                        efn,
-                        "fallible C++ functions are not implemented yet",
-                    ));
-                }
             }
             _ => {}
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fd54654..fe6a364 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -30,6 +30,10 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+
+        fn c_try_return_void() -> Result<()>;
+        fn c_try_return_primitive() -> Result<usize>;
+        fn c_fail_return_primitive() -> Result<usize>;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 0ec2658..4f36f9b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,6 +1,7 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
 #include <cstring>
+#include <stdexcept>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -91,6 +92,12 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_try_return_void() {}
+
+size_t c_try_return_primitive() { return 2020; }
+
+size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7cff6fa..6a5f802 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -36,4 +36,8 @@ void c_take_str(rust::Str s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
+void c_try_return_void();
+size_t c_try_return_primitive();
+size_t c_fail_return_primitive();
+
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index a30aefb..d86ebd2 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -38,6 +38,13 @@ fn test_c_return() {
             .to_str()
             .unwrap()
     );
+
+    assert_eq!((), ffi::c_try_return_void().unwrap());
+    assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
+    assert_eq!(
+        "logic error",
+        ffi::c_fail_return_primitive().unwrap_err().what(),
+    );
 }
 
 #[test]

From a56c07053efa5616c574ad29b1c3d424a6dbeeb2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 00:47:21 +0000
Subject: [PATCH 154/2232] Merge pull request #74 from dtolnay/result


Implement conversion of exception⟶Result
---

diff --git a/gen/include.rs b/gen/include.rs
index a4b416a..da6678d 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -18,6 +18,7 @@ pub fn get(guard: &str) -> &'static str {
 pub struct Includes {
     custom: Vec<String>,
     pub cstdint: bool,
+    pub cstring: bool,
     pub memory: bool,
     pub string: bool,
     pub type_traits: bool,
@@ -41,6 +42,9 @@ impl Display for Includes {
         if self.cstdint {
             writeln!(f, "#include <cstdint>")?;
         }
+        if self.cstring {
+            writeln!(f, "#include <cstring>")?;
+        }
         if self.memory {
             writeln!(f, "#include <memory>")?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index ccb5a0f..3398f9a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -45,6 +45,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
 
     if !header {
         out.begin_block("extern \"C\"");
+        write_exception_glue(out, apis);
         for api in apis {
             let (efn, write): (_, fn(_, _, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
@@ -186,8 +187,32 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+    let mut has_cxx_throws = false;
+    for api in apis {
+        if let Api::CxxFunction(efn) = api {
+            if efn.throws {
+                has_cxx_throws = true;
+                break;
+            }
+        }
+    }
+
+    if has_cxx_throws {
+        out.next_section();
+        write!(
+            out,
+            "const char *cxxbridge02$exception(const char *, size_t);",
+        );
+    }
+}
+
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    write_extern_return_type(out, &efn.ret, types);
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type(out, &efn.ret, types);
+    }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
     }
@@ -221,6 +246,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     writeln!(out, ") = {};", efn.ident);
     write!(out, "  ");
+    if efn.throws {
+        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "  try {{");
+        write!(out, "    ");
+    }
     if indirect_return {
         write!(out, "new (return$) ");
         write_type(out, efn.ret.as_ref().unwrap());
@@ -267,6 +297,19 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, ")");
     }
     writeln!(out, ";");
+    if efn.throws {
+        out.include.cstring = true;
+        writeln!(out, "    throw$.ptr = nullptr;");
+        writeln!(out, "  }} catch (const ::std::exception &catch$) {{");
+        writeln!(out, "    const char *return$ = catch$.what();");
+        writeln!(out, "    throw$.len = ::std::strlen(return$);");
+        writeln!(
+            out,
+            "    throw$.ptr = cxxbridge02$exception(return$, throw$.len);",
+        );
+        writeln!(out, "  }}");
+        writeln!(out, "  return throw$;");
+    }
     writeln!(out, "}}");
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 88fc812..e11b2d3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -134,7 +134,11 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
             quote!(#ident: #ty)
         }
     });
-    let ret = expand_extern_return_type(&efn.ret, types);
+    let ret = if efn.throws {
+        quote!(-> ::cxx::private::Result)
+    } else {
+        expand_extern_return_type(&efn.ret, types)
+    };
     let mut outparam = None;
     if indirect_return(efn, types) {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
@@ -153,7 +157,15 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let args = &efn.args;
-    let ret = expand_return_type(&efn.ret);
+    let ret = if efn.throws {
+        let ok = match &efn.ret {
+            Some(ret) => quote!(#ret),
+            None => quote!(()),
+        };
+        quote!(-> ::std::result::Result<#ok, ::cxx::Exception>)
+    } else {
+        expand_return_type(&efn.ret)
+    };
     let indirect_return = indirect_return(efn, types);
     let vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
@@ -192,10 +204,21 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
-            #local_name(#(#vars,)* __return.as_mut_ptr());
         });
+        if efn.throws {
+            setup.extend(quote! {
+                #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
+            });
+            quote!(::std::result::Result::Ok(__return.assume_init()))
+        } else {
+            setup.extend(quote! {
+                #local_name(#(#vars,)* __return.as_mut_ptr());
+            });
+            quote!(__return.assume_init())
+        }
+    } else if efn.throws {
         quote! {
-            __return.assume_init()
+            #local_name(#(#vars),*).exception()
         }
     } else {
         quote! {
diff --git a/src/exception.rs b/src/exception.rs
new file mode 100644
index 0000000..c436196
--- /dev/null
+++ b/src/exception.rs
@@ -0,0 +1,29 @@
+use std::fmt::{self, Debug, Display};
+use std::slice;
+
+/// Exception thrown from an `extern "C"` function.
+#[derive(Debug)]
+pub struct Exception {
+    pub(crate) what: Box<str>,
+}
+
+impl Display for Exception {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(&self.what)
+    }
+}
+
+impl std::error::Error for Exception {}
+
+impl Exception {
+    pub fn what(&self) -> &str {
+        &self.what
+    }
+}
+
+#[export_name = "cxxbridge02$exception"]
+unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
+    let slice = slice::from_raw_parts(ptr, len);
+    let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
+    Box::leak(boxed).as_ptr()
+}
diff --git a/src/lib.rs b/src/lib.rs
index b985e1d..5dd2649 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,6 +354,7 @@ mod assert;
 
 mod cxx_string;
 mod error;
+mod exception;
 mod gen;
 mod opaque;
 mod paths;
@@ -365,6 +366,7 @@ mod unique_ptr;
 mod unwind;
 
 pub use crate::cxx_string::CxxString;
+pub use crate::exception::Exception;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 
diff --git a/src/result.rs b/src/result.rs
index 6d04a2d..047260b 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,5 +1,7 @@
+use crate::exception::Exception;
 use crate::rust_str::RustStr;
 use std::fmt::Display;
+use std::mem;
 use std::ptr;
 use std::result::Result as StdResult;
 use std::slice;
@@ -41,3 +43,18 @@ unsafe fn to_c_error(msg: String) -> Result {
     let err = RustStr::from(string);
     Result { err }
 }
+
+impl Result {
+    pub unsafe fn exception(self) -> StdResult<(), Exception> {
+        if self.ok.is_null() {
+            Ok(())
+        } else {
+            let err = self.err;
+            let slice = slice::from_raw_parts(err.ptr.as_ptr(), err.len);
+            let s = str::from_utf8_unchecked(slice);
+            Err(Exception {
+                what: mem::transmute::<*const str, Box<str>>(s),
+            })
+        }
+    }
+}
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 110889b..51e4835 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -7,8 +7,8 @@ use std::str;
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct RustStr {
-    ptr: NonNull<u8>,
-    len: usize,
+    pub(crate) ptr: NonNull<u8>,
+    pub(crate) len: usize,
 }
 
 impl RustStr {
diff --git a/syntax/check.rs b/syntax/check.rs
index b781445..ef3faff 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Lang::*, Ref, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
 use proc_macro2::Ident;
 use syn::{Error, Result};
 
@@ -69,12 +69,6 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                         errors.push(return_by_value(ty, types));
                     }
                 }
-                if efn.throws && efn.lang == Cxx {
-                    errors.push(Error::new_spanned(
-                        efn,
-                        "fallible C++ functions are not implemented yet",
-                    ));
-                }
             }
             _ => {}
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fd54654..fe6a364 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -30,6 +30,10 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+
+        fn c_try_return_void() -> Result<()>;
+        fn c_try_return_primitive() -> Result<usize>;
+        fn c_fail_return_primitive() -> Result<usize>;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 0ec2658..4f36f9b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,6 +1,7 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs"
 #include <cstring>
+#include <stdexcept>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -91,6 +92,12 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_try_return_void() {}
+
+size_t c_try_return_primitive() { return 2020; }
+
+size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7cff6fa..6a5f802 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -36,4 +36,8 @@ void c_take_str(rust::Str s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 
+void c_try_return_void();
+size_t c_try_return_primitive();
+size_t c_fail_return_primitive();
+
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index a30aefb..d86ebd2 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -38,6 +38,13 @@ fn test_c_return() {
             .to_str()
             .unwrap()
     );
+
+    assert_eq!((), ffi::c_try_return_void().unwrap());
+    assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
+    assert_eq!(
+        "logic error",
+        ffi::c_fail_return_primitive().unwrap_err().what(),
+    );
 }
 
 #[test]

From bffcdd5f4bdf47c691770d7de7e971f7ba220172 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 02:12:38 +0000
Subject: [PATCH 155/2232] Use consistent filenames for generated code


This makes it clearer that the filename doesn't need to be connected to
the rule name.

---

diff --git a/demo-rs/BUCK b/demo-rs/BUCK
index a0f6fb0..eac4182 100644
--- a/demo-rs/BUCK
+++ b/demo-rs/BUCK
@@ -22,7 +22,7 @@ genrule(
     srcs = ["src/main.rs"],
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
     type = "cxxbridge",
-    out = "gen-demo.h",
+    out = "generated.h",
 )
 
 genrule(
@@ -30,7 +30,7 @@ genrule(
     srcs = ["src/main.rs"],
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     type = "cxxbridge",
-    out = "gen-demo.cc",
+    out = "generated.cc",
 )
 
 cxx_library(
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index 389ee58..f703be3 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -30,7 +30,7 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
-    outs = ["gen-demo.cc"],
+    outs = ["generated.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
diff --git a/tests/BUCK b/tests/BUCK
index 81f74de..b488c90 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -31,12 +31,12 @@ genrule(
     name = "gen-header",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    out = "gen.h",
+    out = "generated.h",
 )
 
 genrule(
     name = "gen-source",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    out = "gen.cc",
+    out = "generated.cc",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 16825f6..ef6477f 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -39,7 +39,7 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["ffi/lib.rs"],
-    outs = ["gen.cc"],
+    outs = ["generated.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )

From 1a2683ac220706c26ca80cf6c679793aedad9d35 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 02:13:22 +0000
Subject: [PATCH 156/2232] Allow .rs.h extension when including generated header


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 04287b8..cd447ea 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -1,5 +1,5 @@
 #include "demo-cxx/demo.h"
-#include "demo-rs/src/main.rs"
+#include "demo-rs/src/main.rs.h"
 #include <iostream>
 
 namespace org {
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
index eac4182..d4164d3 100644
--- a/demo-rs/BUCK
+++ b/demo-rs/BUCK
@@ -36,7 +36,7 @@ genrule(
 cxx_library(
     name = "include",
     exported_headers = {
-        "src/main.rs": ":gen-header",
+        "src/main.rs.h": ":gen-header",
     },
     visibility = ["PUBLIC"],
 )
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index f703be3..e3ebb96 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -22,7 +22,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    outs = ["main.rs"],
+    outs = ["main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
diff --git a/src/paths.rs b/src/paths.rs
index e318664..62fbb6e 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -22,21 +22,28 @@ fn try_cc_build() -> Result<cc::Build> {
 }
 
 // Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.h.
+// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
 pub(crate) fn symlink_header(path: &Path, original: &Path) {
     let _ = try_symlink_header(path, original);
 }
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
+    #[cfg(unix)]
+    use os::unix::fs::symlink;
+    #[cfg(windows)]
+    use os::windows::fs::symlink_file as symlink;
+
     let suffix = relative_to_parent_of_target_dir(original)?;
     let ref dst = include_dir()?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
-    #[cfg(unix)]
-    os::unix::fs::symlink(path, dst)?;
-    #[cfg(windows)]
-    os::windows::fs::symlink_file(path, dst)?;
+    symlink(path, dst)?;
+
+    let mut file_name = dst.file_name().unwrap().to_os_string();
+    file_name.push(".h");
+    let dst2 = dst.with_file_name(file_name);
+    symlink(path, dst2)?;
 
     Ok(())
 }
diff --git a/tests/BUCK b/tests/BUCK
index b488c90..659223c 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -21,7 +21,7 @@ cxx_library(
         ":gen-source",
     ],
     headers = {
-        "ffi/lib.rs": ":gen-header",
+        "ffi/lib.rs.h": ":gen-header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
diff --git a/tests/BUILD b/tests/BUILD
index ef6477f..65c5b41 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -31,7 +31,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs"],
+    outs = ["lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4f36f9b..184e8aa 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
 #include "tests/ffi/tests.h"
-#include "tests/ffi/lib.rs"
+#include "tests/ffi/lib.rs.h"
 #include <cstring>
 #include <stdexcept>
 

From 5840afe465ded5d8415d015d0467b23369234b51 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 02:41:13 +0000
Subject: [PATCH 157/2232] Merge pull request #75 from dtolnay/extension


Allow .rs.h extension when including generated header
---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 04287b8..cd447ea 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -1,5 +1,5 @@
 #include "demo-cxx/demo.h"
-#include "demo-rs/src/main.rs"
+#include "demo-rs/src/main.rs.h"
 #include <iostream>
 
 namespace org {
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
index eac4182..d4164d3 100644
--- a/demo-rs/BUCK
+++ b/demo-rs/BUCK
@@ -36,7 +36,7 @@ genrule(
 cxx_library(
     name = "include",
     exported_headers = {
-        "src/main.rs": ":gen-header",
+        "src/main.rs.h": ":gen-header",
     },
     visibility = ["PUBLIC"],
 )
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
index f703be3..e3ebb96 100644
--- a/demo-rs/BUILD
+++ b/demo-rs/BUILD
@@ -22,7 +22,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    outs = ["main.rs"],
+    outs = ["main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
diff --git a/src/paths.rs b/src/paths.rs
index e318664..62fbb6e 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -22,21 +22,28 @@ fn try_cc_build() -> Result<cc::Build> {
 }
 
 // Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.h.
+// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
 pub(crate) fn symlink_header(path: &Path, original: &Path) {
     let _ = try_symlink_header(path, original);
 }
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
+    #[cfg(unix)]
+    use os::unix::fs::symlink;
+    #[cfg(windows)]
+    use os::windows::fs::symlink_file as symlink;
+
     let suffix = relative_to_parent_of_target_dir(original)?;
     let ref dst = include_dir()?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
-    #[cfg(unix)]
-    os::unix::fs::symlink(path, dst)?;
-    #[cfg(windows)]
-    os::windows::fs::symlink_file(path, dst)?;
+    symlink(path, dst)?;
+
+    let mut file_name = dst.file_name().unwrap().to_os_string();
+    file_name.push(".h");
+    let dst2 = dst.with_file_name(file_name);
+    symlink(path, dst2)?;
 
     Ok(())
 }
diff --git a/tests/BUCK b/tests/BUCK
index b488c90..659223c 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -21,7 +21,7 @@ cxx_library(
         ":gen-source",
     ],
     headers = {
-        "ffi/lib.rs": ":gen-header",
+        "ffi/lib.rs.h": ":gen-header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
diff --git a/tests/BUILD b/tests/BUILD
index ef6477f..65c5b41 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -31,7 +31,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs"],
+    outs = ["lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4f36f9b..184e8aa 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
 #include "tests/ffi/tests.h"
-#include "tests/ffi/lib.rs"
+#include "tests/ffi/lib.rs.h"
 #include <cstring>
 #include <stdexcept>
 

From 26ad0bd98c23c5983c7d13df0ae3ec3b578e9b6c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 04:34:16 +0000
Subject: [PATCH 158/2232] Look for end of line when finding headers ifdefs


---

diff --git a/gen/include.rs b/gen/include.rs
index da6678d..68cb00d 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -5,8 +5,8 @@ pub static HEADER: &str = include_str!("include/cxx.h");
 pub fn get(guard: &str) -> &'static str {
     let ifndef = format!("#ifndef {}", guard);
     let endif = format!("#endif // {}", guard);
-    let begin = HEADER.find(&ifndef);
-    let end = HEADER.find(&endif);
+    let begin = find_line(&ifndef);
+    let end = find_line(&endif);
     if let (Some(begin), Some(end)) = (begin, end) {
         &HEADER[begin..end + endif.len()]
     } else {
@@ -14,6 +14,18 @@ pub fn get(guard: &str) -> &'static str {
     }
 }
 
+fn find_line(line: &str) -> Option<usize> {
+    let mut offset = 0;
+    loop {
+        offset += HEADER[offset..].find(line)?;
+        let rest = &HEADER[offset + line.len()..];
+        if rest.starts_with('\n') || rest.starts_with('\r') {
+            return Some(offset);
+        }
+        offset += line.len();
+    }
+}
+
 #[derive(Default)]
 pub struct Includes {
     custom: Vec<String>,

From b7a7cb6785b63188c411a74db3f1eb05dce240b9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 04:40:47 +0000
Subject: [PATCH 159/2232] Provide more struct definitions where needed


---

diff --git a/gen/include.rs b/gen/include.rs
index 68cb00d..a7657e4 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -29,8 +29,10 @@ fn find_line(line: &str) -> Option<usize> {
 #[derive(Default)]
 pub struct Includes {
     custom: Vec<String>,
+    pub array: bool,
     pub cstdint: bool,
     pub cstring: bool,
+    pub exception: bool,
     pub memory: bool,
     pub string: bool,
     pub type_traits: bool,
@@ -51,12 +53,18 @@ impl Display for Includes {
         for include in &self.custom {
             writeln!(f, "#include \"{}\"", include.escape_default())?;
         }
+        if self.array {
+            writeln!(f, "#include <array>")?;
+        }
         if self.cstdint {
             writeln!(f, "#include <cstdint>")?;
         }
         if self.cstring {
             writeln!(f, "#include <cstring>")?;
         }
+        if self.exception {
+            writeln!(f, "#include <exception>")?;
+        }
         if self.memory {
             writeln!(f, "#include <memory>")?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index 3398f9a..a75d4c0 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -97,47 +97,84 @@ fn write_includes(out: &mut OutFile, types: &Types) {
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
+    let mut needs_rust_string = false;
+    let mut needs_rust_str = false;
     let mut needs_rust_box = false;
     for ty in types {
-        if let Type::RustBox(_) = ty {
-            needs_rust_box = true;
-            break;
+        match ty {
+            Type::RustBox(_) => {
+                out.include.type_traits = true;
+                needs_rust_box = true;
+            }
+            Type::Str(_) => {
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_str = true;
+            }
+            ty if ty == RustString => {
+                out.include.array = true;
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_string = true;
+            }
+            _ => {}
         }
     }
 
+    let mut needs_rust_error = false;
+    let mut needs_unsafe_bitcopy = false;
     let mut needs_manually_drop = false;
     let mut needs_maybe_uninit = false;
     for api in apis {
-        if let Api::RustFunction(efn) = api {
-            for arg in &efn.args {
-                if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-                    needs_manually_drop = true;
-                    break;
+        match api {
+            Api::CxxFunction(efn) if !out.header => {
+                for arg in &efn.args {
+                    if arg.ty == RustString {
+                        needs_unsafe_bitcopy = true;
+                        break;
+                    }
                 }
             }
-            if let Some(ret) = &efn.ret {
-                if types.needs_indirect_abi(ret) {
-                    needs_maybe_uninit = true;
+            Api::RustFunction(efn) if !out.header => {
+                if efn.throws {
+                    out.include.exception = true;
+                    needs_rust_error = true;
+                }
+                for arg in &efn.args {
+                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                        needs_manually_drop = true;
+                        break;
+                    }
+                }
+                if let Some(ret) = &efn.ret {
+                    if types.needs_indirect_abi(ret) {
+                        needs_maybe_uninit = true;
+                    }
                 }
             }
+            _ => {}
         }
     }
 
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge02");
 
-    if needs_rust_box || needs_manually_drop || needs_maybe_uninit {
+    if needs_rust_string
+        || needs_rust_str
+        || needs_rust_box
+        || needs_rust_error
+        || needs_unsafe_bitcopy
+        || needs_manually_drop
+        || needs_maybe_uninit
+    {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    if needs_rust_box {
-        out.next_section();
-        for line in include::get("CXXBRIDGE02_RUST_BOX").lines() {
-            if !line.trim_start().starts_with("//") {
-                writeln!(out, "{}", line);
-            }
-        }
-    }
+    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
+    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
+    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();
@@ -166,6 +203,17 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
+fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
+    if needed {
+        out.next_section();
+        for line in include::get(section).lines() {
+            if !line.trim_start().starts_with("//") {
+                writeln!(out, "{}", line);
+            }
+        }
+    }
+}
+
 fn write_struct(out: &mut OutFile, strct: &Struct) {
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
diff --git a/include/cxx.h b/include/cxx.h
index b48abb5..a021ca7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -1,6 +1,7 @@
 #pragma once
 #include <array>
 #include <cstdint>
+#include <exception>
 #include <iosfwd>
 #include <string>
 #include <type_traits>
@@ -10,6 +11,8 @@ inline namespace cxxbridge02 {
 
 struct unsafe_bitcopy_t;
 
+#ifndef CXXBRIDGE02_RUST_STRING
+#define CXXBRIDGE02_RUST_STRING
 class String final {
 public:
   String() noexcept;
@@ -37,7 +40,10 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
 };
+#endif // CXXBRIDGE02_RUST_STRING
 
+#ifndef CXXBRIDGE02_RUST_STR
+#define CXXBRIDGE02_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -70,6 +76,7 @@ public:
 private:
   Repr repr;
 };
+#endif // CXXBRIDGE02_RUST_STR
 
 #ifndef CXXBRIDGE02_RUST_BOX
 #define CXXBRIDGE02_RUST_BOX
@@ -138,6 +145,8 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+#ifndef CXXBRIDGE02_RUST_ERROR
+#define CXXBRIDGE02_RUST_ERROR
 class Error final : std::exception {
 public:
   Error(const Error &);
@@ -149,6 +158,7 @@ public:
 private:
   Str::Repr msg;
 };
+#endif // CXXBRIDGE02_RUST_ERROR
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -159,10 +169,13 @@ using str = Str;
 template <class T> using box = Box<T>;
 using error = Error;
 
+#ifndef CXXBRIDGE02_RUST_BITCOPY
+#define CXXBRIDGE02_RUST_BITCOPY
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
 };
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+#endif // CXXBRIDGE02_RUST_BITCOPY
 
 } // namespace cxxbridge02
 } // namespace rust

From 3577d451d7877ee00e765c2f93fd7e563ee45499 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 04:48:13 +0000
Subject: [PATCH 160/2232] Fix blank first line if no headers emitted


---

diff --git a/gen/include.rs b/gen/include.rs
index a7657e4..b19a097 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -26,7 +26,7 @@ fn find_line(line: &str) -> Option<usize> {
     }
 }
 
-#[derive(Default)]
+#[derive(Default, PartialEq)]
 pub struct Includes {
     custom: Vec<String>,
     pub array: bool,
@@ -74,6 +74,9 @@ impl Display for Includes {
         if self.type_traits {
             writeln!(f, "#include <type_traits>")?;
         }
+        if *self != Self::default() {
+            writeln!(f)?;
+        }
         Ok(())
     }
 }
diff --git a/gen/out.rs b/gen/out.rs
index 124816f..2a5b17d 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -53,14 +53,18 @@ impl Write for OutFile {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         if !s.is_empty() {
             if !self.blocks_pending.is_empty() {
-                self.content.push(b'\n');
+                if !self.content.is_empty() {
+                    self.content.push(b'\n');
+                }
                 for block in self.blocks_pending.drain(..) {
                     self.content.extend_from_slice(block.as_bytes());
                     self.content.extend_from_slice(b" {\n");
                 }
                 self.section_pending = false;
             } else if self.section_pending {
-                self.content.push(b'\n');
+                if !self.content.is_empty() {
+                    self.content.push(b'\n');
+                }
                 self.section_pending = false;
             }
             self.content.extend_from_slice(s.as_bytes());

From 4791f1c115181788ebfea5572f64bff5549d801c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 04:55:19 +0000
Subject: [PATCH 161/2232] Include <utility> when using std::move


---

diff --git a/gen/include.rs b/gen/include.rs
index b19a097..a642c0a 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -36,6 +36,7 @@ pub struct Includes {
     pub memory: bool,
     pub string: bool,
     pub type_traits: bool,
+    pub utility: bool,
 }
 
 impl Includes {
@@ -74,6 +75,9 @@ impl Display for Includes {
         if self.type_traits {
             writeln!(f, "#include <type_traits>")?;
         }
+        if self.utility {
+            writeln!(f, "#include <utility>")?;
+        }
         if *self != Self::default() {
             writeln!(f)?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index a75d4c0..16322c1 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -178,6 +178,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 
     if needs_manually_drop {
         out.next_section();
+        out.include.utility = true;
         writeln!(out, "template <typename T>");
         writeln!(out, "union ManuallyDrop {{");
         writeln!(out, "  T value;");
@@ -329,6 +330,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 arg.ident,
             );
         } else if types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
         } else {
             write!(out, "{}", arg.ident);
@@ -347,6 +349,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     writeln!(out, ";");
     if efn.throws {
         out.include.cstring = true;
+        out.include.exception = true;
         writeln!(out, "    throw$.ptr = nullptr;");
         writeln!(out, "  }} catch (const ::std::exception &catch$) {{");
         writeln!(out, "    const char *return$ = catch$.what();");
@@ -410,6 +413,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, " {{");
         for arg in &efn.args {
             if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                out.include.utility = true;
                 write!(out, "  ::rust::ManuallyDrop<");
                 write_type(out, &arg.ty);
                 writeln!(out, "> {}$(::std::move({0}));", arg.ident);
@@ -481,6 +485,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             writeln!(out, "  }}");
         }
         if indirect_return {
+            out.include.utility = true;
             writeln!(out, "  return ::std::move(return$.value);");
         }
         writeln!(out, "}}");
@@ -668,6 +673,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
+    out.include.utility = true;
+
     let mut inner = String::new();
     for name in &out.namespace {
         inner += name;
diff --git a/include/cxx.h b/include/cxx.h
index a021ca7..1026743 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -5,6 +5,7 @@
 #include <iosfwd>
 #include <string>
 #include <type_traits>
+#include <utility>
 
 namespace rust {
 inline namespace cxxbridge02 {

From 5d12144989e81ae8a2a9e4e305a311cfcc98abfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 05:22:24 +0000
Subject: [PATCH 162/2232] Factor catch implementation to static function


---

diff --git a/gen/write.rs b/gen/write.rs
index 16322c1..33674b4 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -125,9 +125,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_unsafe_bitcopy = false;
     let mut needs_manually_drop = false;
     let mut needs_maybe_uninit = false;
+    let mut needs_trycatch = false;
     for api in apis {
         match api {
             Api::CxxFunction(efn) if !out.header => {
+                if efn.throws {
+                    needs_trycatch = true;
+                }
                 for arg in &efn.args {
                     if arg.ty == RustString {
                         needs_unsafe_bitcopy = true;
@@ -166,6 +170,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
+        || needs_trycatch
     {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
@@ -200,6 +205,20 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
+    if needs_trycatch {
+        out.next_section();
+        out.include.exception = true;
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(
+            out,
+            "static void trycatch(Try &&func, Fail &&fail) noexcept try {{",
+        );
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+    }
+
     out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
@@ -297,8 +316,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  try {{");
-        write!(out, "    ");
+        writeln!(out, "  ::rust::trycatch(");
+        writeln!(out, "      [&] {{");
+        write!(out, "        ");
     }
     if indirect_return {
         write!(out, "new (return$) ");
@@ -349,16 +369,15 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     writeln!(out, ";");
     if efn.throws {
         out.include.cstring = true;
-        out.include.exception = true;
-        writeln!(out, "    throw$.ptr = nullptr;");
-        writeln!(out, "  }} catch (const ::std::exception &catch$) {{");
-        writeln!(out, "    const char *return$ = catch$.what();");
-        writeln!(out, "    throw$.len = ::std::strlen(return$);");
+        writeln!(out, "        throw$.ptr = nullptr;");
+        writeln!(out, "      }},");
+        writeln!(out, "      [&](const char *catch$) {{");
+        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "    throw$.ptr = cxxbridge02$exception(return$, throw$.len);",
+            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
         );
-        writeln!(out, "  }}");
+        writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
     }
     writeln!(out, "}}");

From b7a42acc73ef38ba011e643d94b1b345e0972c15 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 05:47:24 +0000
Subject: [PATCH 163/2232] Merge pull request #76 from dtolnay/trycatch


Factor catch implementation to static function
---

diff --git a/gen/write.rs b/gen/write.rs
index 16322c1..33674b4 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -125,9 +125,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_unsafe_bitcopy = false;
     let mut needs_manually_drop = false;
     let mut needs_maybe_uninit = false;
+    let mut needs_trycatch = false;
     for api in apis {
         match api {
             Api::CxxFunction(efn) if !out.header => {
+                if efn.throws {
+                    needs_trycatch = true;
+                }
                 for arg in &efn.args {
                     if arg.ty == RustString {
                         needs_unsafe_bitcopy = true;
@@ -166,6 +170,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
+        || needs_trycatch
     {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
@@ -200,6 +205,20 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
+    if needs_trycatch {
+        out.next_section();
+        out.include.exception = true;
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(
+            out,
+            "static void trycatch(Try &&func, Fail &&fail) noexcept try {{",
+        );
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+    }
+
     out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
@@ -297,8 +316,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  try {{");
-        write!(out, "    ");
+        writeln!(out, "  ::rust::trycatch(");
+        writeln!(out, "      [&] {{");
+        write!(out, "        ");
     }
     if indirect_return {
         write!(out, "new (return$) ");
@@ -349,16 +369,15 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     writeln!(out, ";");
     if efn.throws {
         out.include.cstring = true;
-        out.include.exception = true;
-        writeln!(out, "    throw$.ptr = nullptr;");
-        writeln!(out, "  }} catch (const ::std::exception &catch$) {{");
-        writeln!(out, "    const char *return$ = catch$.what();");
-        writeln!(out, "    throw$.len = ::std::strlen(return$);");
+        writeln!(out, "        throw$.ptr = nullptr;");
+        writeln!(out, "      }},");
+        writeln!(out, "      [&](const char *catch$) {{");
+        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "    throw$.ptr = cxxbridge02$exception(return$, throw$.len);",
+            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
         );
-        writeln!(out, "  }}");
+        writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
     }
     writeln!(out, "}}");

From 82c1617925687ec3d5eace66150c40f1eb555502 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 05:54:12 +0000
Subject: [PATCH 164/2232] Catch block isn't allowed to throw


---

diff --git a/gen/write.rs b/gen/write.rs
index 33674b4..99260ea 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -371,7 +371,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         out.include.cstring = true;
         writeln!(out, "        throw$.ptr = nullptr;");
         writeln!(out, "      }},");
-        writeln!(out, "      [&](const char *catch$) {{");
+        writeln!(out, "      [&](const char *catch$) noexcept {{");
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,

From 3e3e0af976aab5ec8095c464093ebb6665298db7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 06:03:24 +0000
Subject: [PATCH 165/2232] Allow catch behavior to be customized


If the user's cxx::bridge invocation includes any header that defines
the following function, they get it's behavior as the exception-to-Result
conversion.

    namespace rust::behavior {
    template <typename Try, typename Fail>
    static void trycatch(Try &&func, Fail &&fail) noexcept try {
      func();
    } catch (/* up to you */) {
      fail(/* const char *msg */);
    }
    }

The default behavior is equivalent to:

    } catch (const std::exception &e) {
      fail(e.what());
    }

Codebases that use Folly, for example, may be interested in behavior
like this instead for better type information on the error messages:

    } catch (const std::exception &e) {
      fail(folly::exceptionStr(e));
    } catch (...) {
      fail("<unknown exception>");
    }

---

diff --git a/gen/write.rs b/gen/write.rs
index 99260ea..de2d0cd 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -205,10 +205,21 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
+    out.end_block("namespace cxxbridge02");
+
     if needs_trycatch {
-        out.next_section();
+        out.begin_block("namespace behavior");
         out.include.exception = true;
-        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "struct trycatch {{");
+        writeln!(out, "  template <typename T> trycatch(T);");
+        writeln!(out, "  static char use_default;");
+        writeln!(out, "}};");
+        writeln!(out);
+        writeln!(out, "template <typename Try, typename Fail,");
+        writeln!(
+            out,
+            "          typename = decltype(trycatch(std::declval<Try>()).use_default)>",
+        );
         writeln!(
             out,
             "static void trycatch(Try &&func, Fail &&fail) noexcept try {{",
@@ -217,9 +228,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}} catch (const ::std::exception &e) {{");
         writeln!(out, "  fail(e.what());");
         writeln!(out, "}}");
+        out.end_block("namespace behavior");
     }
 
-    out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
 
@@ -316,7 +327,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  ::rust::trycatch(");
+        writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
         write!(out, "        ");
     }

From cf2de24613d6d7e31941df4508701e935835edad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 06:20:57 +0000
Subject: [PATCH 166/2232] Add Result to builtin types table


Closes #53.

---

diff --git a/README.md b/README.md
index ea82afb..7909711 100644
--- a/README.md
+++ b/README.md
@@ -302,6 +302,7 @@ of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>Result&lt;T&gt;</td><td>error ↔️ exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
@@ -336,7 +337,6 @@ the facets that I still intend for this project to tackle:
 - [ ] Support associated methods: `extern "Rust" { fn f(self: &Struct); }`
 - [ ] Support C++ member functions
 - [ ] Support passing function pointers across the FFI
-- [ ] Support translating between Result ⟷ exceptions
 - [ ] Support structs with type parameters
 - [ ] Support async functions
 
diff --git a/src/lib.rs b/src/lib.rs
index 5dd2649..b03c234 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -306,6 +306,7 @@
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>Result&lt;T&gt;</td><td>error ↔️ exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file

From 06515f0ed2d59cd6c8451e9fbf3e951c8b4bad72 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 06:28:02 +0000
Subject: [PATCH 167/2232] Replace arrows with html entity


---

diff --git a/README.md b/README.md
index 7909711..fe54024 100644
--- a/README.md
+++ b/README.md
@@ -291,9 +291,9 @@ Some of the considerations that go into ensuring safety are:
 
 ## Builtin types
 
-In addition to all the primitive types (i32 ⟷ int32_t), the following common
-types may be used in the fields of shared structs and the arguments and returns
-of functions.
+In addition to all the primitive types (i32 &xharr; int32_t), the following
+common types may be used in the fields of shared structs and the arguments and
+returns of functions.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
@@ -302,7 +302,7 @@ of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td>Result&lt;T&gt;</td><td>error ↔️ exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td>Result&lt;T&gt;</td><td>error &harr; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/src/lib.rs b/src/lib.rs
index b03c234..cc9fb12 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -295,9 +295,9 @@
 //!
 //! # Builtin types
 //!
-//! In addition to all the primitive types (i32 ⟷ int32_t), the following common
-//! types may be used in the fields of shared structs and the arguments and
-//! returns of functions.
+//! In addition to all the primitive types (i32 &xharr; int32_t), the following
+//! common types may be used in the fields of shared structs and the arguments
+//! and returns of functions.
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
@@ -306,7 +306,7 @@
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-//! <tr><td>Result&lt;T&gt;</td><td>error ↔️ exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+//! <tr><td>Result&lt;T&gt;</td><td>error &harr; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file

From 559fbb3918a8276383ed00eb64ed4199441d8261 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 06:32:22 +0000
Subject: [PATCH 168/2232] Give up and use ascii arrows


None of the unicode ones look consistently good across different systems.

---

diff --git a/README.md b/README.md
index fe54024..4308291 100644
--- a/README.md
+++ b/README.md
@@ -291,7 +291,7 @@ Some of the considerations that go into ensuring safety are:
 
 ## Builtin types
 
-In addition to all the primitive types (i32 &xharr; int32_t), the following
+In addition to all the primitive types (i32 &lt;=&gt; int32_t), the following
 common types may be used in the fields of shared structs and the arguments and
 returns of functions.
 
@@ -302,7 +302,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td>Result&lt;T&gt;</td><td>error &harr; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/src/lib.rs b/src/lib.rs
index cc9fb12..8d1ba19 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -295,9 +295,9 @@
 //!
 //! # Builtin types
 //!
-//! In addition to all the primitive types (i32 &xharr; int32_t), the following
-//! common types may be used in the fields of shared structs and the arguments
-//! and returns of functions.
+//! In addition to all the primitive types (i32 &lt;=&gt; int32_t), the
+//! following common types may be used in the fields of shared structs and the
+//! arguments and returns of functions.
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
@@ -306,7 +306,7 @@
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-//! <tr><td>Result&lt;T&gt;</td><td>error &harr; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+//! <tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file

From 047223384ee12c63da523d61a7bdbb4d740e2e1b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 18:35:39 +0000
Subject: [PATCH 169/2232] Make trycatch sfinae work on msvc


---

diff --git a/gen/write.rs b/gen/write.rs
index de2d0cd..9a33fc5 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -210,20 +210,19 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     if needs_trycatch {
         out.begin_block("namespace behavior");
         out.include.exception = true;
-        writeln!(out, "struct trycatch {{");
-        writeln!(out, "  template <typename T> trycatch(T);");
-        writeln!(out, "  static char use_default;");
-        writeln!(out, "}};");
+        out.include.type_traits = true;
+        out.include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
         writeln!(out);
-        writeln!(out, "template <typename Try, typename Fail,");
-        writeln!(
-            out,
-            "          typename = decltype(trycatch(std::declval<Try>()).use_default)>",
-        );
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename std::enable_if<");
         writeln!(
             out,
-            "static void trycatch(Try &&func, Fail &&fail) noexcept try {{",
+            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
         );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
         writeln!(out, "  func();");
         writeln!(out, "}} catch (const ::std::exception &e) {{");
         writeln!(out, "  fail(e.what());");

From 57d01e41071b12f10c9598132124833981d0481c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 18:53:57 +0000
Subject: [PATCH 170/2232] Merge pull request #77 from dtolnay/catch


Allow catch behavior to be customized
---

diff --git a/gen/write.rs b/gen/write.rs
index 99260ea..9a33fc5 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -205,21 +205,31 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
+    out.end_block("namespace cxxbridge02");
+
     if needs_trycatch {
-        out.next_section();
+        out.begin_block("namespace behavior");
         out.include.exception = true;
+        out.include.type_traits = true;
+        out.include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
+        writeln!(out);
         writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename std::enable_if<");
         writeln!(
             out,
-            "static void trycatch(Try &&func, Fail &&fail) noexcept try {{",
+            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
         );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
         writeln!(out, "  func();");
         writeln!(out, "}} catch (const ::std::exception &e) {{");
         writeln!(out, "  fail(e.what());");
         writeln!(out, "}}");
+        out.end_block("namespace behavior");
     }
 
-    out.end_block("namespace cxxbridge02");
     out.end_block("namespace rust");
 }
 
@@ -316,7 +326,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  ::rust::trycatch(");
+        writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
         write!(out, "        ");
     }

From e68634c0a1624dc57c69ff277892e9addf14bad8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 19:03:40 +0000
Subject: [PATCH 171/2232] Fix missing newline after cxxbridge02$exception declaration


---

diff --git a/gen/write.rs b/gen/write.rs
index 9a33fc5..ff5670c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -278,7 +278,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
 
     if has_cxx_throws {
         out.next_section();
-        write!(
+        writeln!(
             out,
             "const char *cxxbridge02$exception(const char *, size_t);",
         );

From 16448731f2923bfa02f1bc015c51c9a98ac43659 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 19:40:26 +0000
Subject: [PATCH 172/2232] Move extern fn signature fields to struct


This will allow reusing the Signature struct for the type of function
pointers.

---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 741431a..dfaab55 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,6 +1,15 @@
-use crate::syntax::{Ref, Ty1, Type};
+use crate::syntax::{ExternFn, Ref, Signature, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
+use std::ops::Deref;
+
+impl Deref for ExternFn {
+    type Target = Signature;
+
+    fn deref(&self) -> &Self::Target {
+        &self.sig
+    }
+}
 
 impl Hash for Type {
     fn hash<H: Hasher>(&self, state: &mut H) {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 79a4a7b..f2e1c1c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -46,13 +46,17 @@ pub struct Struct {
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
-    pub fn_token: Token![fn],
     pub ident: Ident,
+    pub sig: Signature,
+    pub semi_token: Token![;],
+}
+
+pub struct Signature {
+    pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
     pub args: Vec<Var>,
     pub ret: Option<Type>,
     pub throws: bool,
-    pub semi_token: Token![;],
 }
 
 pub struct Var {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 00ea15c..e07ee25 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,5 +1,6 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Struct, Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Struct,
+    Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::quote;
@@ -207,12 +208,14 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     Ok(ExternFn {
         lang,
         doc,
-        fn_token,
         ident,
-        receiver,
-        args,
-        ret,
-        throws,
+        sig: Signature {
+            fn_token,
+            receiver,
+            args,
+            ret,
+            throws,
+        },
         semi_token,
     })
 }

From 0b76aea8e8ac0c31ec9b28deeb0cf4f68889a451 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 19:54:24 +0000
Subject: [PATCH 173/2232] Allow extern abi to be specified as "C++"


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index e07ee25..2258dd6 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -111,7 +111,7 @@ fn parse_lang(abi: Abi) -> Result<Lang> {
         }
     };
     match name.value().as_str() {
-        "C" => Ok(Lang::Cxx),
+        "C" | "C++" => Ok(Lang::Cxx),
         "Rust" => Ok(Lang::Rust),
         _ => Err(Error::new_spanned(abi, "unrecognized ABI")),
     }

From b40b9dba076f33859faf383d80416355d2c65ac6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 20:50:36 +0000
Subject: [PATCH 174/2232] Divide up big parse_type function


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2258dd6..10db16e 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,7 +6,8 @@ use proc_macro2::Ident;
 use quote::quote;
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
+    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType, TypePath,
+    TypeReference,
 };
 
 pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
@@ -222,62 +223,64 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
 
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => {
-            let inner = parse_type(&ty.elem)?;
-            let which = match &inner {
-                Type::Ident(ident) if ident == "str" => {
-                    if ty.mutability.is_some() {
-                        return Err(Error::new_spanned(ty, "unsupported type"));
-                    } else {
-                        Type::Str
-                    }
-                }
-                _ => Type::Ref,
-            };
-            return Ok(which(Box::new(Ref {
-                ampersand: ty.and_token,
-                mutability: ty.mutability,
-                inner,
-            })));
+        RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Path(ty) => parse_type_path(ty),
+        RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
+        _ => Err(Error::new_spanned(ty, "unsupported type")),
+    }
+}
+
+fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
+    let which = match &inner {
+        Type::Ident(ident) if ident == "str" => {
+            if ty.mutability.is_some() {
+                return Err(Error::new_spanned(ty, "unsupported type"));
+            } else {
+                Type::Str
+            }
         }
-        RustType::Path(ty) => {
-            let path = &ty.path;
-            if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
-                let segment = &path.segments[0];
-                let ident = segment.ident.clone();
-                match &segment.arguments {
-                    PathArguments::None => return Ok(Type::Ident(ident)),
-                    PathArguments::AngleBracketed(generic) => {
-                        if ident == "UniquePtr" && generic.args.len() == 1 {
-                            if let GenericArgument::Type(arg) = &generic.args[0] {
-                                let inner = parse_type(arg)?;
-                                return Ok(Type::UniquePtr(Box::new(Ty1 {
-                                    name: ident,
-                                    langle: generic.lt_token,
-                                    inner,
-                                    rangle: generic.gt_token,
-                                })));
-                            }
-                        } else if ident == "Box" && generic.args.len() == 1 {
-                            if let GenericArgument::Type(arg) = &generic.args[0] {
-                                let inner = parse_type(arg)?;
-                                return Ok(Type::RustBox(Box::new(Ty1 {
-                                    name: ident,
-                                    langle: generic.lt_token,
-                                    inner,
-                                    rangle: generic.gt_token,
-                                })));
-                            }
-                        }
+        _ => Type::Ref,
+    };
+    Ok(which(Box::new(Ref {
+        ampersand: ty.and_token,
+        mutability: ty.mutability,
+        inner,
+    })))
+}
+
+fn parse_type_path(ty: &TypePath) -> Result<Type> {
+    let path = &ty.path;
+    if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
+        let segment = &path.segments[0];
+        let ident = segment.ident.clone();
+        match &segment.arguments {
+            PathArguments::None => return Ok(Type::Ident(ident)),
+            PathArguments::AngleBracketed(generic) => {
+                if ident == "UniquePtr" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::UniquePtr(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
+                } else if ident == "Box" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::RustBox(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
                     }
-                    PathArguments::Parenthesized(_) => {}
                 }
             }
+            PathArguments::Parenthesized(_) => {}
         }
-        RustType::Tuple(ty) if ty.elems.is_empty() => {
-            return Ok(Type::Void(ty.paren_token.span));
-        }
-        _ => {}
     }
     Err(Error::new_spanned(ty, "unsupported type"))
 }

From 6dfa3b0a7c9471bf23fd51c5e21b25b77d2b81e1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 21:01:12 +0000
Subject: [PATCH 175/2232] Update third-party dependencies


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 7dd18fe..ccb2107 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -2,7 +2,7 @@
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.27/src/**"]),
     visibility = ["PUBLIC"],
     features = ["std"],
 )
@@ -115,7 +115,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.11/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.12/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":clap",
@@ -126,7 +126,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.4/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.5/src/**"]),
     proc_macro = True,
     deps = [
         ":heck",
diff --git a/third-party/BUILD b/third-party/BUILD
index 93e5426..ad779fd 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -7,7 +7,7 @@ load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.26/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.27/src/**"]),
     crate_features = ["std"],
     visibility = ["//visibility:public"],
 )
@@ -120,7 +120,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.11/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.12/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.4/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.5/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b0ac2a8..d8c5cb0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -11,9 +11,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
+checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785"
 
 [[package]]
 name = "atty"
@@ -168,9 +168,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.67"
+version = "0.2.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
+checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
 
 [[package]]
 name = "link-cplusplus"
@@ -238,24 +238,24 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
+checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
 
 [[package]]
 name = "serde"
-version = "1.0.104"
+version = "1.0.105"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
+checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.104"
+version = "1.0.105"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
+checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -281,9 +281,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.11"
+version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073"
+checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d"
 dependencies = [
  "clap",
  "lazy_static",
@@ -292,9 +292,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd"
+checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430"
 dependencies = [
  "heck",
  "proc-macro-error",

From e2e7bc3c9ed932dfd08a589ab782f591fd8d80b7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 22:17:37 +0000
Subject: [PATCH 176/2232] Update to codespan-reporting 0.9


---

diff --git a/BUCK b/BUCK
index 2f80c9b..4357dd6 100644
--- a/BUCK
+++ b/BUCK
@@ -7,7 +7,6 @@ rust_library(
         ":macro",
         "//third-party:anyhow",
         "//third-party:cc",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
         "//third-party:proc-macro2",
@@ -26,7 +25,6 @@ rust_binary(
     },
     deps = [
         "//third-party:anyhow",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
diff --git a/BUILD b/BUILD
index db22203..59ac9fc 100644
--- a/BUILD
+++ b/BUILD
@@ -10,7 +10,6 @@ rust_library(
         ":cxxbridge-macro",
         "//third-party:anyhow",
         "//third-party:cc",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
         "//third-party:proc-macro2",
@@ -27,7 +26,6 @@ rust_binary(
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
diff --git a/Cargo.toml b/Cargo.toml
index 8432bc7..63a3a94 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,8 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 cc = "1.0.49"
-codespan = "0.7"
-codespan-reporting = "0.7"
+codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.0", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 7ee974c..aef31f6 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -16,8 +16,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 
 [dependencies]
 anyhow = "1.0"
-codespan = "0.7"
-codespan-reporting = "0.7"
+codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
diff --git a/gen/error.rs b/gen/error.rs
index b8ac337..ca78acb 100644
--- a/gen/error.rs
+++ b/gen/error.rs
@@ -1,8 +1,8 @@
 use crate::gen::Error;
 use crate::syntax;
 use anyhow::anyhow;
-use codespan::{FileId, Files};
 use codespan_reporting::diagnostic::{Diagnostic, Label};
+use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
 use codespan_reporting::term::{self, Config};
 use std::io::Write;
@@ -46,32 +46,30 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err
     }
     end_offset += end.column;
 
-    let mut files = Files::new();
+    let mut files = SimpleFiles::new();
     let file = files.add(path.to_string_lossy(), source);
 
-    let range = start_offset as u32..end_offset as u32;
-    let diagnostic = diagnose(file, range, error);
+    let diagnostic = diagnose(file, start_offset..end_offset, error);
 
     let config = Config::default();
     let _ = term::emit(stderr, &config, &files, &diagnostic);
 }
 
-fn diagnose(file: FileId, range: Range<u32>, error: syn::Error) -> Diagnostic {
+fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
     let message = error.to_string();
     let info = syntax::error::ERRORS
         .iter()
         .find(|e| message.contains(e.msg));
-    let mut diagnostic = if let Some(info) = info {
-        let label = Label::new(file, range, info.label.unwrap_or(&message));
-        let mut diagnostic = Diagnostic::new_error(&message, label);
-        if let Some(note) = info.note {
-            diagnostic = diagnostic.with_notes(vec![note.to_owned()]);
-        }
-        diagnostic
+    let mut diagnostic = Diagnostic::error().with_message(&message);
+    let mut label = Label::primary(file, range);
+    if let Some(info) = info {
+        label.message = info.label.map_or(message, str::to_owned);
+        diagnostic.labels.push(label);
+        diagnostic.notes.extend(info.note.map(str::to_owned));
     } else {
-        let label = Label::new(file, range, &message);
-        Diagnostic::new_error(&message, label)
-    };
+        label.message = message;
+        diagnostic.labels.push(label);
+    }
     diagnostic.code = Some("cxxbridge".to_owned());
     diagnostic
 }
diff --git a/third-party/BUCK b/third-party/BUCK
index ccb2107..14f2542 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -30,18 +30,10 @@ rust_library(
 )
 
 rust_library(
-    name = "codespan",
-    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
-    visibility = ["PUBLIC"],
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
-        ":codespan",
         ":termcolor",
         ":unicode-width",
     ],
diff --git a/third-party/BUILD b/third-party/BUILD
index ad779fd..daf9ea1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -35,18 +35,10 @@ rust_library(
 )
 
 rust_library(
-    name = "codespan",
-    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
-    visibility = ["//visibility:public"],
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
-        ":codespan",
         ":termcolor",
         ":unicode-width",
     ],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index d8c5cb0..e76c831 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -54,21 +54,11 @@ dependencies = [
 ]
 
 [[package]]
-name = "codespan"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "codespan-reporting"
-version = "0.7.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "657b2c99e1f17bc3e5153808d9f704c8ba6171c3fe45e69fde26e2876156938b"
+checksum = "7606d610349258b637bb639f7565bb7ee5fd6114130d2af59d0f39154e92426a"
 dependencies = [
- "codespan",
  "termcolor",
  "unicode-width",
 ]
@@ -79,7 +69,6 @@ version = "0.2.0"
 dependencies = [
  "anyhow",
  "cc",
- "codespan",
  "codespan-reporting",
  "cxx-test-suite",
  "cxxbridge-macro",
@@ -104,7 +93,6 @@ name = "cxxbridge-cmd"
 version = "0.2.0"
 dependencies = [
  "anyhow",
- "codespan",
  "codespan-reporting",
  "proc-macro2",
  "quote",

From f1d3a38e3f0c18c2acf2d579acc3f58fc45908da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 22:35:11 +0000
Subject: [PATCH 177/2232] Merge pull request #78 from dtolnay/codespan


Update to codespan-reporting 0.9
---

diff --git a/BUCK b/BUCK
index 2f80c9b..4357dd6 100644
--- a/BUCK
+++ b/BUCK
@@ -7,7 +7,6 @@ rust_library(
         ":macro",
         "//third-party:anyhow",
         "//third-party:cc",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
         "//third-party:proc-macro2",
@@ -26,7 +25,6 @@ rust_binary(
     },
     deps = [
         "//third-party:anyhow",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
diff --git a/BUILD b/BUILD
index db22203..59ac9fc 100644
--- a/BUILD
+++ b/BUILD
@@ -10,7 +10,6 @@ rust_library(
         ":cxxbridge-macro",
         "//third-party:anyhow",
         "//third-party:cc",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
         "//third-party:proc-macro2",
@@ -27,7 +26,6 @@ rust_binary(
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
-        "//third-party:codespan",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
diff --git a/Cargo.toml b/Cargo.toml
index 8432bc7..63a3a94 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,8 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 cc = "1.0.49"
-codespan = "0.7"
-codespan-reporting = "0.7"
+codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.0", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 7ee974c..aef31f6 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -16,8 +16,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 
 [dependencies]
 anyhow = "1.0"
-codespan = "0.7"
-codespan-reporting = "0.7"
+codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
diff --git a/gen/error.rs b/gen/error.rs
index b8ac337..ca78acb 100644
--- a/gen/error.rs
+++ b/gen/error.rs
@@ -1,8 +1,8 @@
 use crate::gen::Error;
 use crate::syntax;
 use anyhow::anyhow;
-use codespan::{FileId, Files};
 use codespan_reporting::diagnostic::{Diagnostic, Label};
+use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
 use codespan_reporting::term::{self, Config};
 use std::io::Write;
@@ -46,32 +46,30 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err
     }
     end_offset += end.column;
 
-    let mut files = Files::new();
+    let mut files = SimpleFiles::new();
     let file = files.add(path.to_string_lossy(), source);
 
-    let range = start_offset as u32..end_offset as u32;
-    let diagnostic = diagnose(file, range, error);
+    let diagnostic = diagnose(file, start_offset..end_offset, error);
 
     let config = Config::default();
     let _ = term::emit(stderr, &config, &files, &diagnostic);
 }
 
-fn diagnose(file: FileId, range: Range<u32>, error: syn::Error) -> Diagnostic {
+fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
     let message = error.to_string();
     let info = syntax::error::ERRORS
         .iter()
         .find(|e| message.contains(e.msg));
-    let mut diagnostic = if let Some(info) = info {
-        let label = Label::new(file, range, info.label.unwrap_or(&message));
-        let mut diagnostic = Diagnostic::new_error(&message, label);
-        if let Some(note) = info.note {
-            diagnostic = diagnostic.with_notes(vec![note.to_owned()]);
-        }
-        diagnostic
+    let mut diagnostic = Diagnostic::error().with_message(&message);
+    let mut label = Label::primary(file, range);
+    if let Some(info) = info {
+        label.message = info.label.map_or(message, str::to_owned);
+        diagnostic.labels.push(label);
+        diagnostic.notes.extend(info.note.map(str::to_owned));
     } else {
-        let label = Label::new(file, range, &message);
-        Diagnostic::new_error(&message, label)
-    };
+        label.message = message;
+        diagnostic.labels.push(label);
+    }
     diagnostic.code = Some("cxxbridge".to_owned());
     diagnostic
 }
diff --git a/third-party/BUCK b/third-party/BUCK
index ccb2107..14f2542 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -30,18 +30,10 @@ rust_library(
 )
 
 rust_library(
-    name = "codespan",
-    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
-    visibility = ["PUBLIC"],
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
-        ":codespan",
         ":termcolor",
         ":unicode-width",
     ],
diff --git a/third-party/BUILD b/third-party/BUILD
index ad779fd..daf9ea1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -35,18 +35,10 @@ rust_library(
 )
 
 rust_library(
-    name = "codespan",
-    srcs = glob(["vendor/codespan-0.7.0/src/**"]),
-    visibility = ["//visibility:public"],
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.7.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
-        ":codespan",
         ":termcolor",
         ":unicode-width",
     ],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index d8c5cb0..e76c831 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -54,21 +54,11 @@ dependencies = [
 ]
 
 [[package]]
-name = "codespan"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "codespan-reporting"
-version = "0.7.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "657b2c99e1f17bc3e5153808d9f704c8ba6171c3fe45e69fde26e2876156938b"
+checksum = "7606d610349258b637bb639f7565bb7ee5fd6114130d2af59d0f39154e92426a"
 dependencies = [
- "codespan",
  "termcolor",
  "unicode-width",
 ]
@@ -79,7 +69,6 @@ version = "0.2.0"
 dependencies = [
  "anyhow",
  "cc",
- "codespan",
  "codespan-reporting",
  "cxx-test-suite",
  "cxxbridge-macro",
@@ -104,7 +93,6 @@ name = "cxxbridge-cmd"
 version = "0.2.0"
 dependencies = [
  "anyhow",
- "codespan",
  "codespan-reporting",
  "proc-macro2",
  "quote",

From 35c82eb673314dee3b4e77cc600d1d2fa454c6c4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2020 23:48:36 +0000
Subject: [PATCH 178/2232] Prevent forgetting fields in PartialEq and Hash impls


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index dfaab55..6baa122 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -45,14 +45,32 @@ impl Eq for Ty1 {}
 
 impl PartialEq for Ty1 {
     fn eq(&self, other: &Ty1) -> bool {
-        self.name == other.name && self.inner == other.inner
+        let Ty1 {
+            name,
+            langle: _,
+            inner,
+            rangle: _,
+        } = self;
+        let Ty1 {
+            name: name2,
+            langle: _,
+            inner: inner2,
+            rangle: _,
+        } = other;
+        name == name2 && inner == inner2
     }
 }
 
 impl Hash for Ty1 {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        self.name.hash(state);
-        self.inner.hash(state);
+        let Ty1 {
+            name,
+            langle: _,
+            inner,
+            rangle: _,
+        } = self;
+        name.hash(state);
+        inner.hash(state);
     }
 }
 
@@ -60,12 +78,28 @@ impl Eq for Ref {}
 
 impl PartialEq for Ref {
     fn eq(&self, other: &Ref) -> bool {
-        self.inner == other.inner
+        let Ref {
+            ampersand: _,
+            mutability,
+            inner,
+        } = self;
+        let Ref {
+            ampersand: _,
+            mutability: mutability2,
+            inner: inner2,
+        } = other;
+        mutability.is_some() == mutability2.is_some() && inner == inner2
     }
 }
 
 impl Hash for Ref {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        self.inner.hash(state);
+        let Ref {
+            ampersand: _,
+            mutability,
+            inner,
+        } = self;
+        mutability.is_some().hash(state);
+        inner.hash(state);
     }
 }

From 417305a41aa8145dab3a7edf24c5a4e65fbbaeb0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 00:03:26 +0000
Subject: [PATCH 179/2232] Add function pointer types to syntax tree


---

diff --git a/gen/write.rs b/gen/write.rs
index ff5670c..8883d9b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -608,6 +608,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
+        Type::Fn(_) => unimplemented!(),
         Type::Void(_) => unreachable!(),
     }
 }
@@ -617,6 +618,7 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
         Type::Ref(_) => {}
+        Type::Fn(_) => unimplemented!(),
         Type::Void(_) => unreachable!(),
     }
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index ef3faff..be61226 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -167,6 +167,7 @@ fn describe(ty: &Type, types: &Types) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6baa122..57b42d1 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Ref, Signature, Ty1, Type};
+use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
@@ -20,6 +20,7 @@ impl Hash for Type {
             Type::UniquePtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
+            Type::Fn(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -35,6 +36,7 @@ impl PartialEq for Type {
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
@@ -103,3 +105,62 @@ impl Hash for Ref {
         inner.hash(state);
     }
 }
+
+impl Eq for Signature {}
+
+impl PartialEq for Signature {
+    fn eq(&self, other: &Signature) -> bool {
+        let Signature {
+            fn_token: _,
+            receiver,
+            args,
+            ret,
+            throws,
+        } = self;
+        let Signature {
+            fn_token: _,
+            receiver: receiver2,
+            args: args2,
+            ret: ret2,
+            throws: throws2,
+        } = other;
+        receiver == receiver2 && args == args2 && ret == ret2 && throws == throws2
+    }
+}
+
+impl Hash for Signature {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Signature {
+            fn_token: _,
+            receiver,
+            args,
+            ret,
+            throws,
+        } = self;
+        receiver.hash(state);
+        args.hash(state);
+        ret.hash(state);
+        throws.hash(state);
+    }
+}
+
+impl Eq for Receiver {}
+
+impl PartialEq for Receiver {
+    fn eq(&self, other: &Receiver) -> bool {
+        let Receiver { mutability, ident } = self;
+        let Receiver {
+            mutability: mutability2,
+            ident: ident2,
+        } = other;
+        mutability.is_some() == mutability2.is_some() && ident == ident2
+    }
+}
+
+impl Hash for Receiver {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Receiver { mutability, ident } = self;
+        mutability.is_some().hash(state);
+        ident.hash(state);
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f2e1c1c..6274cf1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -59,6 +59,7 @@ pub struct Signature {
     pub throws: bool,
 }
 
+#[derive(Eq, PartialEq, Hash)]
 pub struct Var {
     pub ident: Ident,
     pub ty: Type,
@@ -75,6 +76,7 @@ pub enum Type {
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Fn(Box<Signature>),
     Void(Span),
 }
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 52c47d5..3bbe872 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
-use quote::{quote_spanned, ToTokens};
+use quote::{quote, quote_spanned, ToTokens};
 use syn::Token;
 
 impl ToTokens for Type {
@@ -16,6 +16,21 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Fn(f) => {
+                let fn_token = f.fn_token;
+                let args = &f.args;
+                tokens.extend(quote!(#fn_token(#(#args),*)));
+                let mut ret = match &f.ret {
+                    Some(ret) => quote!(#ret),
+                    None => quote!(()),
+                };
+                if f.throws {
+                    ret = quote!(::std::result::Result<#ret, _>);
+                }
+                if f.ret.is_some() || f.throws {
+                    tokens.extend(quote!(-> #ret));
+                }
+            }
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index f9f87f3..f65b12f 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -26,6 +26,14 @@ impl<'a> Types<'a> {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Fn(f) => {
+                    if let Some(ret) = &f.ret {
+                        visit(all, ret);
+                    }
+                    for arg in &f.args {
+                        visit(all, &arg.ty);
+                    }
+                }
             }
         }
 

From d2bb3da09b77f8831b9428a15eb96b3b96f626e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 00:19:39 +0000
Subject: [PATCH 180/2232] Suppress declare_interior_mutable_const lint


---

diff --git a/src/lib.rs b/src/lib.rs
index 8d1ba19..b3bf41c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -335,6 +335,7 @@
 #![doc(html_root_url = "https://docs.rs/cxx/0.1.2")]
 #![deny(improper_ctypes)]
 #![allow(
+    clippy::declare_interior_mutable_const,
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::missing_safety_doc,

From db96ed9f517562132622426548e94c775bcf20db Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 00:20:39 +0000
Subject: [PATCH 181/2232] Resolve transmute_ptr_to_ptr lint


---

diff --git a/src/lib.rs b/src/lib.rs
index b3bf41c..4dbc97a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -345,7 +345,6 @@
     clippy::or_fun_call,
     clippy::ptr_arg,
     clippy::toplevel_ref_arg,
-    clippy::transmute_ptr_to_ptr,
     clippy::useless_let_if_seq
 )]
 
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 258576d..113adfd 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -14,7 +14,7 @@ impl RustString {
     }
 
     pub fn from_ref(s: &String) -> &Self {
-        unsafe { std::mem::transmute::<&String, &RustString>(s) }
+        unsafe { &*(s as *const String as *const RustString) }
     }
 
     pub fn into_string(self) -> String {

From 2d40845a49d46571056ba030b096529df54d3a6c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 00:24:16 +0000
Subject: [PATCH 182/2232] Eliminate use of transmute in Result::exception


---

diff --git a/src/result.rs b/src/result.rs
index 047260b..296efea 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,7 +1,6 @@
 use crate::exception::Exception;
 use crate::rust_str::RustStr;
 use std::fmt::Display;
-use std::mem;
 use std::ptr;
 use std::result::Result as StdResult;
 use std::slice;
@@ -50,10 +49,10 @@ impl Result {
             Ok(())
         } else {
             let err = self.err;
-            let slice = slice::from_raw_parts(err.ptr.as_ptr(), err.len);
-            let s = str::from_utf8_unchecked(slice);
+            let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len);
+            let s = str::from_utf8_unchecked_mut(slice);
             Err(Exception {
-                what: mem::transmute::<*const str, Box<str>>(s),
+                what: Box::from_raw(s),
             })
         }
     }

From 33d302978062f1384c5657f11d07401602edf481 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 01:18:36 +0000
Subject: [PATCH 183/2232] Add flag to inject additional #include lines


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index b2cde40..3577f72 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -33,6 +33,10 @@ struct Opt {
     /// Emit header with declarations only
     #[structopt(long)]
     header: bool,
+
+    /// Any additional headers to #include
+    #[structopt(short, long)]
+    include: Vec<String>,
 }
 
 fn write(content: impl AsRef<[u8]>) {
@@ -42,9 +46,13 @@ fn write(content: impl AsRef<[u8]>) {
 fn main() {
     let opt = Opt::from_args();
 
+    let gen = gen::Opt {
+        include: opt.include,
+    };
+
     match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::do_generate_header(&input)),
-        (Some(input), false) => write(gen::do_generate_bridge(&input)),
+        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
+        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
         (None, true) => write(include::HEADER),
         (None, false) => unreachable!(), // enforced by required_unless
     }
diff --git a/gen/include.rs b/gen/include.rs
index a642c0a..7bec492 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -49,6 +49,12 @@ impl Includes {
     }
 }
 
+impl Extend<String> for Includes {
+    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
+        self.custom.extend(iter);
+    }
+}
+
 impl Display for Includes {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for include in &self.custom {
diff --git a/gen/mod.rs b/gen/mod.rs
index df9f3ee..9a34705 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -36,17 +36,23 @@ struct Input {
     module: Vec<Item>,
 }
 
-pub(super) fn do_generate_bridge(path: &Path) -> OutFile {
+#[derive(Default)]
+pub(super) struct Opt {
+    /// Any additional headers to #include
+    pub include: Vec<String>,
+}
+
+pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> OutFile {
     let header = false;
-    generate(path, header)
+    generate(path, opt, header)
 }
 
-pub(super) fn do_generate_header(path: &Path) -> OutFile {
+pub(super) fn do_generate_header(path: &Path, opt: Opt) -> OutFile {
     let header = true;
-    generate(path, header)
+    generate(path, opt, header)
 }
 
-fn generate(path: &Path, header: bool) -> OutFile {
+fn generate(path: &Path, opt: Opt, header: bool) -> OutFile {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
@@ -57,7 +63,7 @@ fn generate(path: &Path, header: bool) -> OutFile {
         let apis = syntax::parse_items(bridge.module)?;
         let types = Types::collect(&apis)?;
         check::typecheck(&apis, &types)?;
-        let out = write::gen(bridge.namespace, &apis, &types, header);
+        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
         Ok(out)
     })() {
         Ok(out) => out,
diff --git a/gen/write.rs b/gen/write.rs
index 8883d9b..f0c9077 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,10 +1,16 @@
-use crate::gen::include;
 use crate::gen::out::OutFile;
+use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{Api, ExternFn, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
-pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: bool) -> OutFile {
+pub(super) fn gen(
+    namespace: Vec<String>,
+    apis: &[Api],
+    types: &Types,
+    opt: Opt,
+    header: bool,
+) -> OutFile {
     let mut out_file = OutFile::new(namespace.clone(), header);
     let out = &mut out_file;
 
@@ -12,6 +18,7 @@ pub(super) fn gen(namespace: Vec<String>, apis: &[Api], types: &Types, header: b
         writeln!(out, "#pragma once");
     }
 
+    out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
             out.include.insert(include.value());
diff --git a/src/lib.rs b/src/lib.rs
index 4dbc97a..09326f5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -383,6 +383,7 @@ pub mod private {
 }
 
 use crate::error::Result;
+use crate::gen::Opt;
 use anyhow::anyhow;
 use std::fs;
 use std::io::{self, Write};
@@ -465,13 +466,13 @@ impl Build {
 }
 
 fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
-    let header = gen::do_generate_header(rust_source_file);
+    let header = gen::do_generate_header(rust_source_file, Opt::default());
     let header_path = paths::out_with_extension(rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
     fs::write(&header_path, header)?;
     paths::symlink_header(&header_path, rust_source_file);
 
-    let bridge = gen::do_generate_bridge(rust_source_file);
+    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
     let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
     fs::write(&bridge_path, bridge)?;
     let mut build = paths::cc_build();

From d95b119931f3e167738110ab659b47add6451286 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 03:07:46 +0000
Subject: [PATCH 184/2232] Preserve original tokens of Signature


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 57b42d1..27aa43a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -116,6 +116,7 @@ impl PartialEq for Signature {
             args,
             ret,
             throws,
+            tokens: _,
         } = self;
         let Signature {
             fn_token: _,
@@ -123,6 +124,7 @@ impl PartialEq for Signature {
             args: args2,
             ret: ret2,
             throws: throws2,
+            tokens: _,
         } = other;
         receiver == receiver2 && args == args2 && ret == ret2 && throws == throws2
     }
@@ -136,6 +138,7 @@ impl Hash for Signature {
             args,
             ret,
             throws,
+            tokens: _,
         } = self;
         receiver.hash(state);
         args.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 6274cf1..7d2ca19 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -12,7 +12,7 @@ pub mod set;
 mod tokens;
 pub mod types;
 
-use proc_macro2::{Ident, Span};
+use proc_macro2::{Ident, Span, TokenStream};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
@@ -57,6 +57,7 @@ pub struct Signature {
     pub args: Vec<Var>,
     pub ret: Option<Type>,
     pub throws: bool,
+    pub tokens: TokenStream,
 }
 
 #[derive(Eq, PartialEq, Hash)]
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 10db16e..58237f3 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -205,7 +205,11 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
+    let mut foreign_fn2 = foreign_fn.clone();
+    foreign_fn2.attrs.clear();
+    let tokens = quote!(#foreign_fn2);
     let semi_token = foreign_fn.semi_token;
+
     Ok(ExternFn {
         lang,
         doc,
@@ -216,6 +220,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
             args,
             ret,
             throws,
+            tokens,
         },
         semi_token,
     })
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 3bbe872..ed5b315 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -77,8 +77,6 @@ impl ToTokens for Derive {
 
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.fn_token.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
-        self.semi_token.to_tokens(tokens);
+        self.sig.tokens.to_tokens(tokens);
     }
 }

From c071b89c2c7e618970609f068669c62b9ad55240 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 03:14:00 +0000
Subject: [PATCH 185/2232] Parse function pointer types


---

diff --git a/syntax/check.rs b/syntax/check.rs
index be61226..1fe3daf 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -45,6 +45,7 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                     errors.push(unsupported_reference_type(ty));
                 }
             }
+            Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
             _ => {}
         }
     }
@@ -213,3 +214,7 @@ fn return_by_value(ty: &Type, types: &Types) -> Error {
     let message = format!("returning {} by value is not supported", desc);
     Error::new_spanned(ty, message)
 }
+
+fn unimplemented_fn_type(ty: &Type) -> Error {
+    Error::new_spanned(ty, "function pointer support is not implemented yet")
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 58237f3..3d35f78 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,11 +3,11 @@ use crate::syntax::{
     Ty1, Type, Var,
 };
 use proc_macro2::Ident;
-use quote::quote;
+use quote::{format_ident, quote};
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType, TypePath,
-    TypeReference,
+    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
+    TypeBareFn, TypePath, TypeReference,
 };
 
 pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
@@ -176,32 +176,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     }
 
     let mut throws = false;
-    let ret = match &foreign_fn.sig.output {
-        ReturnType::Default => None,
-        ReturnType::Type(_, ret) => {
-            let mut ret = ret.as_ref();
-            if let RustType::Path(ty) = ret {
-                let path = &ty.path;
-                if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
-                    let segment = &path.segments[0];
-                    let ident = segment.ident.clone();
-                    if let PathArguments::AngleBracketed(generic) = &segment.arguments {
-                        if ident == "Result" && generic.args.len() == 1 {
-                            if let GenericArgument::Type(arg) = &generic.args[0] {
-                                ret = arg;
-                                throws = true;
-                            }
-                        }
-                    }
-                }
-            }
-            match parse_type(ret)? {
-                Type::Void(_) => None,
-                ty => Some(ty),
-            }
-        }
-    };
-
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws)?;
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
@@ -230,6 +205,7 @@ fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
         RustType::Path(ty) => parse_type_path(ty),
+        RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
@@ -290,6 +266,71 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
+fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
+    if ty.lifetimes.is_some() {
+        return Err(Error::new_spanned(
+            ty,
+            "function pointer with lifetime parameters is not supported yet",
+        ));
+    }
+    if ty.variadic.is_some() {
+        return Err(Error::new_spanned(
+            ty,
+            "variadic function pointer is not supported yet",
+        ));
+    }
+    let args = ty
+        .inputs
+        .iter()
+        .enumerate()
+        .map(|(i, arg)| {
+            let ty = parse_type(&arg.ty)?;
+            let ident = match &arg.name {
+                Some(ident) => ident.0.clone(),
+                None => format_ident!("_{}", i),
+            };
+            Ok(Var { ident, ty })
+        })
+        .collect::<Result<_>>()?;
+    let mut throws = false;
+    let ret = parse_return_type(&ty.output, &mut throws)?;
+    let tokens = quote!(#ty);
+    Ok(Type::Fn(Box::new(Signature {
+        fn_token: ty.fn_token,
+        receiver: None,
+        args,
+        ret,
+        throws,
+        tokens,
+    })))
+}
+
+fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>> {
+    let mut ret = match ty {
+        ReturnType::Default => return Ok(None),
+        ReturnType::Type(_, ret) => ret.as_ref(),
+    };
+    if let RustType::Path(ty) = ret {
+        let path = &ty.path;
+        if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
+            let segment = &path.segments[0];
+            let ident = segment.ident.clone();
+            if let PathArguments::AngleBracketed(generic) = &segment.arguments {
+                if ident == "Result" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        ret = arg;
+                        *throws = true;
+                    }
+                }
+            }
+        }
+    }
+    match parse_type(ret)? {
+        Type::Void(_) => Ok(None),
+        ty => Ok(Some(ty)),
+    }
+}
+
 fn check_reserved_name(ident: &Ident) -> Result<()> {
     if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
         Err(Error::new(ident.span(), "reserved name"))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index ed5b315..59bb0de 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
-use quote::{quote, quote_spanned, ToTokens};
+use quote::{quote_spanned, ToTokens};
 use syn::Token;
 
 impl ToTokens for Type {
@@ -16,21 +16,7 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
-            Type::Fn(f) => {
-                let fn_token = f.fn_token;
-                let args = &f.args;
-                tokens.extend(quote!(#fn_token(#(#args),*)));
-                let mut ret = match &f.ret {
-                    Some(ret) => quote!(#ret),
-                    None => quote!(()),
-                };
-                if f.throws {
-                    ret = quote!(::std::result::Result<#ret, _>);
-                }
-                if f.ret.is_some() || f.throws {
-                    tokens.extend(quote!(-> #ret));
-                }
-            }
+            Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
@@ -80,3 +66,9 @@ impl ToTokens for ExternFn {
         self.sig.tokens.to_tokens(tokens);
     }
 }
+
+impl ToTokens for Signature {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.tokens.to_tokens(tokens);
+    }
+}

From 265f6a079dd32c772ce35420b12891e2141c18e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 03:14:00 +0000
Subject: [PATCH 186/2232] Suppress some clippy lints in test suite


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fe6a364..bd9d4df 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::boxed_local, clippy::trivially_copy_pass_by_ref)]
+
 use cxx::{CxxString, UniquePtr};
 use std::fmt::{self, Display};
 

From a4dd952094b9d04af94dbc5839d3a46df3960ab0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 19 2020 03:31:52 +0000
Subject: [PATCH 187/2232] Merge pull request #79 from dtolnay/fn


Parse function pointer types
---

diff --git a/syntax/check.rs b/syntax/check.rs
index be61226..1fe3daf 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -45,6 +45,7 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
                     errors.push(unsupported_reference_type(ty));
                 }
             }
+            Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
             _ => {}
         }
     }
@@ -213,3 +214,7 @@ fn return_by_value(ty: &Type, types: &Types) -> Error {
     let message = format!("returning {} by value is not supported", desc);
     Error::new_spanned(ty, message)
 }
+
+fn unimplemented_fn_type(ty: &Type) -> Error {
+    Error::new_spanned(ty, "function pointer support is not implemented yet")
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 58237f3..3d35f78 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,11 +3,11 @@ use crate::syntax::{
     Ty1, Type, Var,
 };
 use proc_macro2::Ident;
-use quote::quote;
+use quote::{format_ident, quote};
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType, TypePath,
-    TypeReference,
+    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
+    TypeBareFn, TypePath, TypeReference,
 };
 
 pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
@@ -176,32 +176,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     }
 
     let mut throws = false;
-    let ret = match &foreign_fn.sig.output {
-        ReturnType::Default => None,
-        ReturnType::Type(_, ret) => {
-            let mut ret = ret.as_ref();
-            if let RustType::Path(ty) = ret {
-                let path = &ty.path;
-                if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
-                    let segment = &path.segments[0];
-                    let ident = segment.ident.clone();
-                    if let PathArguments::AngleBracketed(generic) = &segment.arguments {
-                        if ident == "Result" && generic.args.len() == 1 {
-                            if let GenericArgument::Type(arg) = &generic.args[0] {
-                                ret = arg;
-                                throws = true;
-                            }
-                        }
-                    }
-                }
-            }
-            match parse_type(ret)? {
-                Type::Void(_) => None,
-                ty => Some(ty),
-            }
-        }
-    };
-
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws)?;
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
@@ -230,6 +205,7 @@ fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
         RustType::Path(ty) => parse_type_path(ty),
+        RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
@@ -290,6 +266,71 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
+fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
+    if ty.lifetimes.is_some() {
+        return Err(Error::new_spanned(
+            ty,
+            "function pointer with lifetime parameters is not supported yet",
+        ));
+    }
+    if ty.variadic.is_some() {
+        return Err(Error::new_spanned(
+            ty,
+            "variadic function pointer is not supported yet",
+        ));
+    }
+    let args = ty
+        .inputs
+        .iter()
+        .enumerate()
+        .map(|(i, arg)| {
+            let ty = parse_type(&arg.ty)?;
+            let ident = match &arg.name {
+                Some(ident) => ident.0.clone(),
+                None => format_ident!("_{}", i),
+            };
+            Ok(Var { ident, ty })
+        })
+        .collect::<Result<_>>()?;
+    let mut throws = false;
+    let ret = parse_return_type(&ty.output, &mut throws)?;
+    let tokens = quote!(#ty);
+    Ok(Type::Fn(Box::new(Signature {
+        fn_token: ty.fn_token,
+        receiver: None,
+        args,
+        ret,
+        throws,
+        tokens,
+    })))
+}
+
+fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>> {
+    let mut ret = match ty {
+        ReturnType::Default => return Ok(None),
+        ReturnType::Type(_, ret) => ret.as_ref(),
+    };
+    if let RustType::Path(ty) = ret {
+        let path = &ty.path;
+        if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
+            let segment = &path.segments[0];
+            let ident = segment.ident.clone();
+            if let PathArguments::AngleBracketed(generic) = &segment.arguments {
+                if ident == "Result" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        ret = arg;
+                        *throws = true;
+                    }
+                }
+            }
+        }
+    }
+    match parse_type(ret)? {
+        Type::Void(_) => Ok(None),
+        ty => Ok(Some(ty)),
+    }
+}
+
 fn check_reserved_name(ident: &Ident) -> Result<()> {
     if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
         Err(Error::new(ident.span(), "reserved name"))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index ed5b315..59bb0de 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
-use quote::{quote, quote_spanned, ToTokens};
+use quote::{quote_spanned, ToTokens};
 use syn::Token;
 
 impl ToTokens for Type {
@@ -16,21 +16,7 @@ impl ToTokens for Type {
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
-            Type::Fn(f) => {
-                let fn_token = f.fn_token;
-                let args = &f.args;
-                tokens.extend(quote!(#fn_token(#(#args),*)));
-                let mut ret = match &f.ret {
-                    Some(ret) => quote!(#ret),
-                    None => quote!(()),
-                };
-                if f.throws {
-                    ret = quote!(::std::result::Result<#ret, _>);
-                }
-                if f.ret.is_some() || f.throws {
-                    tokens.extend(quote!(-> #ret));
-                }
-            }
+            Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
     }
@@ -80,3 +66,9 @@ impl ToTokens for ExternFn {
         self.sig.tokens.to_tokens(tokens);
     }
 }
+
+impl ToTokens for Signature {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.tokens.to_tokens(tokens);
+    }
+}

From 30430f13c92a64f571f04b555b908da0b10e67e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 20 2020 03:49:34 +0000
Subject: [PATCH 188/2232] Include <cstddef> for size_t


---

diff --git a/gen/include.rs b/gen/include.rs
index 7bec492..e3a9dd7 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -30,6 +30,7 @@ fn find_line(line: &str) -> Option<usize> {
 pub struct Includes {
     custom: Vec<String>,
     pub array: bool,
+    pub cstddef: bool,
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
@@ -63,6 +64,9 @@ impl Display for Includes {
         if self.array {
             writeln!(f, "#include <array>")?;
         }
+        if self.cstddef {
+            writeln!(f, "#include <cstddef>")?;
+        }
         if self.cstdint {
             writeln!(f, "#include <cstdint>")?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index f0c9077..a4e2eb2 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -91,10 +91,11 @@ fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
             Type::Ident(ident) => match Atom::from(ident) {
-                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-                | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
+                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
+                | Some(I64) => out.include.cstdint = true,
+                Some(Usize) => out.include.cstddef = true,
                 Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
diff --git a/include/cxx.h b/include/cxx.h
index 1026743..50f8f69 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -1,5 +1,6 @@
 #pragma once
 #include <array>
+#include <cstddef>
 #include <cstdint>
 #include <exception>
 #include <iosfwd>

From 09462acd4b1b89dd6e11af78973ae2a7ce270270 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 20 2020 21:58:56 +0000
Subject: [PATCH 189/2232] Disallow shared structs having 0 fields


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 1fe3daf..742ecc2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
-use proc_macro2::Ident;
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types, Var};
+use proc_macro2::{Delimiter, Group, Ident, TokenStream};
+use quote::quote;
 use syn::{Error, Result};
 
 pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
@@ -53,6 +54,9 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
     for api in apis {
         match api {
             Api::Struct(strct) => {
+                if strct.fields.is_empty() {
+                    errors.push(struct_empty(strct));
+                }
                 for field in &strct.fields {
                     if is_unsized(&field.ty, types) {
                         errors.push(field_by_value(field, types));
@@ -197,6 +201,14 @@ fn unsupported_unique_ptr_target(unique_ptr: &Ty1) -> Error {
     Error::new_spanned(unique_ptr, "unsupported unique_ptr target type")
 }
 
+fn struct_empty(strct: &Struct) -> Error {
+    let struct_token = strct.struct_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(strct.brace_token.span);
+    let span = quote!(#struct_token #brace_token);
+    Error::new_spanned(span, "structs without any fields are not supported")
+}
+
 fn field_by_value(field: &Var, types: &Types) -> Error {
     let desc = describe(&field.ty, types);
     let message = format!("using {} by value is not supported", desc);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 7d2ca19..38e21b0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,7 +13,7 @@ mod tokens;
 pub mod types;
 
 use proc_macro2::{Ident, Span, TokenStream};
-use syn::{LitStr, Token};
+use syn::{token::Brace, LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -40,6 +40,7 @@ pub struct Struct {
     pub derives: Vec<Ident>,
     pub struct_token: Token![struct],
     pub ident: Ident,
+    pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d35f78..a00f8dd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -46,26 +46,32 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     let mut derives = Vec::new();
     attrs::parse(&item.attrs, &mut doc, Some(&mut derives))?;
     check_reserved_name(&item.ident)?;
-    match item.fields {
-        Fields::Named(fields) => Ok(Api::Struct(Struct {
-            doc,
-            derives,
-            struct_token: item.struct_token,
-            ident: item.ident,
-            fields: fields
-                .named
-                .into_iter()
-                .map(|field| {
-                    Ok(Var {
-                        ident: field.ident.unwrap(),
-                        ty: parse_type(&field.ty)?,
-                    })
+
+    let fields = match item.fields {
+        Fields::Named(fields) => fields,
+        Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
+        Fields::Unnamed(_) => {
+            return Err(Error::new_spanned(item, "tuple structs are not supported"))
+        }
+    };
+
+    Ok(Api::Struct(Struct {
+        doc,
+        derives,
+        struct_token: item.struct_token,
+        ident: item.ident,
+        brace_token: fields.brace_token,
+        fields: fields
+            .named
+            .into_iter()
+            .map(|field| {
+                Ok(Var {
+                    ident: field.ident.unwrap(),
+                    ty: parse_type(&field.ty)?,
                 })
-                .collect::<Result<_>>()?,
-        })),
-        Fields::Unit => Err(Error::new_spanned(item, "unit structs are not supported")),
-        Fields::Unnamed(_) => Err(Error::new_spanned(item, "tuple structs are not supported")),
-    }
+            })
+            .collect::<Result<_>>()?,
+    }))
 }
 
 fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
diff --git a/tests/ui/empty_struct.rs b/tests/ui/empty_struct.rs
new file mode 100644
index 0000000..060cfe0
--- /dev/null
+++ b/tests/ui/empty_struct.rs
@@ -0,0 +1,6 @@
+#[cxx::bridge]
+mod ffi {
+    struct Empty {}
+}
+
+fn main() {}
diff --git a/tests/ui/empty_struct.stderr b/tests/ui/empty_struct.stderr
new file mode 100644
index 0000000..612476b
--- /dev/null
+++ b/tests/ui/empty_struct.stderr
@@ -0,0 +1,5 @@
+error: structs without any fields are not supported
+ --> $DIR/empty_struct.rs:3:5
+  |
+3 |     struct Empty {}
+  |     ^^^^^^^^^^^^^^^

From 54b96bfe28db1c79606012f91ca7f750bbceb752 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 20 2020 22:11:35 +0000
Subject: [PATCH 190/2232] Merge pull request #81 from dtolnay/empty


Disallow shared structs having 0 fields
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 1fe3daf..742ecc2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Ty1, Type, Types, Var};
-use proc_macro2::Ident;
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types, Var};
+use proc_macro2::{Delimiter, Group, Ident, TokenStream};
+use quote::quote;
 use syn::{Error, Result};
 
 pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
@@ -53,6 +54,9 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
     for api in apis {
         match api {
             Api::Struct(strct) => {
+                if strct.fields.is_empty() {
+                    errors.push(struct_empty(strct));
+                }
                 for field in &strct.fields {
                     if is_unsized(&field.ty, types) {
                         errors.push(field_by_value(field, types));
@@ -197,6 +201,14 @@ fn unsupported_unique_ptr_target(unique_ptr: &Ty1) -> Error {
     Error::new_spanned(unique_ptr, "unsupported unique_ptr target type")
 }
 
+fn struct_empty(strct: &Struct) -> Error {
+    let struct_token = strct.struct_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(strct.brace_token.span);
+    let span = quote!(#struct_token #brace_token);
+    Error::new_spanned(span, "structs without any fields are not supported")
+}
+
 fn field_by_value(field: &Var, types: &Types) -> Error {
     let desc = describe(&field.ty, types);
     let message = format!("using {} by value is not supported", desc);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 7d2ca19..38e21b0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,7 +13,7 @@ mod tokens;
 pub mod types;
 
 use proc_macro2::{Ident, Span, TokenStream};
-use syn::{LitStr, Token};
+use syn::{token::Brace, LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -40,6 +40,7 @@ pub struct Struct {
     pub derives: Vec<Ident>,
     pub struct_token: Token![struct],
     pub ident: Ident,
+    pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d35f78..a00f8dd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -46,26 +46,32 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     let mut derives = Vec::new();
     attrs::parse(&item.attrs, &mut doc, Some(&mut derives))?;
     check_reserved_name(&item.ident)?;
-    match item.fields {
-        Fields::Named(fields) => Ok(Api::Struct(Struct {
-            doc,
-            derives,
-            struct_token: item.struct_token,
-            ident: item.ident,
-            fields: fields
-                .named
-                .into_iter()
-                .map(|field| {
-                    Ok(Var {
-                        ident: field.ident.unwrap(),
-                        ty: parse_type(&field.ty)?,
-                    })
+
+    let fields = match item.fields {
+        Fields::Named(fields) => fields,
+        Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
+        Fields::Unnamed(_) => {
+            return Err(Error::new_spanned(item, "tuple structs are not supported"))
+        }
+    };
+
+    Ok(Api::Struct(Struct {
+        doc,
+        derives,
+        struct_token: item.struct_token,
+        ident: item.ident,
+        brace_token: fields.brace_token,
+        fields: fields
+            .named
+            .into_iter()
+            .map(|field| {
+                Ok(Var {
+                    ident: field.ident.unwrap(),
+                    ty: parse_type(&field.ty)?,
                 })
-                .collect::<Result<_>>()?,
-        })),
-        Fields::Unit => Err(Error::new_spanned(item, "unit structs are not supported")),
-        Fields::Unnamed(_) => Err(Error::new_spanned(item, "tuple structs are not supported")),
-    }
+            })
+            .collect::<Result<_>>()?,
+    }))
 }
 
 fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
diff --git a/tests/ui/empty_struct.rs b/tests/ui/empty_struct.rs
new file mode 100644
index 0000000..060cfe0
--- /dev/null
+++ b/tests/ui/empty_struct.rs
@@ -0,0 +1,6 @@
+#[cxx::bridge]
+mod ffi {
+    struct Empty {}
+}
+
+fn main() {}
diff --git a/tests/ui/empty_struct.stderr b/tests/ui/empty_struct.stderr
new file mode 100644
index 0000000..612476b
--- /dev/null
+++ b/tests/ui/empty_struct.stderr
@@ -0,0 +1,5 @@
+error: structs without any fields are not supported
+ --> $DIR/empty_struct.rs:3:5
+  |
+3 |     struct Empty {}
+  |     ^^^^^^^^^^^^^^^

From 84849300714aab955eae57285327d53c8862ba5b Mon Sep 17 00:00:00 2001
From: Myron Ahn <myronahn@gmail.com>
Date: Mar 25 2020 15:39:00 +0000
Subject: [PATCH 191/2232] Result now works for UniquePtr and other types


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e11b2d3..69b7fb5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -225,10 +225,24 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             #local_name(#(#vars),*)
         }
     };
-    let expr = efn
-        .ret
-        .as_ref()
-        .and_then(|ret| match ret {
+    let expr = if efn.throws {
+        efn.ret.as_ref().and_then(|ret| match ret {
+            Type::Ident(ident) if ident == RustString => {
+                Some(quote!(#call.map(|r| r.into_string())))
+            }
+            Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
+            Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
+            Type::Ref(ty) => match &ty.inner {
+                Type::Ident(ident) if ident == RustString => {
+                    Some(quote!(#call.map(|r| r.as_string())))
+                }
+                _ => None,
+            },
+            Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
+            _ => None,
+        })
+    } else {
+        efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
@@ -239,7 +253,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::Str(_) => Some(quote!(#call.as_str())),
             _ => None,
         })
-        .unwrap_or(call);
+    }
+    .unwrap_or(call);
     quote! {
         #doc
         pub fn #ident(#(#args),*) #ret {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index bd9d4df..5d0598e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -36,6 +36,8 @@ pub mod ffi {
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
         fn c_fail_return_primitive() -> Result<usize>;
+        fn c_try_return_string() -> Result<UniquePtr<CxxString>>;
+        fn c_fail_return_string() -> Result<UniquePtr<CxxString>>;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 184e8aa..90538b9 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -98,6 +98,14 @@ size_t c_try_return_primitive() { return 2020; }
 
 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
 
+std::unique_ptr<std::string> c_try_return_string() {
+  return std::unique_ptr<std::string>(new std::string("ok"));
+}
+
+std::unique_ptr<std::string> c_fail_return_string() { 
+  throw std::logic_error("logic error getting string"); 
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6a5f802..7f45287 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -39,5 +39,7 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_try_return_void();
 size_t c_try_return_primitive();
 size_t c_fail_return_primitive();
+std::unique_ptr<std::string> c_try_return_string();
+std::unique_ptr<std::string> c_fail_return_string();
 
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index d86ebd2..9f1ea24 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -45,6 +45,18 @@ fn test_c_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
+    assert_eq!(
+        "ok",
+        ffi::c_try_return_string()
+            .unwrap()
+            .as_ref()
+            .unwrap()
+            .to_string()
+    );
+    assert_eq!(
+        "logic error getting string",
+        ffi::c_fail_return_string().unwrap_err().what(),
+    );
 }
 
 #[test]

From a8520d417fa25e19fc2427213c18295ee835d1e4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 19:14:19 +0000
Subject: [PATCH 192/2232] Merge pull request #83 from myronahn/feature/result-quick-fix


Make Result work with UniquePtr, RustBox, RustString, Str
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e11b2d3..69b7fb5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -225,10 +225,24 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             #local_name(#(#vars),*)
         }
     };
-    let expr = efn
-        .ret
-        .as_ref()
-        .and_then(|ret| match ret {
+    let expr = if efn.throws {
+        efn.ret.as_ref().and_then(|ret| match ret {
+            Type::Ident(ident) if ident == RustString => {
+                Some(quote!(#call.map(|r| r.into_string())))
+            }
+            Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
+            Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
+            Type::Ref(ty) => match &ty.inner {
+                Type::Ident(ident) if ident == RustString => {
+                    Some(quote!(#call.map(|r| r.as_string())))
+                }
+                _ => None,
+            },
+            Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
+            _ => None,
+        })
+    } else {
+        efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
@@ -239,7 +253,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::Str(_) => Some(quote!(#call.as_str())),
             _ => None,
         })
-        .unwrap_or(call);
+    }
+    .unwrap_or(call);
     quote! {
         #doc
         pub fn #ident(#(#args),*) #ret {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index bd9d4df..5d0598e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -36,6 +36,8 @@ pub mod ffi {
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
         fn c_fail_return_primitive() -> Result<usize>;
+        fn c_try_return_string() -> Result<UniquePtr<CxxString>>;
+        fn c_fail_return_string() -> Result<UniquePtr<CxxString>>;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 184e8aa..90538b9 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -98,6 +98,14 @@ size_t c_try_return_primitive() { return 2020; }
 
 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
 
+std::unique_ptr<std::string> c_try_return_string() {
+  return std::unique_ptr<std::string>(new std::string("ok"));
+}
+
+std::unique_ptr<std::string> c_fail_return_string() { 
+  throw std::logic_error("logic error getting string"); 
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6a5f802..7f45287 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -39,5 +39,7 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_try_return_void();
 size_t c_try_return_primitive();
 size_t c_fail_return_primitive();
+std::unique_ptr<std::string> c_try_return_string();
+std::unique_ptr<std::string> c_fail_return_string();
 
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index d86ebd2..9f1ea24 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -45,6 +45,18 @@ fn test_c_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
+    assert_eq!(
+        "ok",
+        ffi::c_try_return_string()
+            .unwrap()
+            .as_ref()
+            .unwrap()
+            .to_string()
+    );
+    assert_eq!(
+        "logic error getting string",
+        ffi::c_fail_return_string().unwrap_err().what(),
+    );
 }
 
 #[test]

From f90ce8585ba5406e604e0aa5954b87f1ab2d8e25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 19:15:18 +0000
Subject: [PATCH 193/2232] Remove trailing whitespace from tests from PR 83


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 90538b9..6ca27db 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -102,8 +102,8 @@ std::unique_ptr<std::string> c_try_return_string() {
   return std::unique_ptr<std::string>(new std::string("ok"));
 }
 
-std::unique_ptr<std::string> c_fail_return_string() { 
-  throw std::logic_error("logic error getting string"); 
+std::unique_ptr<std::string> c_fail_return_string() {
+  throw std::logic_error("logic error getting string");
 }
 
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {

From d930a79e6fb665789117800b55e8ab96d4e61357 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 19:24:40 +0000
Subject: [PATCH 194/2232] Write CxxString fmt impls in terms of to_string_lossy


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index f2cca5b..6b69435 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -80,12 +80,12 @@ impl CxxString {
 
 impl Display for CxxString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
+        Display::fmt(self.to_string_lossy().as_ref(), f)
     }
 }
 
 impl Debug for CxxString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Debug::fmt(&String::from_utf8_lossy(self.as_bytes()), f)
+        Debug::fmt(self.to_string_lossy().as_ref(), f)
     }
 }

From 42ebfa2d5e0968078d8a29c40fe09ddbd545b49f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 19:26:22 +0000
Subject: [PATCH 195/2232] Add some PartialEq impls for CxxString


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 6b69435..d3d128c 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -89,3 +89,21 @@ impl Debug for CxxString {
         Debug::fmt(self.to_string_lossy().as_ref(), f)
     }
 }
+
+impl PartialEq for CxxString {
+    fn eq(&self, other: &CxxString) -> bool {
+        self.as_bytes() == other.as_bytes()
+    }
+}
+
+impl PartialEq<CxxString> for str {
+    fn eq(&self, other: &CxxString) -> bool {
+        self.as_bytes() == other.as_bytes()
+    }
+}
+
+impl PartialEq<str> for CxxString {
+    fn eq(&self, other: &str) -> bool {
+        self.as_bytes() == other.as_bytes()
+    }
+}
diff --git a/tests/test.rs b/tests/test.rs
index 9f1ea24..87a18ad 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -45,14 +45,7 @@ fn test_c_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
-    assert_eq!(
-        "ok",
-        ffi::c_try_return_string()
-            .unwrap()
-            .as_ref()
-            .unwrap()
-            .to_string()
-    );
+    assert_eq!("ok", ffi::c_try_return_string().unwrap().as_ref().unwrap());
     assert_eq!(
         "logic error getting string",
         ffi::c_fail_return_string().unwrap_err().what(),

From 9964262630a98b2f6b6d3309b306b2bb0af70410 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 23:44:11 +0000
Subject: [PATCH 196/2232] Implement and test some more fallible return types


---

diff --git a/gen/write.rs b/gen/write.rs
index a4e2eb2..72962f2 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -297,7 +297,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     if efn.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type(out, &efn.ret, types);
+        write_extern_return_type_space(out, &efn.ret, types);
     }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
@@ -317,7 +317,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if !efn.args.is_empty() {
             write!(out, ", ");
         }
-        write_return_type(out, &efn.ret);
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
         write!(out, "*return$");
     }
     writeln!(out, ") noexcept {{");
@@ -340,15 +340,15 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     if indirect_return {
         write!(out, "new (return$) ");
-        write_type(out, efn.ret.as_ref().unwrap());
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
-    } else if let Some(ret) = &efn.ret {
+    } else if efn.ret.is_some() {
         write!(out, "return ");
-        match ret {
-            Type::Ref(_) => write!(out, "&"),
-            Type::Str(_) => write!(out, "::rust::Str::Repr("),
-            _ => {}
-        }
+    }
+    match &efn.ret {
+        Some(Type::Ref(_)) => write!(out, "&"),
+        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
+        _ => {}
     }
     write!(out, "{}$(", efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
@@ -378,7 +378,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) => write!(out, ")"),
+        Some(Type::Str(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -405,7 +405,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     if efn.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type(out, &efn.ret, types);
+        write_extern_return_type_space(out, &efn.ret, types);
     }
     for name in out.namespace.clone() {
         write!(out, "{}$", name);
@@ -542,7 +542,34 @@ fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
         .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
 }
 
-fn write_extern_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::RustBox(ty) | Type::UniquePtr(ty) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Type::Ref(ty) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
+        Type::Str(_) => write!(out, "::rust::Str::Repr"),
+        _ => write_type(out, ty),
+    }
+}
+
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
+    write_indirect_return_type(out, ty);
+    match ty {
+        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
+        Type::Str(_) => write!(out, " "),
+        _ => write_space_after_type(out, ty),
+    }
+}
+
+fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
             write_type_space(out, &ty.inner);
@@ -623,6 +650,10 @@ fn write_type(out: &mut OutFile, ty: &Type) {
 
 fn write_type_space(out: &mut OutFile, ty: &Type) {
     write_type(out, ty);
+    write_space_after_type(out, ty);
+}
+
+fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
         Type::Ref(_) => {}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5d0598e..492fc91 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -36,8 +36,11 @@ pub mod ffi {
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
         fn c_fail_return_primitive() -> Result<usize>;
-        fn c_try_return_string() -> Result<UniquePtr<CxxString>>;
-        fn c_fail_return_string() -> Result<UniquePtr<CxxString>>;
+        fn c_try_return_box() -> Result<Box<R>>;
+        fn c_try_return_ref(s: &String) -> Result<&String>;
+        fn c_try_return_str(s: &str) -> Result<&str>;
+        fn c_try_return_rust_string() -> Result<String>;
+        fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6ca27db..6384ac1 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -98,12 +98,16 @@ size_t c_try_return_primitive() { return 2020; }
 
 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
 
-std::unique_ptr<std::string> c_try_return_string() {
-  return std::unique_ptr<std::string>(new std::string("ok"));
-}
+rust::Box<R> c_try_return_box() { return c_return_box(); }
+
+const rust::String &c_try_return_ref(const rust::String &s) { return s; }
+
+rust::Str c_try_return_str(rust::Str s) { return s; }
+
+rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
-std::unique_ptr<std::string> c_fail_return_string() {
-  throw std::logic_error("logic error getting string");
+std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
+  return c_return_unique_ptr_string();
 }
 
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7f45287..e0e7624 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -39,7 +39,10 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_try_return_void();
 size_t c_try_return_primitive();
 size_t c_fail_return_primitive();
-std::unique_ptr<std::string> c_try_return_string();
-std::unique_ptr<std::string> c_fail_return_string();
+rust::Box<R> c_try_return_box();
+const rust::String &c_try_return_ref(const rust::String &);
+rust::Str c_try_return_str(rust::Str);
+rust::String c_try_return_rust_string();
+std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index 87a18ad..6a6fc3e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -38,17 +38,26 @@ fn test_c_return() {
             .to_str()
             .unwrap()
     );
+}
 
+#[test]
+fn test_c_try_return() {
     assert_eq!((), ffi::c_try_return_void().unwrap());
     assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
     assert_eq!(
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
-    assert_eq!("ok", ffi::c_try_return_string().unwrap().as_ref().unwrap());
+    assert_eq!(2020, *ffi::c_try_return_box().unwrap());
+    assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
+    assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
+    assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
     assert_eq!(
-        "logic error getting string",
-        ffi::c_fail_return_string().unwrap_err().what(),
+        "2020",
+        ffi::c_try_return_unique_ptr_string()
+            .unwrap()
+            .as_ref()
+            .unwrap()
     );
 }
 

From d4e6830d40756c822892409506e666e560f23203 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2020 23:59:02 +0000
Subject: [PATCH 197/2232] Split up typecheck logic to functions


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 742ecc2..f5ccba9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -5,47 +5,14 @@ use quote::quote;
 use syn::{Error, Result};
 
 pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
-    let mut errors = Vec::new();
+    let ref mut errors = Vec::new();
 
     for ty in types {
         match ty {
-            Type::Ident(ident) => {
-                if Atom::from(ident).is_none()
-                    && !types.structs.contains_key(ident)
-                    && !types.cxx.contains(ident)
-                    && !types.rust.contains(ident)
-                {
-                    errors.push(unsupported_type(ident));
-                }
-            }
-            Type::RustBox(ptr) => {
-                if let Type::Ident(ident) = &ptr.inner {
-                    if types.cxx.contains(ident) {
-                        errors.push(unsupported_cxx_type_in_box(ptr));
-                    }
-                    if Atom::from(ident).is_none() {
-                        continue;
-                    }
-                }
-                errors.push(unsupported_box_target(ptr));
-            }
-            Type::UniquePtr(ptr) => {
-                if let Type::Ident(ident) = &ptr.inner {
-                    if types.rust.contains(ident) {
-                        errors.push(unsupported_rust_type_in_unique_ptr(ptr));
-                    }
-                    match Atom::from(ident) {
-                        None | Some(CxxString) => continue,
-                        _ => {}
-                    }
-                }
-                errors.push(unsupported_unique_ptr_target(ptr));
-            }
-            Type::Ref(ty) => {
-                if let Type::Void(_) = ty.inner {
-                    errors.push(unsupported_reference_type(ty));
-                }
-            }
+            Type::Ident(ident) => check_type_ident(errors, types, ident),
+            Type::RustBox(ptr) => check_type_box(errors, types, ptr),
+            Type::UniquePtr(ptr) => check_type_unique_ptr(errors, types, ptr),
+            Type::Ref(ty) => check_type_ref(errors, ty),
             Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
             _ => {}
         }
@@ -53,28 +20,8 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
 
     for api in apis {
         match api {
-            Api::Struct(strct) => {
-                if strct.fields.is_empty() {
-                    errors.push(struct_empty(strct));
-                }
-                for field in &strct.fields {
-                    if is_unsized(&field.ty, types) {
-                        errors.push(field_by_value(field, types));
-                    }
-                }
-            }
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                for arg in &efn.args {
-                    if is_unsized(&arg.ty, types) {
-                        errors.push(argument_by_value(arg, types));
-                    }
-                }
-                if let Some(ty) = &efn.ret {
-                    if is_unsized(ty, types) {
-                        errors.push(return_by_value(ty, types));
-                    }
-                }
-            }
+            Api::Struct(strct) => check_api_struct(errors, types, strct),
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(errors, types, efn),
             _ => {}
         }
     }
@@ -88,9 +35,9 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
         }
     }
 
-    ident::check_all(apis, &mut errors);
+    ident::check_all(apis, errors);
 
-    let mut iter = errors.into_iter();
+    let mut iter = errors.drain(..);
     let mut all_errors = match iter.next() {
         Some(err) => err,
         None => return Ok(()),
@@ -101,13 +48,69 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
     Err(all_errors)
 }
 
-fn is_unsized(ty: &Type, types: &Types) -> bool {
-    let ident = match ty {
-        Type::Ident(ident) => ident,
-        Type::Void(_) => return true,
-        _ => return false,
-    };
-    ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
+fn check_type_ident(errors: &mut Vec<Error>, types: &Types, ident: &Ident) {
+    if Atom::from(ident).is_none()
+        && !types.structs.contains_key(ident)
+        && !types.cxx.contains(ident)
+        && !types.rust.contains(ident)
+    {
+        errors.push(unsupported_type(ident));
+    }
+}
+
+fn check_type_box(errors: &mut Vec<Error>, types: &Types, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if types.cxx.contains(ident) {
+            errors.push(unsupported_cxx_type_in_box(ptr));
+        }
+        if Atom::from(ident).is_none() {
+            return;
+        }
+    }
+    errors.push(unsupported_box_target(ptr));
+}
+
+fn check_type_unique_ptr(errors: &mut Vec<Error>, types: &Types, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if types.rust.contains(ident) {
+            errors.push(unsupported_rust_type_in_unique_ptr(ptr));
+        }
+        match Atom::from(ident) {
+            None | Some(CxxString) => return,
+            _ => {}
+        }
+    }
+    errors.push(unsupported_unique_ptr_target(ptr));
+}
+
+fn check_type_ref(errors: &mut Vec<Error>, ty: &Ref) {
+    if let Type::Void(_) = ty.inner {
+        errors.push(unsupported_reference_type(ty));
+    }
+}
+
+fn check_api_struct(errors: &mut Vec<Error>, types: &Types, strct: &Struct) {
+    if strct.fields.is_empty() {
+        errors.push(struct_empty(strct));
+    }
+    for field in &strct.fields {
+        if is_unsized(&field.ty, types) {
+            errors.push(field_by_value(field, types));
+        }
+    }
+}
+
+fn check_api_fn(errors: &mut Vec<Error>, types: &Types, efn: &ExternFn) {
+    for arg in &efn.args {
+        if is_unsized(&arg.ty, types) {
+            errors.push(argument_by_value(arg, types));
+        }
+    }
+    if let Some(ty) = &efn.ret {
+        if is_unsized(ty, types) {
+            errors.push(return_by_value(ty, types));
+        }
+    }
 }
 
 fn check_mut_return_restriction(efn: &ExternFn) -> Result<()> {
@@ -153,6 +156,15 @@ fn check_multiple_arg_lifetimes(efn: &ExternFn) -> Result<()> {
     }
 }
 
+fn is_unsized(ty: &Type, types: &Types) -> bool {
+    let ident = match ty {
+        Type::Ident(ident) => ident,
+        Type::Void(_) => return true,
+        _ => return false,
+    };
+    ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
+}
+
 fn describe(ty: &Type, types: &Types) -> String {
     match ty {
         Type::Ident(ident) => {

From 26a2a1deda5da262a48a01d017cf99aca5f089c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2020 00:35:17 +0000
Subject: [PATCH 198/2232] Collect typecheck context into a struct


---

diff --git a/syntax/check.rs b/syntax/check.rs
index f5ccba9..5a3590f 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -4,139 +4,144 @@ use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::quote;
 use syn::{Error, Result};
 
+struct Check<'a> {
+    apis: &'a [Api],
+    types: &'a Types<'a>,
+    errors: &'a mut Vec<Error>,
+}
+
 pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
-    let ref mut errors = Vec::new();
+    let mut errors = Vec::new();
+    let mut cx = Check {
+        apis,
+        types,
+        errors: &mut errors,
+    };
+    do_typecheck(&mut cx);
+    combine_errors(errors)
+}
 
-    for ty in types {
+fn do_typecheck(cx: &mut Check) {
+    for ty in cx.types {
         match ty {
-            Type::Ident(ident) => check_type_ident(errors, types, ident),
-            Type::RustBox(ptr) => check_type_box(errors, types, ptr),
-            Type::UniquePtr(ptr) => check_type_unique_ptr(errors, types, ptr),
-            Type::Ref(ty) => check_type_ref(errors, ty),
-            Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
+            Type::Ident(ident) => check_type_ident(cx, ident),
+            Type::RustBox(ptr) => check_type_box(cx, ptr),
+            Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Fn(_) => cx.errors.push(unimplemented_fn_type(ty)),
             _ => {}
         }
     }
 
-    for api in apis {
+    for api in cx.apis {
         match api {
-            Api::Struct(strct) => check_api_struct(errors, types, strct),
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(errors, types, efn),
+            Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
         }
     }
 
-    for api in apis {
+    for api in cx.apis {
         if let Api::CxxFunction(efn) = api {
-            errors.extend(check_mut_return_restriction(efn).err());
+            check_mut_return_restriction(cx, efn);
         }
         if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            errors.extend(check_multiple_arg_lifetimes(efn).err());
+            check_multiple_arg_lifetimes(cx, efn);
         }
     }
 
-    ident::check_all(apis, errors);
-
-    let mut iter = errors.drain(..);
-    let mut all_errors = match iter.next() {
-        Some(err) => err,
-        None => return Ok(()),
-    };
-    for err in iter {
-        all_errors.combine(err);
-    }
-    Err(all_errors)
+    ident::check_all(cx.apis, cx.errors);
 }
 
-fn check_type_ident(errors: &mut Vec<Error>, types: &Types, ident: &Ident) {
+fn check_type_ident(cx: &mut Check, ident: &Ident) {
     if Atom::from(ident).is_none()
-        && !types.structs.contains_key(ident)
-        && !types.cxx.contains(ident)
-        && !types.rust.contains(ident)
+        && !cx.types.structs.contains_key(ident)
+        && !cx.types.cxx.contains(ident)
+        && !cx.types.rust.contains(ident)
     {
-        errors.push(unsupported_type(ident));
+        cx.errors.push(unsupported_type(ident));
     }
 }
 
-fn check_type_box(errors: &mut Vec<Error>, types: &Types, ptr: &Ty1) {
+fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if types.cxx.contains(ident) {
-            errors.push(unsupported_cxx_type_in_box(ptr));
+        if cx.types.cxx.contains(ident) {
+            cx.errors.push(unsupported_cxx_type_in_box(ptr));
         }
         if Atom::from(ident).is_none() {
             return;
         }
     }
-    errors.push(unsupported_box_target(ptr));
+    cx.errors.push(unsupported_box_target(ptr));
 }
 
-fn check_type_unique_ptr(errors: &mut Vec<Error>, types: &Types, ptr: &Ty1) {
+fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if types.rust.contains(ident) {
-            errors.push(unsupported_rust_type_in_unique_ptr(ptr));
+        if cx.types.rust.contains(ident) {
+            cx.errors.push(unsupported_rust_type_in_unique_ptr(ptr));
         }
         match Atom::from(ident) {
             None | Some(CxxString) => return,
             _ => {}
         }
     }
-    errors.push(unsupported_unique_ptr_target(ptr));
+    cx.errors.push(unsupported_unique_ptr_target(ptr));
 }
 
-fn check_type_ref(errors: &mut Vec<Error>, ty: &Ref) {
+fn check_type_ref(cx: &mut Check, ty: &Ref) {
     if let Type::Void(_) = ty.inner {
-        errors.push(unsupported_reference_type(ty));
+        cx.errors.push(unsupported_reference_type(ty));
     }
 }
 
-fn check_api_struct(errors: &mut Vec<Error>, types: &Types, strct: &Struct) {
+fn check_api_struct(cx: &mut Check, strct: &Struct) {
     if strct.fields.is_empty() {
-        errors.push(struct_empty(strct));
+        cx.errors.push(struct_empty(strct));
     }
     for field in &strct.fields {
-        if is_unsized(&field.ty, types) {
-            errors.push(field_by_value(field, types));
+        if is_unsized(cx, &field.ty) {
+            cx.errors.push(field_by_value(field, cx.types));
         }
     }
 }
 
-fn check_api_fn(errors: &mut Vec<Error>, types: &Types, efn: &ExternFn) {
+fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     for arg in &efn.args {
-        if is_unsized(&arg.ty, types) {
-            errors.push(argument_by_value(arg, types));
+        if is_unsized(cx, &arg.ty) {
+            cx.errors.push(argument_by_value(arg, cx.types));
         }
     }
     if let Some(ty) = &efn.ret {
-        if is_unsized(ty, types) {
-            errors.push(return_by_value(ty, types));
+        if is_unsized(cx, ty) {
+            cx.errors.push(return_by_value(ty, cx.types));
         }
     }
 }
 
-fn check_mut_return_restriction(efn: &ExternFn) -> Result<()> {
+fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutability.is_some() => {}
-        _ => return Ok(()),
+        _ => return,
     }
 
     for arg in &efn.args {
         if let Type::Ref(ty) = &arg.ty {
             if ty.mutability.is_some() {
-                return Ok(());
+                return;
             }
         }
     }
 
-    Err(Error::new_spanned(
+    cx.errors.push(Error::new_spanned(
         efn,
         "&mut return type is not allowed unless there is a &mut argument",
-    ))
+    ));
 }
 
-fn check_multiple_arg_lifetimes(efn: &ExternFn) -> Result<()> {
+fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(_)) => {}
-        _ => return Ok(()),
+        _ => return,
     }
 
     let mut reference_args = 0;
@@ -146,23 +151,33 @@ fn check_multiple_arg_lifetimes(efn: &ExternFn) -> Result<()> {
         }
     }
 
-    if reference_args == 1 {
-        Ok(())
-    } else {
-        Err(Error::new_spanned(
+    if reference_args != 1 {
+        cx.errors.push(Error::new_spanned(
             efn,
             "functions that return a reference must take exactly one input reference",
-        ))
+        ));
     }
 }
 
-fn is_unsized(ty: &Type, types: &Types) -> bool {
+fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
         Type::Void(_) => return true,
         _ => return false,
     };
-    ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
+    ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
+}
+
+fn combine_errors(errors: Vec<Error>) -> Result<()> {
+    let mut iter = errors.into_iter();
+    let mut all_errors = match iter.next() {
+        Some(err) => err,
+        None => return Ok(()),
+    };
+    for err in iter {
+        all_errors.combine(err);
+    }
+    Err(all_errors)
 }
 
 fn describe(ty: &Type, types: &Types) -> String {

From a420f0141aca0c434de8427f1dbd061dfdda4883 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2020 01:01:12 +0000
Subject: [PATCH 199/2232] Move error message construction into checking functions


These were pulled out originally because error message construction was
so verbose that it detracted from being able to follow the logic of the
checks, but now that checks are broken up into finer granularity the
messages can be inlined.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 5a3590f..256a193 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,7 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
-use quote::quote;
+use quote::{quote, ToTokens};
+use std::fmt::Display;
 use syn::{Error, Result};
 
 struct Check<'a> {
@@ -28,7 +29,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
-            Type::Fn(_) => cx.errors.push(unimplemented_fn_type(ty)),
+            Type::Fn(_) => cx.error(ty, "function pointer support is not implemented yet"),
             _ => {}
         }
     }
@@ -53,54 +54,68 @@ fn do_typecheck(cx: &mut Check) {
     ident::check_all(cx.apis, cx.errors);
 }
 
+impl Check<'_> {
+    fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
+        self.errors.push(Error::new_spanned(sp, msg));
+    }
+}
+
 fn check_type_ident(cx: &mut Check, ident: &Ident) {
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
-        cx.errors.push(unsupported_type(ident));
+        cx.error(ident, "unsupported type");
     }
 }
 
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.cxx.contains(ident) {
-            cx.errors.push(unsupported_cxx_type_in_box(ptr));
+            cx.error(ptr, error::BOX_CXX_TYPE.msg);
         }
+
         if Atom::from(ident).is_none() {
             return;
         }
     }
-    cx.errors.push(unsupported_box_target(ptr));
+
+    cx.error(ptr, "unsupported target type of Box");
 }
 
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
-            cx.errors.push(unsupported_rust_type_in_unique_ptr(ptr));
+            cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
         }
+
         match Atom::from(ident) {
             None | Some(CxxString) => return,
             _ => {}
         }
     }
-    cx.errors.push(unsupported_unique_ptr_target(ptr));
+
+    cx.error(ptr, "unsupported unique_ptr target type");
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
     if let Type::Void(_) = ty.inner {
-        cx.errors.push(unsupported_reference_type(ty));
+        cx.error(ty, "unsupported reference type");
     }
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
     if strct.fields.is_empty() {
-        cx.errors.push(struct_empty(strct));
+        let span = span_for_struct_error(strct);
+        cx.error(span, "structs without any fields are not supported");
     }
+
     for field in &strct.fields {
         if is_unsized(cx, &field.ty) {
-            cx.errors.push(field_by_value(field, cx.types));
+            let desc = describe(cx, &field.ty);
+            let msg = format!("using {} by value is not supported", desc);
+            cx.error(field, msg);
         }
     }
 }
@@ -108,12 +123,17 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     for arg in &efn.args {
         if is_unsized(cx, &arg.ty) {
-            cx.errors.push(argument_by_value(arg, cx.types));
+            let desc = describe(cx, &arg.ty);
+            let msg = format!("passing {} by value is not supported", desc);
+            cx.error(arg, msg);
         }
     }
+
     if let Some(ty) = &efn.ret {
         if is_unsized(cx, ty) {
-            cx.errors.push(return_by_value(ty, cx.types));
+            let desc = describe(cx, ty);
+            let msg = format!("returning {} by value is not supported", desc);
+            cx.error(ty, msg);
         }
     }
 }
@@ -132,10 +152,10 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
         }
     }
 
-    cx.errors.push(Error::new_spanned(
+    cx.error(
         efn,
         "&mut return type is not allowed unless there is a &mut argument",
-    ));
+    );
 }
 
 fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
@@ -152,10 +172,10 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
     }
 
     if reference_args != 1 {
-        cx.errors.push(Error::new_spanned(
+        cx.error(
             efn,
             "functions that return a reference must take exactly one input reference",
-        ));
+        );
     }
 }
 
@@ -168,6 +188,13 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
 }
 
+fn span_for_struct_error(strct: &Struct) -> TokenStream {
+    let struct_token = strct.struct_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(strct.brace_token.span);
+    quote!(#struct_token #brace_token)
+}
+
 fn combine_errors(errors: Vec<Error>) -> Result<()> {
     let mut iter = errors.into_iter();
     let mut all_errors = match iter.next() {
@@ -180,14 +207,14 @@ fn combine_errors(errors: Vec<Error>) -> Result<()> {
     Err(all_errors)
 }
 
-fn describe(ty: &Type, types: &Types) -> String {
+fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
-            if types.structs.contains_key(ident) {
+            if cx.types.structs.contains_key(ident) {
                 "struct".to_owned()
-            } else if types.cxx.contains(ident) {
+            } else if cx.types.cxx.contains(ident) {
                 "C++ type".to_owned()
-            } else if types.rust.contains(ident) {
+            } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
                 "C++ string".to_owned()
@@ -203,57 +230,3 @@ fn describe(ty: &Type, types: &Types) -> String {
         Type::Void(_) => "()".to_owned(),
     }
 }
-
-fn unsupported_type(ident: &Ident) -> Error {
-    Error::new(ident.span(), "unsupported type")
-}
-
-fn unsupported_reference_type(ty: &Ref) -> Error {
-    Error::new_spanned(ty, "unsupported reference type")
-}
-
-fn unsupported_cxx_type_in_box(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, error::BOX_CXX_TYPE.msg)
-}
-
-fn unsupported_box_target(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unsupported target type of Box")
-}
-
-fn unsupported_rust_type_in_unique_ptr(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unique_ptr of a Rust type is not supported yet")
-}
-
-fn unsupported_unique_ptr_target(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unsupported unique_ptr target type")
-}
-
-fn struct_empty(strct: &Struct) -> Error {
-    let struct_token = strct.struct_token;
-    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
-    brace_token.set_span(strct.brace_token.span);
-    let span = quote!(#struct_token #brace_token);
-    Error::new_spanned(span, "structs without any fields are not supported")
-}
-
-fn field_by_value(field: &Var, types: &Types) -> Error {
-    let desc = describe(&field.ty, types);
-    let message = format!("using {} by value is not supported", desc);
-    Error::new_spanned(field, message)
-}
-
-fn argument_by_value(arg: &Var, types: &Types) -> Error {
-    let desc = describe(&arg.ty, types);
-    let message = format!("passing {} by value is not supported", desc);
-    Error::new_spanned(arg, message)
-}
-
-fn return_by_value(ty: &Type, types: &Types) -> Error {
-    let desc = describe(ty, types);
-    let message = format!("returning {} by value is not supported", desc);
-    Error::new_spanned(ty, message)
-}
-
-fn unimplemented_fn_type(ty: &Type) -> Error {
-    Error::new_spanned(ty, "function pointer support is not implemented yet")
-}

From cd0793f0f1b461435ea04e2ae83fed1e03388d64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2020 01:12:15 +0000
Subject: [PATCH 200/2232] Merge pull request #84 from dtolnay/check


Typecheck refactor
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 742ecc2..256a193 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,139 +1,167 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types, Var};
+use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
-use quote::quote;
+use quote::{quote, ToTokens};
+use std::fmt::Display;
 use syn::{Error, Result};
 
+struct Check<'a> {
+    apis: &'a [Api],
+    types: &'a Types<'a>,
+    errors: &'a mut Vec<Error>,
+}
+
 pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
     let mut errors = Vec::new();
+    let mut cx = Check {
+        apis,
+        types,
+        errors: &mut errors,
+    };
+    do_typecheck(&mut cx);
+    combine_errors(errors)
+}
 
-    for ty in types {
+fn do_typecheck(cx: &mut Check) {
+    for ty in cx.types {
         match ty {
-            Type::Ident(ident) => {
-                if Atom::from(ident).is_none()
-                    && !types.structs.contains_key(ident)
-                    && !types.cxx.contains(ident)
-                    && !types.rust.contains(ident)
-                {
-                    errors.push(unsupported_type(ident));
-                }
-            }
-            Type::RustBox(ptr) => {
-                if let Type::Ident(ident) = &ptr.inner {
-                    if types.cxx.contains(ident) {
-                        errors.push(unsupported_cxx_type_in_box(ptr));
-                    }
-                    if Atom::from(ident).is_none() {
-                        continue;
-                    }
-                }
-                errors.push(unsupported_box_target(ptr));
-            }
-            Type::UniquePtr(ptr) => {
-                if let Type::Ident(ident) = &ptr.inner {
-                    if types.rust.contains(ident) {
-                        errors.push(unsupported_rust_type_in_unique_ptr(ptr));
-                    }
-                    match Atom::from(ident) {
-                        None | Some(CxxString) => continue,
-                        _ => {}
-                    }
-                }
-                errors.push(unsupported_unique_ptr_target(ptr));
-            }
-            Type::Ref(ty) => {
-                if let Type::Void(_) = ty.inner {
-                    errors.push(unsupported_reference_type(ty));
-                }
-            }
-            Type::Fn(_) => errors.push(unimplemented_fn_type(ty)),
+            Type::Ident(ident) => check_type_ident(cx, ident),
+            Type::RustBox(ptr) => check_type_box(cx, ptr),
+            Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Fn(_) => cx.error(ty, "function pointer support is not implemented yet"),
             _ => {}
         }
     }
 
-    for api in apis {
+    for api in cx.apis {
         match api {
-            Api::Struct(strct) => {
-                if strct.fields.is_empty() {
-                    errors.push(struct_empty(strct));
-                }
-                for field in &strct.fields {
-                    if is_unsized(&field.ty, types) {
-                        errors.push(field_by_value(field, types));
-                    }
-                }
-            }
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                for arg in &efn.args {
-                    if is_unsized(&arg.ty, types) {
-                        errors.push(argument_by_value(arg, types));
-                    }
-                }
-                if let Some(ty) = &efn.ret {
-                    if is_unsized(ty, types) {
-                        errors.push(return_by_value(ty, types));
-                    }
-                }
-            }
+            Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
         }
     }
 
-    for api in apis {
+    for api in cx.apis {
         if let Api::CxxFunction(efn) = api {
-            errors.extend(check_mut_return_restriction(efn).err());
+            check_mut_return_restriction(cx, efn);
         }
         if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            errors.extend(check_multiple_arg_lifetimes(efn).err());
+            check_multiple_arg_lifetimes(cx, efn);
         }
     }
 
-    ident::check_all(apis, &mut errors);
+    ident::check_all(cx.apis, cx.errors);
+}
 
-    let mut iter = errors.into_iter();
-    let mut all_errors = match iter.next() {
-        Some(err) => err,
-        None => return Ok(()),
-    };
-    for err in iter {
-        all_errors.combine(err);
+impl Check<'_> {
+    fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
+        self.errors.push(Error::new_spanned(sp, msg));
     }
-    Err(all_errors)
 }
 
-fn is_unsized(ty: &Type, types: &Types) -> bool {
-    let ident = match ty {
-        Type::Ident(ident) => ident,
-        Type::Void(_) => return true,
-        _ => return false,
-    };
-    ident == CxxString || types.cxx.contains(ident) || types.rust.contains(ident)
+fn check_type_ident(cx: &mut Check, ident: &Ident) {
+    if Atom::from(ident).is_none()
+        && !cx.types.structs.contains_key(ident)
+        && !cx.types.cxx.contains(ident)
+        && !cx.types.rust.contains(ident)
+    {
+        cx.error(ident, "unsupported type");
+    }
 }
 
-fn check_mut_return_restriction(efn: &ExternFn) -> Result<()> {
+fn check_type_box(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.cxx.contains(ident) {
+            cx.error(ptr, error::BOX_CXX_TYPE.msg);
+        }
+
+        if Atom::from(ident).is_none() {
+            return;
+        }
+    }
+
+    cx.error(ptr, "unsupported target type of Box");
+}
+
+fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(ident) {
+            cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
+        }
+
+        match Atom::from(ident) {
+            None | Some(CxxString) => return,
+            _ => {}
+        }
+    }
+
+    cx.error(ptr, "unsupported unique_ptr target type");
+}
+
+fn check_type_ref(cx: &mut Check, ty: &Ref) {
+    if let Type::Void(_) = ty.inner {
+        cx.error(ty, "unsupported reference type");
+    }
+}
+
+fn check_api_struct(cx: &mut Check, strct: &Struct) {
+    if strct.fields.is_empty() {
+        let span = span_for_struct_error(strct);
+        cx.error(span, "structs without any fields are not supported");
+    }
+
+    for field in &strct.fields {
+        if is_unsized(cx, &field.ty) {
+            let desc = describe(cx, &field.ty);
+            let msg = format!("using {} by value is not supported", desc);
+            cx.error(field, msg);
+        }
+    }
+}
+
+fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
+    for arg in &efn.args {
+        if is_unsized(cx, &arg.ty) {
+            let desc = describe(cx, &arg.ty);
+            let msg = format!("passing {} by value is not supported", desc);
+            cx.error(arg, msg);
+        }
+    }
+
+    if let Some(ty) = &efn.ret {
+        if is_unsized(cx, ty) {
+            let desc = describe(cx, ty);
+            let msg = format!("returning {} by value is not supported", desc);
+            cx.error(ty, msg);
+        }
+    }
+}
+
+fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutability.is_some() => {}
-        _ => return Ok(()),
+        _ => return,
     }
 
     for arg in &efn.args {
         if let Type::Ref(ty) = &arg.ty {
             if ty.mutability.is_some() {
-                return Ok(());
+                return;
             }
         }
     }
 
-    Err(Error::new_spanned(
+    cx.error(
         efn,
         "&mut return type is not allowed unless there is a &mut argument",
-    ))
+    );
 }
 
-fn check_multiple_arg_lifetimes(efn: &ExternFn) -> Result<()> {
+fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(_)) => {}
-        _ => return Ok(()),
+        _ => return,
     }
 
     let mut reference_args = 0;
@@ -143,24 +171,50 @@ fn check_multiple_arg_lifetimes(efn: &ExternFn) -> Result<()> {
         }
     }
 
-    if reference_args == 1 {
-        Ok(())
-    } else {
-        Err(Error::new_spanned(
+    if reference_args != 1 {
+        cx.error(
             efn,
             "functions that return a reference must take exactly one input reference",
-        ))
+        );
+    }
+}
+
+fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
+    let ident = match ty {
+        Type::Ident(ident) => ident,
+        Type::Void(_) => return true,
+        _ => return false,
+    };
+    ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
+}
+
+fn span_for_struct_error(strct: &Struct) -> TokenStream {
+    let struct_token = strct.struct_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(strct.brace_token.span);
+    quote!(#struct_token #brace_token)
+}
+
+fn combine_errors(errors: Vec<Error>) -> Result<()> {
+    let mut iter = errors.into_iter();
+    let mut all_errors = match iter.next() {
+        Some(err) => err,
+        None => return Ok(()),
+    };
+    for err in iter {
+        all_errors.combine(err);
     }
+    Err(all_errors)
 }
 
-fn describe(ty: &Type, types: &Types) -> String {
+fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
-            if types.structs.contains_key(ident) {
+            if cx.types.structs.contains_key(ident) {
                 "struct".to_owned()
-            } else if types.cxx.contains(ident) {
+            } else if cx.types.cxx.contains(ident) {
                 "C++ type".to_owned()
-            } else if types.rust.contains(ident) {
+            } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
                 "C++ string".to_owned()
@@ -176,57 +230,3 @@ fn describe(ty: &Type, types: &Types) -> String {
         Type::Void(_) => "()".to_owned(),
     }
 }
-
-fn unsupported_type(ident: &Ident) -> Error {
-    Error::new(ident.span(), "unsupported type")
-}
-
-fn unsupported_reference_type(ty: &Ref) -> Error {
-    Error::new_spanned(ty, "unsupported reference type")
-}
-
-fn unsupported_cxx_type_in_box(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, error::BOX_CXX_TYPE.msg)
-}
-
-fn unsupported_box_target(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unsupported target type of Box")
-}
-
-fn unsupported_rust_type_in_unique_ptr(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unique_ptr of a Rust type is not supported yet")
-}
-
-fn unsupported_unique_ptr_target(unique_ptr: &Ty1) -> Error {
-    Error::new_spanned(unique_ptr, "unsupported unique_ptr target type")
-}
-
-fn struct_empty(strct: &Struct) -> Error {
-    let struct_token = strct.struct_token;
-    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
-    brace_token.set_span(strct.brace_token.span);
-    let span = quote!(#struct_token #brace_token);
-    Error::new_spanned(span, "structs without any fields are not supported")
-}
-
-fn field_by_value(field: &Var, types: &Types) -> Error {
-    let desc = describe(&field.ty, types);
-    let message = format!("using {} by value is not supported", desc);
-    Error::new_spanned(field, message)
-}
-
-fn argument_by_value(arg: &Var, types: &Types) -> Error {
-    let desc = describe(&arg.ty, types);
-    let message = format!("passing {} by value is not supported", desc);
-    Error::new_spanned(arg, message)
-}
-
-fn return_by_value(ty: &Type, types: &Types) -> Error {
-    let desc = describe(ty, types);
-    let message = format!("returning {} by value is not supported", desc);
-    Error::new_spanned(ty, message)
-}
-
-fn unimplemented_fn_type(ty: &Type) -> Error {
-    Error::new_spanned(ty, "function pointer support is not implemented yet")
-}

From d7e1f1e519dd3ea66fe98a88e6e3b81cc3fa085a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2020 03:18:39 +0000
Subject: [PATCH 201/2232] Split function pointer error message into specific cases


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 256a193..b44d0cc 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,7 +29,6 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
-            Type::Fn(_) => cx.error(ty, "function pointer support is not implemented yet"),
             _ => {}
         }
     }
@@ -100,9 +99,12 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
-    if let Type::Void(_) = ty.inner {
-        cx.error(ty, "unsupported reference type");
+    match ty.inner {
+        Type::Fn(_) | Type::Void(_) => {}
+        _ => return,
     }
+
+    cx.error(ty, "unsupported reference type");
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
@@ -117,6 +119,12 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
             let msg = format!("using {} by value is not supported", desc);
             cx.error(field, msg);
         }
+        if let Type::Fn(_) = field.ty {
+            cx.error(
+                field,
+                "function pointers in a struct field are not implemented yet",
+            );
+        }
     }
 }
 
@@ -127,6 +135,12 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             let msg = format!("passing {} by value is not supported", desc);
             cx.error(arg, msg);
         }
+        if let Type::Fn(_) = arg.ty {
+            cx.error(
+                arg,
+                "passing a function pointer argument is not implemented yet",
+            );
+        }
     }
 
     if let Some(ty) = &efn.ret {
@@ -135,6 +149,9 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             let msg = format!("returning {} by value is not supported", desc);
             cx.error(ty, msg);
         }
+        if let Type::Fn(_) = ty {
+            cx.error(ty, "returning a function pointer is not implemented yet");
+        }
     }
 }
 

From d140274c1078152ee57914f48de96b5ea74abecf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2020 05:21:42 +0000
Subject: [PATCH 202/2232] Emit bitcopy forward declaration needed by String constructor


---

diff --git a/gen/write.rs b/gen/write.rs
index 72962f2..a17f8f7 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -183,6 +183,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
+    if needs_rust_string {
+        out.next_section();
+        writeln!(out, "struct unsafe_bitcopy_t;");
+    }
+
     write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");

From 3c19e53ad1ff1808dc9e3d41ca88c8d1eb5f38f9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 03:32:14 +0000
Subject: [PATCH 203/2232] Enable Namespace to be used in format_ident


---

diff --git a/macro/src/namespace.rs b/macro/src/namespace.rs
index 678e7e0..d2b3e1c 100644
--- a/macro/src/namespace.rs
+++ b/macro/src/namespace.rs
@@ -1,4 +1,5 @@
 use crate::syntax::ident;
+use quote::IdentFragment;
 use std::fmt::{self, Display};
 use syn::parse::{Parse, ParseStream, Result};
 use syn::{Path, Token};
@@ -37,3 +38,9 @@ impl Display for Namespace {
         Ok(())
     }
 }
+
+impl IdentFragment for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(self, f)
+    }
+}

From 754e21c678efb3d8442d21c3af30b2f3554cef76 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 04:31:26 +0000
Subject: [PATCH 204/2232] Add a Namespace type in gen


---

diff --git a/gen/mod.rs b/gen/mod.rs
index 9a34705..8006898 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -3,10 +3,12 @@
 
 mod error;
 pub(super) mod include;
+mod namespace;
 pub(super) mod out;
 mod write;
 
 use self::error::format_err;
+use self::namespace::Namespace;
 use self::out::OutFile;
 use crate::syntax::{self, check, ident, Types};
 use quote::quote;
@@ -32,7 +34,7 @@ pub(super) enum Error {
 }
 
 struct Input {
-    namespace: Vec<String>,
+    namespace: Namespace,
     module: Vec<Item>,
 }
 
@@ -86,10 +88,9 @@ fn find_bridge_mod(syntax: File) -> Result<Input> {
                             )));
                         }
                     };
-                    return Ok(Input {
-                        namespace: parse_args(attr)?,
-                        module,
-                    });
+                    let namespace_segments = parse_args(attr)?;
+                    let namespace = Namespace::new(namespace_segments);
+                    return Ok(Input { namespace, module });
                 }
             }
         }
diff --git a/gen/namespace.rs b/gen/namespace.rs
new file mode 100644
index 0000000..c644352
--- /dev/null
+++ b/gen/namespace.rs
@@ -0,0 +1,44 @@
+use std::fmt::{self, Display};
+use std::slice::Iter;
+use std::vec::IntoIter;
+
+#[derive(Clone)]
+pub struct Namespace {
+    segments: Vec<String>,
+}
+
+impl Namespace {
+    pub fn new(segments: Vec<String>) -> Self {
+        Namespace { segments }
+    }
+
+    pub fn iter(&self) -> Iter<String> {
+        self.segments.iter()
+    }
+}
+
+impl Display for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for segment in self {
+            f.write_str(segment)?;
+            f.write_str("$")?;
+        }
+        Ok(())
+    }
+}
+
+impl<'a> IntoIterator for &'a Namespace {
+    type Item = &'a String;
+    type IntoIter = Iter<'a, String>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+impl IntoIterator for Namespace {
+    type Item = String;
+    type IntoIter = IntoIter<String>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.segments.into_iter()
+    }
+}
diff --git a/gen/out.rs b/gen/out.rs
index 2a5b17d..8783dc2 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,8 +1,9 @@
 use crate::gen::include::Includes;
+use crate::gen::namespace::Namespace;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
-    pub namespace: Vec<String>,
+    pub namespace: Namespace,
     pub header: bool,
     pub include: Includes,
     content: Vec<u8>,
@@ -11,7 +12,7 @@ pub(crate) struct OutFile {
 }
 
 impl OutFile {
-    pub fn new(namespace: Vec<String>, header: bool) -> Self {
+    pub fn new(namespace: Namespace, header: bool) -> Self {
         OutFile {
             namespace,
             header,
diff --git a/gen/write.rs b/gen/write.rs
index a17f8f7..a1d5748 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,3 +1,4 @@
+use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -5,7 +6,7 @@ use crate::syntax::{Api, ExternFn, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
-    namespace: Vec<String>,
+    namespace: Namespace,
     apis: &[Api],
     types: &Types,
     opt: Opt,

From 7ece56fb099f63c480ca58f004fda69aad3e82d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 04:31:26 +0000
Subject: [PATCH 205/2232] Allow write_fmt to work on &OutFile


---

diff --git a/gen/mod.rs b/gen/mod.rs
index 8006898..523ba1d 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -9,7 +9,6 @@ mod write;
 
 use self::error::format_err;
 use self::namespace::Namespace;
-use self::out::OutFile;
 use crate::syntax::{self, check, ident, Types};
 use quote::quote;
 use std::fs;
@@ -44,17 +43,17 @@ pub(super) struct Opt {
     pub include: Vec<String>,
 }
 
-pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> OutFile {
+pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
     generate(path, opt, header)
 }
 
-pub(super) fn do_generate_header(path: &Path, opt: Opt) -> OutFile {
+pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     let header = true;
     generate(path, opt, header)
 }
 
-fn generate(path: &Path, opt: Opt, header: bool) -> OutFile {
+fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
@@ -68,7 +67,7 @@ fn generate(path: &Path, opt: Opt, header: bool) -> OutFile {
         let out = write::gen(bridge.namespace, &apis, &types, opt, header);
         Ok(out)
     })() {
-        Ok(out) => out,
+        Ok(out) => out.content(),
         Err(err) => format_err(path, &source, err),
     }
 }
diff --git a/gen/out.rs b/gen/out.rs
index 8783dc2..35f2cd7 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,12 +1,17 @@
 use crate::gen::include::Includes;
 use crate::gen::namespace::Namespace;
+use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
     pub namespace: Namespace,
     pub header: bool,
     pub include: Includes,
-    content: Vec<u8>,
+    content: RefCell<Content>,
+}
+
+struct Content {
+    bytes: Vec<u8>,
     section_pending: bool,
     blocks_pending: Vec<&'static str>,
 }
@@ -17,65 +22,70 @@ impl OutFile {
             namespace,
             header,
             include: Includes::new(),
-            content: Vec::new(),
-            section_pending: false,
-            blocks_pending: Vec::new(),
+            content: RefCell::new(Content {
+                bytes: Vec::new(),
+                section_pending: false,
+                blocks_pending: Vec::new(),
+            }),
         }
     }
 
     // Write a blank line if the preceding section had any contents.
     pub fn next_section(&mut self) {
-        self.section_pending = true;
+        let content = self.content.get_mut();
+        content.section_pending = true;
     }
 
     pub fn begin_block(&mut self, block: &'static str) {
-        self.blocks_pending.push(block);
+        let content = self.content.get_mut();
+        content.blocks_pending.push(block);
     }
 
     pub fn end_block(&mut self, block: &'static str) {
-        if self.blocks_pending.pop().is_none() {
-            self.content.extend_from_slice(b"} // ");
-            self.content.extend_from_slice(block.as_bytes());
-            self.content.push(b'\n');
-            self.section_pending = true;
+        let content = self.content.get_mut();
+        if content.blocks_pending.pop().is_none() {
+            content.bytes.extend_from_slice(b"} // ");
+            content.bytes.extend_from_slice(block.as_bytes());
+            content.bytes.push(b'\n');
+            content.section_pending = true;
         }
     }
 
     pub fn prepend(&mut self, section: String) {
-        self.content.splice(..0, section.into_bytes());
+        let content = self.content.get_mut();
+        content.bytes.splice(..0, section.into_bytes());
+    }
+
+    pub fn write_fmt(&self, args: Arguments) {
+        let content = &mut *self.content.borrow_mut();
+        Write::write_fmt(content, args).unwrap();
     }
 
-    pub fn write_fmt(&mut self, args: Arguments) {
-        Write::write_fmt(self, args).unwrap();
+    pub fn content(&self) -> Vec<u8> {
+        self.content.borrow().bytes.clone()
     }
 }
 
-impl Write for OutFile {
+impl Write for Content {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         if !s.is_empty() {
             if !self.blocks_pending.is_empty() {
-                if !self.content.is_empty() {
-                    self.content.push(b'\n');
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    self.content.extend_from_slice(block.as_bytes());
-                    self.content.extend_from_slice(b" {\n");
+                    self.bytes.extend_from_slice(block.as_bytes());
+                    self.bytes.extend_from_slice(b" {\n");
                 }
                 self.section_pending = false;
             } else if self.section_pending {
-                if !self.content.is_empty() {
-                    self.content.push(b'\n');
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
                 }
                 self.section_pending = false;
             }
-            self.content.extend_from_slice(s.as_bytes());
+            self.bytes.extend_from_slice(s.as_bytes());
         }
         Ok(())
     }
 }
-
-impl AsRef<[u8]> for OutFile {
-    fn as_ref(&self) -> &[u8] {
-        &self.content
-    }
-}

From d815de0195c9af754542052bb29bb9659decda6b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 04:31:26 +0000
Subject: [PATCH 206/2232] Levarage the Display impl for namespace printing


---

diff --git a/gen/write.rs b/gen/write.rs
index a1d5748..1f7adda 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -305,10 +305,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    for name in out.namespace.clone() {
-        write!(out, "{}$", name);
-    }
-    write!(out, "cxxbridge02${}(", efn.ident);
+    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -413,10 +410,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    for name in out.namespace.clone() {
-        write!(out, "{}$", name);
-    }
-    write!(out, "cxxbridge02${}(", efn.ident);
+    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -487,10 +481,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if efn.throws {
             write!(out, "::rust::Str::Repr error$ = ");
         }
-        for name in out.namespace.clone() {
-            write!(out, "{}$", name);
-        }
-        write!(out, "cxxbridge02${}(", efn.ident);
+        write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
         for (i, arg) in efn.args.iter().enumerate() {
             if i > 0 {
                 write!(out, ", ");

From d71eb54c139b5dd576efe778751dda5c94a399f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 04:31:26 +0000
Subject: [PATCH 207/2232] No longer need to iterate Namespace by value


---

diff --git a/gen/namespace.rs b/gen/namespace.rs
index c644352..557e331 100644
--- a/gen/namespace.rs
+++ b/gen/namespace.rs
@@ -1,6 +1,5 @@
 use std::fmt::{self, Display};
 use std::slice::Iter;
-use std::vec::IntoIter;
 
 #[derive(Clone)]
 pub struct Namespace {
@@ -34,11 +33,3 @@ impl<'a> IntoIterator for &'a Namespace {
         self.iter()
     }
 }
-
-impl IntoIterator for Namespace {
-    type Item = String;
-    type IntoIter = IntoIter<String>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.segments.into_iter()
-    }
-}

From 75dca2e84620d79b8a69155d10967761ea543cdf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 04:50:25 +0000
Subject: [PATCH 208/2232] Passing function pointer from Rust to C++


---

diff --git a/gen/write.rs b/gen/write.rs
index 1f7adda..b745739 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@ use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -109,6 +109,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_string = false;
     let mut needs_rust_str = false;
     let mut needs_rust_box = false;
+    let mut needs_rust_fn = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -120,6 +121,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 out.include.string = true;
                 needs_rust_str = true;
             }
+            Type::Fn(_) => {
+                needs_rust_fn = true;
+            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -175,6 +179,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     if needs_rust_string
         || needs_rust_str
         || needs_rust_box
+        || needs_rust_fn
         || needs_rust_error
         || needs_unsafe_bitcopy
         || needs_manually_drop
@@ -192,6 +197,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
@@ -402,27 +408,71 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "  return throw$;");
     }
     writeln!(out, "}}");
+    for arg in &efn.args {
+        if let Type::Fn(f) = &arg.ty {
+            let var = &arg.ident;
+            write_function_pointer_trampoline(out, efn, var, f, types);
+        }
+    }
+}
+
+fn write_function_pointer_trampoline(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    var: &Ident,
+    f: &Signature,
+    types: &Types,
+) {
+    out.next_section();
+    let r_trampoline = format!("{}cxxbridge02${}${}$1", out.namespace, efn.ident, var);
+    let indirect_call = true;
+    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
+
+    out.next_section();
+    let c_trampoline = format!("{}cxxbridge02${}${}$0", out.namespace, efn.ident, var);
+    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    if efn.throws {
+    let link_name = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let indirect_call = false;
+    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
+}
+
+fn write_rust_function_decl_impl(
+    out: &mut OutFile,
+    link_name: &str,
+    sig: &Signature,
+    types: &Types,
+    indirect_call: bool,
+) {
+    if sig.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type_space(out, &efn.ret, types);
+        write_extern_return_type_space(out, &sig.ret, types);
     }
-    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
+    write!(out, "{}(", link_name);
+    let mut needs_comma = false;
+    for arg in &sig.args {
+        if needs_comma {
             write!(out, ", ");
         }
         write_extern_arg(out, arg, types);
+        needs_comma = true;
     }
-    if indirect_return(efn, types) {
-        if !efn.args.is_empty() {
+    if indirect_return(sig, types) {
+        if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &efn.ret);
+        write_return_type(out, &sig.ret);
         write!(out, "*return$");
+        needs_comma = true;
+    }
+    if indirect_call {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write!(out, "void *");
     }
     writeln!(out, ") noexcept;");
 }
@@ -431,24 +481,44 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    write_return_type(out, &efn.ret);
-    write!(out, "{}(", efn.ident);
-    for (i, arg) in efn.args.iter().enumerate() {
+    let local_name = efn.ident.to_string();
+    let invoke = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let indirect_call = false;
+    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &str,
+    indirect_call: bool,
+) {
+    write_return_type(out, &sig.ret);
+    write!(out, "{}(", local_name);
+    for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
         write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
+    if indirect_call {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "void *extern$");
+    }
     write!(out, ")");
-    if !efn.throws {
+    if !sig.throws {
         write!(out, " noexcept");
     }
     if out.header {
         writeln!(out, ";");
     } else {
         writeln!(out, " {{");
-        for arg in &efn.args {
+        for arg in &sig.args {
             if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
                 out.include.utility = true;
                 write!(out, "  ::rust::ManuallyDrop<");
@@ -457,13 +527,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         write!(out, "  ");
-        let indirect_return = indirect_return(efn, types);
+        let indirect_return = indirect_return(sig, types);
         if indirect_return {
             write!(out, "::rust::MaybeUninit<");
-            write_type(out, efn.ret.as_ref().unwrap());
+            write_type(out, sig.ret.as_ref().unwrap());
             writeln!(out, "> return$;");
             write!(out, "  ");
-        } else if let Some(ret) = &efn.ret {
+        } else if let Some(ret) = &sig.ret {
             write!(out, "return ");
             match ret {
                 Type::RustBox(_) => {
@@ -478,11 +548,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 _ => {}
             }
         }
-        if efn.throws {
+        if sig.throws {
             write!(out, "::rust::Str::Repr error$ = ");
         }
-        write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
-        for (i, arg) in efn.args.iter().enumerate() {
+        write!(out, "{}(", invoke);
+        for (i, arg) in sig.args.iter().enumerate() {
             if i > 0 {
                 write!(out, ", ");
             }
@@ -501,19 +571,25 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         if indirect_return {
-            if !efn.args.is_empty() {
+            if !sig.args.is_empty() {
                 write!(out, ", ");
             }
             write!(out, "&return$.value");
         }
+        if indirect_call {
+            if !sig.args.is_empty() || indirect_return {
+                write!(out, ", ");
+            }
+            write!(out, "extern$");
+        }
         write!(out, ")");
-        if let Some(ret) = &efn.ret {
+        if let Some(ret) = &sig.ret {
             if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
                 write!(out, ")");
             }
         }
         writeln!(out, ";");
-        if efn.throws {
+        if sig.throws {
             writeln!(out, "  if (error$.ptr) {{");
             writeln!(out, "    throw ::rust::Error(error$);");
             writeln!(out, "  }}");
@@ -533,10 +609,10 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
     }
 }
 
-fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
-    efn.ret
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
         .as_ref()
-        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
 fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
@@ -640,7 +716,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::Fn(_) => unimplemented!(),
+        Type::Fn(f) => {
+            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
+            match &f.ret {
+                Some(ret) => write_type(out, ret),
+                None => write!(out, "void"),
+            }
+            write!(out, "(");
+            for (i, arg) in f.args.iter().enumerate() {
+                if i > 0 {
+                    write!(out, ", ");
+                }
+                write_type(out, &arg.ty);
+            }
+            write!(out, ")>");
+        }
         Type::Void(_) => unreachable!(),
     }
 }
@@ -652,9 +742,10 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
 
 fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
-        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
+        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::Fn(_) => {
+            write!(out, " ")
+        }
         Type::Ref(_) => {}
-        Type::Fn(_) => unimplemented!(),
         Type::Void(_) => unreachable!(),
     }
 }
diff --git a/include/cxx.h b/include/cxx.h
index 50f8f69..3dd52e5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -147,6 +147,23 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+#ifndef CXXBRIDGE02_RUST_FN
+#define CXXBRIDGE02_RUST_FN
+template <typename Signature, bool Throws = false> class Fn;
+
+template <typename Ret, typename... Args, bool Throws>
+class Fn<Ret(Args...), Throws> {
+public:
+  Ret operator()(Args... args) noexcept(!Throws);
+
+private:
+  Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
+  void *fn;
+};
+
+template <typename Signature> using TryFn = Fn<Signature, true>;
+#endif // CXXBRIDGE02_RUST_FN
+
 #ifndef CXXBRIDGE02_RUST_ERROR
 #define CXXBRIDGE02_RUST_ERROR
 class Error final : std::exception {
@@ -170,6 +187,9 @@ using string = String;
 using str = Str;
 template <class T> using box = Box<T>;
 using error = Error;
+template <typename Signature, bool Throws = false>
+using fn = Fn<Signature, Throws>;
+template <typename Signature> using try_fn = TryFn<Signature>;
 
 #ifndef CXXBRIDGE02_RUST_BITCOPY
 #define CXXBRIDGE02_RUST_BITCOPY
@@ -179,5 +199,10 @@ struct unsafe_bitcopy_t {
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE02_RUST_BITCOPY
 
+template <typename Ret, typename... Args, bool Throws>
+Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
+  return (*this->trampoline)(std::move(args)..., this->fn);
+}
+
 } // namespace cxxbridge02
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 69b7fb5..6afb548 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,9 +1,9 @@
 use crate::namespace::Namespace;
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{self, check, Api, ExternFn, ExternType, Struct, Type, Types};
+use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
-use syn::{Error, ItemMod, Result, Token};
+use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -128,6 +128,8 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ty = expand_extern_type(&arg.ty);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
+        } else if let Type::Fn(_) = arg.ty {
+            quote!(#ident: ::cxx::private::FatFunction)
         } else if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
@@ -186,6 +188,20 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             _ => quote!(#var),
         }
     });
+    let trampolines = efn
+        .args
+        .iter()
+        .filter_map(|arg| {
+            if let Type::Fn(f) = &arg.ty {
+                let var = &arg.ident;
+                Some(expand_function_pointer_trampoline(
+                    namespace, efn, var, f, types,
+                ))
+            } else {
+                None
+            }
+        })
+        .collect::<TokenStream>();
     let mut setup = efn
         .args
         .iter()
@@ -261,6 +277,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             extern "C" {
                 #decl
             }
+            #trampolines
             unsafe {
                 #setup
                 #expr
@@ -269,6 +286,41 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     }
 }
 
+fn expand_function_pointer_trampoline(
+    namespace: &Namespace,
+    efn: &ExternFn,
+    var: &Ident,
+    sig: &Signature,
+    types: &Types,
+) -> TokenStream {
+    let c_trampoline = format!("{}cxxbridge02${}${}$0", namespace, efn.ident, var);
+    let r_trampoline = format!("{}cxxbridge02${}${}$1", namespace, efn.ident, var);
+    let local_name = parse_quote!(__);
+    let catch_unwind_label = format!("::{}::{}", efn.ident, var);
+    let shim = expand_rust_function_shim_impl(
+        sig,
+        types,
+        &r_trampoline,
+        local_name,
+        catch_unwind_label,
+        None,
+    );
+
+    quote! {
+        let #var = ::cxx::private::FatFunction {
+            trampoline: {
+                extern "C" {
+                    #[link_name = #c_trampoline]
+                    fn trampoline();
+                }
+                #shim
+                trampoline as usize as *const ()
+            },
+            ptr: #var as usize as *const (),
+        };
+    }
+}
+
 fn expand_rust_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     quote! {
@@ -278,7 +330,29 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let args = efn.args.iter().map(|arg| {
+    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let local_name = format_ident!("__{}", ident);
+    let catch_unwind_label = format!("::{}", ident);
+    let invoke = Some(ident);
+    expand_rust_function_shim_impl(
+        efn,
+        types,
+        &link_name,
+        local_name,
+        catch_unwind_label,
+        invoke,
+    )
+}
+
+fn expand_rust_function_shim_impl(
+    sig: &Signature,
+    types: &Types,
+    link_name: &str,
+    local_name: Ident,
+    catch_unwind_label: String,
+    invoke: Option<&Ident>,
+) -> TokenStream {
+    let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
         if types.needs_indirect_abi(&arg.ty) {
@@ -287,7 +361,8 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             quote!(#ident: #ty)
         }
     });
-    let vars = efn.args.iter().map(|arg| {
+
+    let vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
             Type::Ident(i) if i == RustString => {
@@ -304,9 +379,14 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => quote!(#ident),
         }
     });
-    let mut outparam = None;
-    let call = quote!(super::#ident(#(#vars),*));
-    let mut expr = efn
+
+    let mut call = match invoke {
+        Some(ident) => quote!(super::#ident),
+        None => quote!(__extern),
+    };
+    call.extend(quote! { (#(#vars),*) });
+
+    let mut expr = sig
         .ret
         .as_ref()
         .and_then(|ret| match ret {
@@ -325,13 +405,15 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => None,
         })
         .unwrap_or(call);
-    let indirect_return = indirect_return(efn, types);
+
+    let mut outparam = None;
+    let indirect_return = indirect_return(sig, types);
     if indirect_return {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap());
-        outparam = Some(quote!(__return: *mut #ret));
+        let ret = expand_extern_type(sig.ret.as_ref().unwrap());
+        outparam = Some(quote!(__return: *mut #ret,));
     }
-    if efn.throws {
-        let out = match efn.ret {
+    if sig.throws {
+        let out = match sig.ret {
             Some(_) => quote!(__return),
             None => quote!(&mut ()),
         };
@@ -339,19 +421,24 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
+
     expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
-    let ret = if efn.throws {
+
+    let ret = if sig.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&efn.ret, types)
+        expand_extern_return_type(&sig.ret, types)
     };
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
-    let local_name = format_ident!("__{}", ident);
-    let catch_unwind_label = format!("::{}", ident);
+
+    let pointer = match invoke {
+        None => Some(quote!(__extern: #sig)),
+        Some(_) => None,
+    };
+
     quote! {
         #[doc(hidden)]
         #[export_name = #link_name]
-        unsafe extern "C" fn #local_name(#(#args,)* #outparam) #ret {
+        unsafe extern "C" fn #local_name(#(#args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
             #expr
         }
@@ -457,10 +544,10 @@ fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     }
 }
 
-fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
-    efn.ret
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
         .as_ref()
-        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
diff --git a/src/function.rs b/src/function.rs
new file mode 100644
index 0000000..1166b3d
--- /dev/null
+++ b/src/function.rs
@@ -0,0 +1,5 @@
+#[repr(C)]
+pub struct FatFunction {
+    pub trampoline: *const (),
+    pub ptr: *const (),
+}
diff --git a/src/lib.rs b/src/lib.rs
index 09326f5..3aaf172 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -356,6 +356,7 @@ mod assert;
 mod cxx_string;
 mod error;
 mod exception;
+mod function;
 mod gen;
 mod opaque;
 mod paths;
@@ -374,6 +375,7 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
     pub use crate::rust_str::RustStr;
diff --git a/syntax/check.rs b/syntax/check.rs
index b44d0cc..2826a85 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types};
+use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Struct, Ty1, Type, Types};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
@@ -136,10 +136,12 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(arg, msg);
         }
         if let Type::Fn(_) = arg.ty {
-            cx.error(
-                arg,
-                "passing a function pointer argument is not implemented yet",
-            );
+            if efn.lang == Lang::Rust {
+                cx.error(
+                    arg,
+                    "passing a function pointer from C++ to Rust is not implemented yet",
+                );
+            }
         }
     }
 
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 492fc91..7df0110 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -32,6 +32,7 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6384ac1..4aad3a2 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -92,6 +92,10 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
+  callback("2020");
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index e0e7624..6713614 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -35,6 +35,7 @@ void c_take_ref_c(const C &c);
 void c_take_str(rust::Str s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index 6a6fc3e..f8e9ca8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -78,6 +78,18 @@ fn test_c_take() {
 }
 
 #[test]
+fn test_c_callback() {
+    fn callback(s: String) -> usize {
+        if s == "2020" {
+            cxx_test_suite_set_correct();
+        }
+        0
+    }
+
+    check!(ffi::c_take_callback(callback));
+}
+
+#[test]
 fn test_c_call_r() {
     fn cxx_run_test() {
         extern "C" {

From 6c39077541e26e93ed13402839c71e844aae26d3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 05:19:15 +0000
Subject: [PATCH 209/2232] Merge pull request #85 from dtolnay/fn


Implement function pointer passing from Rust to C++
---

diff --git a/gen/write.rs b/gen/write.rs
index 1f7adda..b745739 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@ use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -109,6 +109,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_string = false;
     let mut needs_rust_str = false;
     let mut needs_rust_box = false;
+    let mut needs_rust_fn = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -120,6 +121,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 out.include.string = true;
                 needs_rust_str = true;
             }
+            Type::Fn(_) => {
+                needs_rust_fn = true;
+            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -175,6 +179,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     if needs_rust_string
         || needs_rust_str
         || needs_rust_box
+        || needs_rust_fn
         || needs_rust_error
         || needs_unsafe_bitcopy
         || needs_manually_drop
@@ -192,6 +197,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
@@ -402,27 +408,71 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "  return throw$;");
     }
     writeln!(out, "}}");
+    for arg in &efn.args {
+        if let Type::Fn(f) = &arg.ty {
+            let var = &arg.ident;
+            write_function_pointer_trampoline(out, efn, var, f, types);
+        }
+    }
+}
+
+fn write_function_pointer_trampoline(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    var: &Ident,
+    f: &Signature,
+    types: &Types,
+) {
+    out.next_section();
+    let r_trampoline = format!("{}cxxbridge02${}${}$1", out.namespace, efn.ident, var);
+    let indirect_call = true;
+    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
+
+    out.next_section();
+    let c_trampoline = format!("{}cxxbridge02${}${}$0", out.namespace, efn.ident, var);
+    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    if efn.throws {
+    let link_name = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let indirect_call = false;
+    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
+}
+
+fn write_rust_function_decl_impl(
+    out: &mut OutFile,
+    link_name: &str,
+    sig: &Signature,
+    types: &Types,
+    indirect_call: bool,
+) {
+    if sig.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type_space(out, &efn.ret, types);
+        write_extern_return_type_space(out, &sig.ret, types);
     }
-    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
+    write!(out, "{}(", link_name);
+    let mut needs_comma = false;
+    for arg in &sig.args {
+        if needs_comma {
             write!(out, ", ");
         }
         write_extern_arg(out, arg, types);
+        needs_comma = true;
     }
-    if indirect_return(efn, types) {
-        if !efn.args.is_empty() {
+    if indirect_return(sig, types) {
+        if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &efn.ret);
+        write_return_type(out, &sig.ret);
         write!(out, "*return$");
+        needs_comma = true;
+    }
+    if indirect_call {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write!(out, "void *");
     }
     writeln!(out, ") noexcept;");
 }
@@ -431,24 +481,44 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    write_return_type(out, &efn.ret);
-    write!(out, "{}(", efn.ident);
-    for (i, arg) in efn.args.iter().enumerate() {
+    let local_name = efn.ident.to_string();
+    let invoke = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let indirect_call = false;
+    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &str,
+    indirect_call: bool,
+) {
+    write_return_type(out, &sig.ret);
+    write!(out, "{}(", local_name);
+    for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
         write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
+    if indirect_call {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "void *extern$");
+    }
     write!(out, ")");
-    if !efn.throws {
+    if !sig.throws {
         write!(out, " noexcept");
     }
     if out.header {
         writeln!(out, ";");
     } else {
         writeln!(out, " {{");
-        for arg in &efn.args {
+        for arg in &sig.args {
             if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
                 out.include.utility = true;
                 write!(out, "  ::rust::ManuallyDrop<");
@@ -457,13 +527,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         write!(out, "  ");
-        let indirect_return = indirect_return(efn, types);
+        let indirect_return = indirect_return(sig, types);
         if indirect_return {
             write!(out, "::rust::MaybeUninit<");
-            write_type(out, efn.ret.as_ref().unwrap());
+            write_type(out, sig.ret.as_ref().unwrap());
             writeln!(out, "> return$;");
             write!(out, "  ");
-        } else if let Some(ret) = &efn.ret {
+        } else if let Some(ret) = &sig.ret {
             write!(out, "return ");
             match ret {
                 Type::RustBox(_) => {
@@ -478,11 +548,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 _ => {}
             }
         }
-        if efn.throws {
+        if sig.throws {
             write!(out, "::rust::Str::Repr error$ = ");
         }
-        write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
-        for (i, arg) in efn.args.iter().enumerate() {
+        write!(out, "{}(", invoke);
+        for (i, arg) in sig.args.iter().enumerate() {
             if i > 0 {
                 write!(out, ", ");
             }
@@ -501,19 +571,25 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
             }
         }
         if indirect_return {
-            if !efn.args.is_empty() {
+            if !sig.args.is_empty() {
                 write!(out, ", ");
             }
             write!(out, "&return$.value");
         }
+        if indirect_call {
+            if !sig.args.is_empty() || indirect_return {
+                write!(out, ", ");
+            }
+            write!(out, "extern$");
+        }
         write!(out, ")");
-        if let Some(ret) = &efn.ret {
+        if let Some(ret) = &sig.ret {
             if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
                 write!(out, ")");
             }
         }
         writeln!(out, ";");
-        if efn.throws {
+        if sig.throws {
             writeln!(out, "  if (error$.ptr) {{");
             writeln!(out, "    throw ::rust::Error(error$);");
             writeln!(out, "  }}");
@@ -533,10 +609,10 @@ fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
     }
 }
 
-fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
-    efn.ret
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
         .as_ref()
-        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
 fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
@@ -640,7 +716,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::Fn(_) => unimplemented!(),
+        Type::Fn(f) => {
+            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
+            match &f.ret {
+                Some(ret) => write_type(out, ret),
+                None => write!(out, "void"),
+            }
+            write!(out, "(");
+            for (i, arg) in f.args.iter().enumerate() {
+                if i > 0 {
+                    write!(out, ", ");
+                }
+                write_type(out, &arg.ty);
+            }
+            write!(out, ")>");
+        }
         Type::Void(_) => unreachable!(),
     }
 }
@@ -652,9 +742,10 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
 
 fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
-        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) => write!(out, " "),
+        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::Fn(_) => {
+            write!(out, " ")
+        }
         Type::Ref(_) => {}
-        Type::Fn(_) => unimplemented!(),
         Type::Void(_) => unreachable!(),
     }
 }
diff --git a/include/cxx.h b/include/cxx.h
index 50f8f69..3dd52e5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -147,6 +147,23 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+#ifndef CXXBRIDGE02_RUST_FN
+#define CXXBRIDGE02_RUST_FN
+template <typename Signature, bool Throws = false> class Fn;
+
+template <typename Ret, typename... Args, bool Throws>
+class Fn<Ret(Args...), Throws> {
+public:
+  Ret operator()(Args... args) noexcept(!Throws);
+
+private:
+  Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
+  void *fn;
+};
+
+template <typename Signature> using TryFn = Fn<Signature, true>;
+#endif // CXXBRIDGE02_RUST_FN
+
 #ifndef CXXBRIDGE02_RUST_ERROR
 #define CXXBRIDGE02_RUST_ERROR
 class Error final : std::exception {
@@ -170,6 +187,9 @@ using string = String;
 using str = Str;
 template <class T> using box = Box<T>;
 using error = Error;
+template <typename Signature, bool Throws = false>
+using fn = Fn<Signature, Throws>;
+template <typename Signature> using try_fn = TryFn<Signature>;
 
 #ifndef CXXBRIDGE02_RUST_BITCOPY
 #define CXXBRIDGE02_RUST_BITCOPY
@@ -179,5 +199,10 @@ struct unsafe_bitcopy_t {
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE02_RUST_BITCOPY
 
+template <typename Ret, typename... Args, bool Throws>
+Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
+  return (*this->trampoline)(std::move(args)..., this->fn);
+}
+
 } // namespace cxxbridge02
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 69b7fb5..6afb548 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,9 +1,9 @@
 use crate::namespace::Namespace;
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{self, check, Api, ExternFn, ExternType, Struct, Type, Types};
+use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
-use syn::{Error, ItemMod, Result, Token};
+use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -128,6 +128,8 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ty = expand_extern_type(&arg.ty);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
+        } else if let Type::Fn(_) = arg.ty {
+            quote!(#ident: ::cxx::private::FatFunction)
         } else if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
@@ -186,6 +188,20 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             _ => quote!(#var),
         }
     });
+    let trampolines = efn
+        .args
+        .iter()
+        .filter_map(|arg| {
+            if let Type::Fn(f) = &arg.ty {
+                let var = &arg.ident;
+                Some(expand_function_pointer_trampoline(
+                    namespace, efn, var, f, types,
+                ))
+            } else {
+                None
+            }
+        })
+        .collect::<TokenStream>();
     let mut setup = efn
         .args
         .iter()
@@ -261,6 +277,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             extern "C" {
                 #decl
             }
+            #trampolines
             unsafe {
                 #setup
                 #expr
@@ -269,6 +286,41 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     }
 }
 
+fn expand_function_pointer_trampoline(
+    namespace: &Namespace,
+    efn: &ExternFn,
+    var: &Ident,
+    sig: &Signature,
+    types: &Types,
+) -> TokenStream {
+    let c_trampoline = format!("{}cxxbridge02${}${}$0", namespace, efn.ident, var);
+    let r_trampoline = format!("{}cxxbridge02${}${}$1", namespace, efn.ident, var);
+    let local_name = parse_quote!(__);
+    let catch_unwind_label = format!("::{}::{}", efn.ident, var);
+    let shim = expand_rust_function_shim_impl(
+        sig,
+        types,
+        &r_trampoline,
+        local_name,
+        catch_unwind_label,
+        None,
+    );
+
+    quote! {
+        let #var = ::cxx::private::FatFunction {
+            trampoline: {
+                extern "C" {
+                    #[link_name = #c_trampoline]
+                    fn trampoline();
+                }
+                #shim
+                trampoline as usize as *const ()
+            },
+            ptr: #var as usize as *const (),
+        };
+    }
+}
+
 fn expand_rust_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     quote! {
@@ -278,7 +330,29 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let args = efn.args.iter().map(|arg| {
+    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let local_name = format_ident!("__{}", ident);
+    let catch_unwind_label = format!("::{}", ident);
+    let invoke = Some(ident);
+    expand_rust_function_shim_impl(
+        efn,
+        types,
+        &link_name,
+        local_name,
+        catch_unwind_label,
+        invoke,
+    )
+}
+
+fn expand_rust_function_shim_impl(
+    sig: &Signature,
+    types: &Types,
+    link_name: &str,
+    local_name: Ident,
+    catch_unwind_label: String,
+    invoke: Option<&Ident>,
+) -> TokenStream {
+    let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
         if types.needs_indirect_abi(&arg.ty) {
@@ -287,7 +361,8 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             quote!(#ident: #ty)
         }
     });
-    let vars = efn.args.iter().map(|arg| {
+
+    let vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
             Type::Ident(i) if i == RustString => {
@@ -304,9 +379,14 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => quote!(#ident),
         }
     });
-    let mut outparam = None;
-    let call = quote!(super::#ident(#(#vars),*));
-    let mut expr = efn
+
+    let mut call = match invoke {
+        Some(ident) => quote!(super::#ident),
+        None => quote!(__extern),
+    };
+    call.extend(quote! { (#(#vars),*) });
+
+    let mut expr = sig
         .ret
         .as_ref()
         .and_then(|ret| match ret {
@@ -325,13 +405,15 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
             _ => None,
         })
         .unwrap_or(call);
-    let indirect_return = indirect_return(efn, types);
+
+    let mut outparam = None;
+    let indirect_return = indirect_return(sig, types);
     if indirect_return {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap());
-        outparam = Some(quote!(__return: *mut #ret));
+        let ret = expand_extern_type(sig.ret.as_ref().unwrap());
+        outparam = Some(quote!(__return: *mut #ret,));
     }
-    if efn.throws {
-        let out = match efn.ret {
+    if sig.throws {
+        let out = match sig.ret {
             Some(_) => quote!(__return),
             None => quote!(&mut ()),
         };
@@ -339,19 +421,24 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
     } else if indirect_return {
         expr = quote!(::std::ptr::write(__return, #expr));
     }
+
     expr = quote!(::cxx::private::catch_unwind(__fn, move || #expr));
-    let ret = if efn.throws {
+
+    let ret = if sig.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&efn.ret, types)
+        expand_extern_return_type(&sig.ret, types)
     };
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
-    let local_name = format_ident!("__{}", ident);
-    let catch_unwind_label = format!("::{}", ident);
+
+    let pointer = match invoke {
+        None => Some(quote!(__extern: #sig)),
+        Some(_) => None,
+    };
+
     quote! {
         #[doc(hidden)]
         #[export_name = #link_name]
-        unsafe extern "C" fn #local_name(#(#args,)* #outparam) #ret {
+        unsafe extern "C" fn #local_name(#(#args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
             #expr
         }
@@ -457,10 +544,10 @@ fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     }
 }
 
-fn indirect_return(efn: &ExternFn, types: &Types) -> bool {
-    efn.ret
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
         .as_ref()
-        .map_or(false, |ret| efn.throws || types.needs_indirect_abi(ret))
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
diff --git a/src/function.rs b/src/function.rs
new file mode 100644
index 0000000..1166b3d
--- /dev/null
+++ b/src/function.rs
@@ -0,0 +1,5 @@
+#[repr(C)]
+pub struct FatFunction {
+    pub trampoline: *const (),
+    pub ptr: *const (),
+}
diff --git a/src/lib.rs b/src/lib.rs
index 09326f5..3aaf172 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -356,6 +356,7 @@ mod assert;
 mod cxx_string;
 mod error;
 mod exception;
+mod function;
 mod gen;
 mod opaque;
 mod paths;
@@ -374,6 +375,7 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
     pub use crate::rust_str::RustStr;
diff --git a/syntax/check.rs b/syntax/check.rs
index b44d0cc..2826a85 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Ref, Struct, Ty1, Type, Types};
+use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Struct, Ty1, Type, Types};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
@@ -136,10 +136,12 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(arg, msg);
         }
         if let Type::Fn(_) = arg.ty {
-            cx.error(
-                arg,
-                "passing a function pointer argument is not implemented yet",
-            );
+            if efn.lang == Lang::Rust {
+                cx.error(
+                    arg,
+                    "passing a function pointer from C++ to Rust is not implemented yet",
+                );
+            }
         }
     }
 
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 492fc91..7df0110 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -32,6 +32,7 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6384ac1..4aad3a2 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -92,6 +92,10 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
+  callback("2020");
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index e0e7624..6713614 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -35,6 +35,7 @@ void c_take_ref_c(const C &c);
 void c_take_str(rust::Str s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index 6a6fc3e..f8e9ca8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -78,6 +78,18 @@ fn test_c_take() {
 }
 
 #[test]
+fn test_c_callback() {
+    fn callback(s: String) -> usize {
+        if s == "2020" {
+            cxx_test_suite_set_correct();
+        }
+        0
+    }
+
+    check!(ffi::c_take_callback(callback));
+}
+
+#[test]
 fn test_c_call_r() {
     fn cxx_run_test() {
         extern "C" {

From addc748bbcfc4d3837994db9f3ffb53e25bc270b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 05:19:48 +0000
Subject: [PATCH 210/2232] Add function pointers to builtin types table


---

diff --git a/README.md b/README.md
index 4308291..fee7299 100644
--- a/README.md
+++ b/README.md
@@ -302,6 +302,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
 
diff --git a/src/lib.rs b/src/lib.rs
index 3aaf172..8a80553 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -306,6 +306,7 @@
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
 //!

From 864ab8c6e277412574e5f4e6e1c13a60b1e69359 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 30 2020 05:25:40 +0000
Subject: [PATCH 211/2232] Add github repo link to documentation


---

diff --git a/src/lib.rs b/src/lib.rs
index 8a80553..dfd3414 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,7 @@
+//! **[https://github.com/dtolnay/cxx]**
+//!
+//! <br>
+//!
 //! This library provides a **safe** mechanism for calling C++ code from Rust
 //! and Rust code from C++, not subject to the many ways that things can go
 //! wrong when using bindgen or cbindgen to generate unsafe C-style bindings.

From 7261732ba9c7e41e5e8758eb5e34d672bf3d5e7a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 31 2020 02:45:41 +0000
Subject: [PATCH 212/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 14f2542..44c3a6a 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -2,7 +2,7 @@
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.27/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.28/src/**"]),
     visibility = ["PUBLIC"],
     features = ["std"],
 )
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.2/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
@@ -59,7 +59,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.11/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.12/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -71,7 +71,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.11/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.12/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.9/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.16/src/**"]),
+    srcs = glob(["vendor/syn-1.0.17/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
@@ -171,14 +171,14 @@ rust_library(
 
 rust_library(
     name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    srcs = glob(["vendor/thiserror-1.0.14/src/**"]),
     visibility = ["PUBLIC"],
     deps = [":thiserror-impl"],
 )
 
 rust_library(
     name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    srcs = glob(["vendor/thiserror-impl-1.0.14/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
diff --git a/third-party/BUILD b/third-party/BUILD
index daf9ea1..646289c 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -7,7 +7,7 @@ load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.27/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.28/src/**"]),
     crate_features = ["std"],
     visibility = ["//visibility:public"],
 )
@@ -36,7 +36,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.2/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.11/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-0.4.12/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.11/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-0.4.12/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.9/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.16/src/**"]),
+    srcs = glob(["vendor/syn-1.0.17/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
@@ -176,14 +176,14 @@ rust_library(
 
 rust_library(
     name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.11/src/**"]),
+    srcs = glob(["vendor/thiserror-1.0.14/src/**"]),
     visibility = ["//visibility:public"],
     deps = [":thiserror-impl"],
 )
 
 rust_library(
     name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.11/src/**"]),
+    srcs = glob(["vendor/thiserror-impl-1.0.14/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index e76c831..5c821c5 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -11,9 +11,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.27"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785"
+checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
 
 [[package]]
 name = "atty"
@@ -55,9 +55,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7606d610349258b637bb639f7565bb7ee5fd6114130d2af59d0f39154e92426a"
+checksum = "4efca5ddfdf45cee2eedd9dadbe7a5fa90a5536af6f580f1814267b2a4d6107f"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -135,9 +135,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
+checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
 dependencies = [
  "libc",
 ]
@@ -171,9 +171,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a"
+checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -184,9 +184,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a"
+checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -197,9 +197,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
+checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
 dependencies = [
  "unicode-xid",
 ]
@@ -252,9 +252,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.48"
+version = "1.0.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25"
+checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867"
 dependencies = [
  "itoa",
  "ryu",
@@ -293,9 +293,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.16"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
+checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -333,18 +333,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.11"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db"
+checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.11"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4"
+checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -422,9 +422,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
+checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
 dependencies = [
  "winapi",
 ]

From d4402cae9beeaafe3b45e2885fd97d2f99e58d3c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 31 2020 02:47:58 +0000
Subject: [PATCH 213/2232] Release 0.2.1


---

diff --git a/Cargo.toml b/Cargo.toml
index 63a3a94..2cc6fff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.0" # remember to update html_root_url
+version = "0.2.1" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.0", path = "macro" }
+cxxbridge-macro = { version = "=0.2.1", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index aef31f6..d100adc 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.0"
+version = "0.2.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 635d7cc..9456cda 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.0"
+version = "0.2.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index dfd3414..28f113a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.1.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.1")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::declare_interior_mutable_const,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5c821c5..59dbbb7 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.0"
+version = "0.2.1"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.0"
+version = "0.2.1"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.0"
+version = "0.2.1"
 dependencies = [
  "cxx",
  "proc-macro2",

From e0bad9300c49f5bb631e256135feac326c9f8517 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 02 2020 21:16:29 +0000
Subject: [PATCH 214/2232] Remove finished item from todo list


---

diff --git a/README.md b/README.md
index fee7299..b5c57fd 100644
--- a/README.md
+++ b/README.md
@@ -337,7 +337,6 @@ the facets that I still intend for this project to tackle:
 
 - [ ] Support associated methods: `extern "Rust" { fn f(self: &Struct); }`
 - [ ] Support C++ member functions
-- [ ] Support passing function pointers across the FFI
 - [ ] Support structs with type parameters
 - [ ] Support async functions
 

From 737e02eeb197c256c8dc8062fbec2f2a19c2f035 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 05 2020 04:52:46 +0000
Subject: [PATCH 215/2232] Remove unneeded return from void functions


---

diff --git a/gen/write.rs b/gen/write.rs
index b745739..3d1fdf3 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -821,12 +821,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$box${}$uninit(this);", instance);
+    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$box${}$drop(this);", instance);
+    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 

From e3a481508acf69504b046cb4f9eee1543ddeb0e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:01:16 +0000
Subject: [PATCH 216/2232] Store finer grained tokens of Signature


This is required in order for function pointers like `fn(&CxxString)` to
work, which requires the cxx bridge to emit `fn(&::cxx::CxxString)`
rather than a straight copy of the input tokens.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6afb548..1bb3628 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -273,7 +273,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     .unwrap_or(call);
     quote! {
         #doc
-        pub fn #ident(#(#args),*) #ret {
+        pub fn #ident(#args) #ret {
             extern "C" {
                 #decl
             }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 27aa43a..34fb851 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -116,7 +116,8 @@ impl PartialEq for Signature {
             args,
             ret,
             throws,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = self;
         let Signature {
             fn_token: _,
@@ -124,9 +125,14 @@ impl PartialEq for Signature {
             args: args2,
             ret: ret2,
             throws: throws2,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = other;
-        receiver == receiver2 && args == args2 && ret == ret2 && throws == throws2
+        receiver == receiver2
+            && ret == ret2
+            && throws == throws2
+            && args.len() == args2.len()
+            && args.iter().zip(args2).all(|(arg, arg2)| arg == arg2)
     }
 }
 
@@ -138,10 +144,13 @@ impl Hash for Signature {
             args,
             ret,
             throws,
-            tokens: _,
+            paren_token: _,
+            throws_tokens: _,
         } = self;
         receiver.hash(state);
-        args.hash(state);
+        for arg in args {
+            arg.hash(state);
+        }
         ret.hash(state);
         throws.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 38e21b0..0d0328b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -12,8 +12,11 @@ pub mod set;
 mod tokens;
 pub mod types;
 
-use proc_macro2::{Ident, Span, TokenStream};
-use syn::{token::Brace, LitStr, Token};
+use self::parse::kw;
+use proc_macro2::{Ident, Span};
+use syn::punctuated::Punctuated;
+use syn::token::{Brace, Paren};
+use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -55,10 +58,11 @@ pub struct ExternFn {
 pub struct Signature {
     pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
-    pub args: Vec<Var>,
+    pub args: Punctuated<Var, Token![,]>,
     pub ret: Option<Type>,
     pub throws: bool,
-    pub tokens: TokenStream,
+    pub paren_token: Paren,
+    pub throws_tokens: Option<(kw::Result, Token![<], Token![>])>,
 }
 
 #[derive(Eq, PartialEq, Hash)]
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a00f8dd..8e674bd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,12 +4,17 @@ use crate::syntax::{
 };
 use proc_macro2::Ident;
 use quote::{format_ident, quote};
+use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Type as RustType,
+    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
     TypeBareFn, TypePath, TypeReference,
 };
 
+pub mod kw {
+    syn::custom_keyword!(Result);
+}
+
 pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
     let mut apis = Vec::new();
     for item in items {
@@ -151,8 +156,9 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     }
 
     let mut receiver = None;
-    let mut args = Vec::new();
-    for arg in &foreign_fn.sig.inputs {
+    let mut args = Punctuated::new();
+    for arg in foreign_fn.sig.inputs.pairs() {
+        let (arg, comma) = arg.into_tuple();
         match arg {
             FnArg::Receiver(receiver) => {
                 return Err(Error::new_spanned(receiver, "unsupported signature"))
@@ -164,7 +170,10 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
                 };
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
-                    args.push(Var { ident, ty });
+                    args.push_value(Var { ident, ty });
+                    if let Some(comma) = comma {
+                        args.push_punct(*comma);
+                    }
                     continue;
                 }
                 if let Type::Ref(reference) = ty {
@@ -181,14 +190,13 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
         }
     }
 
-    let mut throws = false;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws)?;
+    let mut throws_tokens = None;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
+    let throws = throws_tokens.is_some();
     let doc = attrs::parse_doc(&foreign_fn.attrs)?;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
-    let mut foreign_fn2 = foreign_fn.clone();
-    foreign_fn2.attrs.clear();
-    let tokens = quote!(#foreign_fn2);
+    let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
 
     Ok(ExternFn {
@@ -201,7 +209,8 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
             args,
             ret,
             throws,
-            tokens,
+            paren_token,
+            throws_tokens,
         },
         semi_token,
     })
@@ -298,20 +307,24 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             Ok(Var { ident, ty })
         })
         .collect::<Result<_>>()?;
-    let mut throws = false;
-    let ret = parse_return_type(&ty.output, &mut throws)?;
-    let tokens = quote!(#ty);
+    let mut throws_tokens = None;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
+    let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         fn_token: ty.fn_token,
         receiver: None,
         args,
         ret,
         throws,
-        tokens,
+        paren_token: ty.paren_token,
+        throws_tokens,
     })))
 }
 
-fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>> {
+fn parse_return_type(
+    ty: &ReturnType,
+    throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
+) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
         ReturnType::Type(_, ret) => ret.as_ref(),
@@ -325,7 +338,8 @@ fn parse_return_type(ty: &ReturnType, throws: &mut bool) -> Result<Option<Type>>
                 if ident == "Result" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         ret = arg;
-                        *throws = true;
+                        *throws_tokens =
+                            Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
                     }
                 }
             }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 59bb0de..51592dd 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -63,12 +63,28 @@ impl ToTokens for Derive {
 
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.sig.tokens.to_tokens(tokens);
+        // Notional token range for error reporting purposes.
+        self.sig.fn_token.to_tokens(tokens);
+        self.semi_token.to_tokens(tokens);
     }
 }
 
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.tokens.to_tokens(tokens);
+        self.fn_token.to_tokens(tokens);
+        self.paren_token.surround(tokens, |tokens| {
+            self.args.to_tokens(tokens);
+        });
+        if let Some(ret) = &self.ret {
+            Token![->](self.paren_token.span).to_tokens(tokens);
+            if let Some((result, langle, rangle)) = self.throws_tokens {
+                result.to_tokens(tokens);
+                langle.to_tokens(tokens);
+                ret.to_tokens(tokens);
+                rangle.to_tokens(tokens);
+            } else {
+                ret.to_tokens(tokens);
+            }
+        }
     }
 }

From a23129c06994718dc70e7b1a81db56cb1a7e0c60 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:08:28 +0000
Subject: [PATCH 217/2232] Allow calling fn pointers with explicit indirect call syntax


---

diff --git a/include/cxx.h b/include/cxx.h
index 3dd52e5..8bdbc90 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -155,6 +155,7 @@ template <typename Ret, typename... Args, bool Throws>
 class Fn<Ret(Args...), Throws> {
 public:
   Ret operator()(Args... args) noexcept(!Throws);
+  Fn operator*() noexcept;
 
 private:
   Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
@@ -204,5 +205,10 @@ Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
 }
 
+template <typename Ret, typename... Args, bool Throws>
+Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() noexcept {
+  return *this;
+}
+
 } // namespace cxxbridge02
 } // namespace rust

From c7673444ed5db49539a42897f18c2e61aab0388e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:18:55 +0000
Subject: [PATCH 218/2232] Merge pull request #89 from dtolnay/fncall


Allow calling fn pointers with explicit indirect call syntax
---

diff --git a/include/cxx.h b/include/cxx.h
index 3dd52e5..8bdbc90 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -155,6 +155,7 @@ template <typename Ret, typename... Args, bool Throws>
 class Fn<Ret(Args...), Throws> {
 public:
   Ret operator()(Args... args) noexcept(!Throws);
+  Fn operator*() noexcept;
 
 private:
   Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
@@ -204,5 +205,10 @@ Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
 }
 
+template <typename Ret, typename... Args, bool Throws>
+Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() noexcept {
+  return *this;
+}
+
 } // namespace cxxbridge02
 } // namespace rust

From 23d8953ff3f94ae71b356a37d26472450f163430 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:21:25 +0000
Subject: [PATCH 219/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 59dbbb7..79cbae2 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -171,9 +171,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "0.4.12"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
+checksum = "8931031034aa65c73f3f1a05c3ec0fa51287fcd06557ecf4e88b2768bdca375e"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -184,9 +184,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "0.4.12"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
+checksum = "2147536f412ee7ae5529364ed50172ca0220fd64591e236296f45f36b38b2f98"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -232,18 +232,18 @@ checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
 
 [[package]]
 name = "serde"
-version = "1.0.105"
+version = "1.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff"
+checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.105"
+version = "1.0.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8"
+checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -252,9 +252,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.50"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867"
+checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9"
 dependencies = [
  "itoa",
  "ryu",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.12"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d"
+checksum = "ff6da2e8d107dfd7b74df5ef4d205c6aebee0706c647f6bc6a2d5789905c00fb"
 dependencies = [
  "clap",
  "lazy_static",
@@ -280,9 +280,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430"
+checksum = "a489c87c08fbaf12e386665109dd13470dcc9c4583ea3e10dd2b4523e5ebd9ac"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -362,9 +362,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.24"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24b4e093c5ed1a60b22557090120aa14f90ca801549c0949d775ea07c1407720"
+checksum = "459186ab1afd6d93bd23c2269125f4f7694f8771fe0e64434b4bdc212b94034d"
 dependencies = [
  "glob",
  "lazy_static",

From 93c51a6c05b0e06f4e5ab53c8ec0070fc3eca64e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:21:25 +0000
Subject: [PATCH 220/2232] Release 0.2.2


---

diff --git a/Cargo.toml b/Cargo.toml
index 2cc6fff..1d3ec29 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.1" # remember to update html_root_url
+version = "0.2.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.1", path = "macro" }
+cxxbridge-macro = { version = "=0.2.2", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index d100adc..ac90392 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.1"
+version = "0.2.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9456cda..5cf50a0 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.1"
+version = "0.2.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 28f113a..27d67ca 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.1")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.2")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::declare_interior_mutable_const,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 79cbae2..4c83627 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.1"
+version = "0.2.2"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.1"
+version = "0.2.2"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.1"
+version = "0.2.2"
 dependencies = [
  "cxx",
  "proc-macro2",

From 4ac0b189b3addc4508e31322c08bc8a26ae1c379 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:35:00 +0000
Subject: [PATCH 221/2232] Fix third-party targets files


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 44c3a6a..483224b 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -59,7 +59,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.12/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.1/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -71,7 +71,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.12/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.1/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
@@ -107,7 +107,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.12/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.13/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":clap",
@@ -118,7 +118,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.5/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.6/src/**"]),
     proc_macro = True,
     deps = [
         ":heck",
diff --git a/third-party/BUILD b/third-party/BUILD
index 646289c..093d509 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-0.4.12/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.1/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-0.4.12/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.1/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
@@ -112,7 +112,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.12/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.13/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
@@ -123,7 +123,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.5/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.6/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",

From 533d458b43402c2b23c5adb9e13c20d0038c05c0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:36:13 +0000
Subject: [PATCH 222/2232] Fill in missing const on Fn member functions


---

diff --git a/include/cxx.h b/include/cxx.h
index 8bdbc90..5de479c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -154,8 +154,8 @@ template <typename Signature, bool Throws = false> class Fn;
 template <typename Ret, typename... Args, bool Throws>
 class Fn<Ret(Args...), Throws> {
 public:
-  Ret operator()(Args... args) noexcept(!Throws);
-  Fn operator*() noexcept;
+  Ret operator()(Args... args) const noexcept(!Throws);
+  Fn operator*() const noexcept;
 
 private:
   Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
@@ -201,12 +201,12 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE02_RUST_BITCOPY
 
 template <typename Ret, typename... Args, bool Throws>
-Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
+Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
 }
 
 template <typename Ret, typename... Args, bool Throws>
-Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() noexcept {
+Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 

From afb6f1387ae755d34ab2b84f64d614b4ff05ed22 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:50:17 +0000
Subject: [PATCH 223/2232] Merge pull request #90 from dtolnay/const


Fill in missing const on Fn member functions
---

diff --git a/include/cxx.h b/include/cxx.h
index 8bdbc90..5de479c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -154,8 +154,8 @@ template <typename Signature, bool Throws = false> class Fn;
 template <typename Ret, typename... Args, bool Throws>
 class Fn<Ret(Args...), Throws> {
 public:
-  Ret operator()(Args... args) noexcept(!Throws);
-  Fn operator*() noexcept;
+  Ret operator()(Args... args) const noexcept(!Throws);
+  Fn operator*() const noexcept;
 
 private:
   Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
@@ -201,12 +201,12 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE02_RUST_BITCOPY
 
 template <typename Ret, typename... Args, bool Throws>
-Ret Fn<Ret(Args...), Throws>::operator()(Args... args) noexcept(!Throws) {
+Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
 }
 
 template <typename Ret, typename... Args, bool Throws>
-Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() noexcept {
+Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 

From 86949cfdc6ec154c71dc64546f6ce4568c5e5247 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 03:51:19 +0000
Subject: [PATCH 224/2232] Release 0.2.3


---

diff --git a/Cargo.toml b/Cargo.toml
index 1d3ec29..f127d5e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.2" # remember to update html_root_url
+version = "0.2.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.2", path = "macro" }
+cxxbridge-macro = { version = "=0.2.3", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index ac90392..b44221d 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.2"
+version = "0.2.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 5cf50a0..4cc82d0 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.2"
+version = "0.2.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 27d67ca..f0f1449 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.3")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::declare_interior_mutable_const,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4c83627..b453309 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.2"
+version = "0.2.3"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.2"
+version = "0.2.3"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.2"
+version = "0.2.3"
 dependencies = [
  "cxx",
  "proc-macro2",

From 4ad8020fc4eec61e4cfb2b6efb75333ba1dbdf17 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 04:16:46 +0000
Subject: [PATCH 225/2232] Accept non-UnwindSafe extern Rust types in extern Rust signatures


---

diff --git a/src/unwind.rs b/src/unwind.rs
index 070aa28..abb7b92 100644
--- a/src/unwind.rs
+++ b/src/unwind.rs
@@ -1,12 +1,16 @@
 use std::io::{self, Write};
-use std::panic::{self, UnwindSafe};
+use std::panic::{self, AssertUnwindSafe};
 use std::process;
 
 pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
 where
-    F: FnOnce() -> R + UnwindSafe,
+    F: FnOnce() -> R,
 {
-    match panic::catch_unwind(foreign_call) {
+    // Regarding the AssertUnwindSafe: we immediately abort on panic so it
+    // doesn't matter whether the types involved are unwind-safe. The UnwindSafe
+    // bound on catch_unwind is about ensuring nothing is in a broken state if
+    // your program plans to continue after the panic.
+    match panic::catch_unwind(AssertUnwindSafe(foreign_call)) {
         Ok(ret) => ret,
         Err(_) => abort(label),
     }

From 48999f99370edcf2db2e8717b9af966f6cb3683a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 04:28:21 +0000
Subject: [PATCH 226/2232] Merge pull request #91 from dtolnay/unwindsafe


Accept non-UnwindSafe extern Rust types in extern Rust signatures
---

diff --git a/src/unwind.rs b/src/unwind.rs
index 070aa28..abb7b92 100644
--- a/src/unwind.rs
+++ b/src/unwind.rs
@@ -1,12 +1,16 @@
 use std::io::{self, Write};
-use std::panic::{self, UnwindSafe};
+use std::panic::{self, AssertUnwindSafe};
 use std::process;
 
 pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
 where
-    F: FnOnce() -> R + UnwindSafe,
+    F: FnOnce() -> R,
 {
-    match panic::catch_unwind(foreign_call) {
+    // Regarding the AssertUnwindSafe: we immediately abort on panic so it
+    // doesn't matter whether the types involved are unwind-safe. The UnwindSafe
+    // bound on catch_unwind is about ensuring nothing is in a broken state if
+    // your program plans to continue after the panic.
+    match panic::catch_unwind(AssertUnwindSafe(foreign_call)) {
         Ok(ret) => ret,
         Err(_) => abort(label),
     }

From 57a1eaa5f1ba580936a1b85fc11220def0f461dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 04:28:35 +0000
Subject: [PATCH 227/2232] Move panic abort message to stderr


---

diff --git a/src/unwind.rs b/src/unwind.rs
index abb7b92..36f6ae3 100644
--- a/src/unwind.rs
+++ b/src/unwind.rs
@@ -18,7 +18,7 @@ where
 
 #[cold]
 fn abort(label: &'static str) -> ! {
-    let mut stdout = io::stdout();
-    let _ = writeln!(stdout, "Error: panic in ffi function {}, aborting.", label);
+    let mut stderr = io::stderr();
+    let _ = writeln!(stderr, "Error: panic in ffi function {}, aborting.", label);
     process::abort();
 }

From b1637adafc50819f3030bc7163f055b5bd17f8f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 09 2020 04:29:14 +0000
Subject: [PATCH 228/2232] Release 0.2.4


---

diff --git a/Cargo.toml b/Cargo.toml
index f127d5e..73c7e57 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.3" # remember to update html_root_url
+version = "0.2.4" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.3", path = "macro" }
+cxxbridge-macro = { version = "=0.2.4", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index b44221d..ea936b3 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.3"
+version = "0.2.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 4cc82d0..4fd507e 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.3"
+version = "0.2.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index f0f1449..86e9541 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.3")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.4")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::declare_interior_mutable_const,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b453309..8c8c6ef 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.3"
+version = "0.2.4"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.3"
+version = "0.2.4"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.3"
+version = "0.2.4"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5383891622e3a128f222b5f165a9cd8b1d3ef5e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 03:56:44 +0000
Subject: [PATCH 229/2232] Do not emit UniquePtr::new for opaque C types


---

diff --git a/gen/write.rs b/gen/write.rs
index 3d1fdf3..217a591 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -766,7 +766,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, inner);
+                    write_unique_ptr(out, inner, types);
                 }
             }
         }
@@ -830,7 +830,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     out.include.utility = true;
 
     let mut inner = String::new();
@@ -860,17 +860,19 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
-        instance, inner, inner,
-    );
-    writeln!(
-        out,
-        "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-        inner, inner,
-    );
-    writeln!(out, "}}");
+    if types.structs.contains_key(ident) {
+        writeln!(
+            out,
+            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
     writeln!(
         out,
         "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bb3628..e9a4495 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -57,7 +57,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, ident));
+                    expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         }
@@ -474,7 +474,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
+fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
     let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
@@ -483,6 +483,22 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let new_method = if types.structs.contains_key(ident) {
+        Some(quote! {
+            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_new]
+                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+                }
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                unsafe { __new(&mut repr, &mut value) }
+                repr
+            }
+        })
+    } else {
+        None
+    };
+
     quote! {
         unsafe impl ::cxx::private::UniquePtrTarget for #ident {
             fn __null() -> *mut ::std::ffi::c_void {
@@ -494,15 +510,7 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
                 unsafe { __null(&mut repr) }
                 repr
             }
-            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
-                extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
-                }
-                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __new(&mut repr, &mut value) }
-                repr
-            }
+            #new_method
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 94b6e25..4a1392a 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -118,7 +118,15 @@ pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
-    fn __new(value: Self) -> *mut c_void;
+    fn __new(value: Self) -> *mut c_void
+    where
+        Self: Sized,
+    {
+        // Opaque C types do not get this method because they can never exist by
+        // value on the Rust side of the bridge.
+        let _ = value;
+        unreachable!()
+    }
     #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void;
     #[doc(hidden)]

From eb0ac1a583dc87aff4b2393428593a9357ed38d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 04:06:36 +0000
Subject: [PATCH 230/2232] Merge pull request #94 from dtolnay/uniquenew


Do not emit UniquePtr::new for opaque C types
---

diff --git a/gen/write.rs b/gen/write.rs
index 3d1fdf3..217a591 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -766,7 +766,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, inner);
+                    write_unique_ptr(out, inner, types);
                 }
             }
         }
@@ -830,7 +830,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     out.include.utility = true;
 
     let mut inner = String::new();
@@ -860,17 +860,19 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
-        instance, inner, inner,
-    );
-    writeln!(
-        out,
-        "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-        inner, inner,
-    );
-    writeln!(out, "}}");
+    if types.structs.contains_key(ident) {
+        writeln!(
+            out,
+            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
     writeln!(
         out,
         "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bb3628..e9a4495 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -57,7 +57,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, ident));
+                    expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         }
@@ -474,7 +474,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
+fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
     let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
@@ -483,6 +483,22 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let new_method = if types.structs.contains_key(ident) {
+        Some(quote! {
+            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_new]
+                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+                }
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                unsafe { __new(&mut repr, &mut value) }
+                repr
+            }
+        })
+    } else {
+        None
+    };
+
     quote! {
         unsafe impl ::cxx::private::UniquePtrTarget for #ident {
             fn __null() -> *mut ::std::ffi::c_void {
@@ -494,15 +510,7 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident) -> TokenStream {
                 unsafe { __null(&mut repr) }
                 repr
             }
-            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
-                extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
-                }
-                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __new(&mut repr, &mut value) }
-                repr
-            }
+            #new_method
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 94b6e25..4a1392a 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -118,7 +118,15 @@ pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
-    fn __new(value: Self) -> *mut c_void;
+    fn __new(value: Self) -> *mut c_void
+    where
+        Self: Sized,
+    {
+        // Opaque C types do not get this method because they can never exist by
+        // value on the Rust side of the bridge.
+        let _ = value;
+        unreachable!()
+    }
     #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void;
     #[doc(hidden)]

From 5f1cc8aa44210f934a2fe810ac334ea9da9f530d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 04:07:36 +0000
Subject: [PATCH 231/2232] Release 0.2.5


---

diff --git a/Cargo.toml b/Cargo.toml
index 73c7e57..851fde8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.4" # remember to update html_root_url
+version = "0.2.5" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.4", path = "macro" }
+cxxbridge-macro = { version = "=0.2.5", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index ea936b3..8e46782 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.4"
+version = "0.2.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 4fd507e..a965cf2 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.4"
+version = "0.2.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 86e9541..a254581 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.4")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.5")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::declare_interior_mutable_const,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8c8c6ef..5c2cc5f 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.4"
+version = "0.2.5"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.4"
+version = "0.2.5"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.4"
+version = "0.2.5"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -171,9 +171,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8931031034aa65c73f3f1a05c3ec0fa51287fcd06557ecf4e88b2768bdca375e"
+checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -184,9 +184,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2147536f412ee7ae5529364ed50172ca0220fd64591e236296f45f36b38b2f98"
+checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
 dependencies = [
  "proc-macro2",
  "quote",

From 25b8c8f1cbd719b4be736d8369262fc3897f1629 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 04:12:27 +0000
Subject: [PATCH 232/2232] Remove <UniquePtr<CxxString>>::new


CxxString is considered an opaque C type and can never exist in Rust by
value, so this constructor was uncallable.

---

diff --git a/src/cxx.cc b/src/cxx.cc
index 0c1b8af..35dcc95 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -169,10 +169,6 @@ void cxxbridge02$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge02$unique_ptr$std$string$new(std::unique_ptr<std::string> *ptr,
-                                           std::string *value) noexcept {
-  new (ptr) std::unique_ptr<std::string>(new std::string(std::move(*value)));
-}
 void cxxbridge02$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 4a1392a..f058d5e 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -2,7 +2,7 @@ use crate::cxx_string::CxxString;
 use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
-use std::mem::{self, MaybeUninit};
+use std::mem;
 use std::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
@@ -140,8 +140,6 @@ pub unsafe trait UniquePtrTarget {
 extern "C" {
     #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge02$unique_ptr$std$string$new"]
-    fn unique_ptr_std_string_new(this: *mut *mut c_void, value: *mut CxxString);
     #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
     #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
@@ -158,12 +156,6 @@ unsafe impl UniquePtrTarget for CxxString {
         unsafe { unique_ptr_std_string_null(&mut repr) }
         repr
     }
-    fn __new(value: Self) -> *mut c_void {
-        let mut repr = ptr::null_mut::<c_void>();
-        let mut value = MaybeUninit::new(value);
-        unsafe { unique_ptr_std_string_new(&mut repr, value.as_mut_ptr() as *mut Self) }
-        repr
-    }
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unique_ptr_std_string_raw(&mut repr, raw);

From 4bacd3cc67f3a285a36b994bb902eb83842f80fb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 04:17:51 +0000
Subject: [PATCH 233/2232] Update targets files to proc-macro-error 1.0.2


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 483224b..3bc34db 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -59,7 +59,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.1/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.2/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -71,7 +71,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.1/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.2/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
diff --git a/third-party/BUILD b/third-party/BUILD
index 093d509..8e47d3d 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.1/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.2/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.1/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.2/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",

From 1a61b16007524c006e80f4da10cc12ce277e5d75 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:20:05 +0000
Subject: [PATCH 234/2232] Provide UniquePtr::as_mut


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index f058d5e..ca527d2 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -51,6 +51,12 @@ where
         unsafe { T::__get(self.repr).as_ref() }
     }
 
+    /// Returns a mutable reference to the object owned by this UniquePtr if
+    /// any, otherwise None.
+    pub fn as_mut(&mut self) -> Option<&mut T> {
+        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
+    }
+
     /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
     ///
     /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).

From 4bc9815c6aeda5a4d09a7971afc2d490a24cc41c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:26:16 +0000
Subject: [PATCH 235/2232] Suppress clippy::cognitive_complexity lint


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 3577f72..d0a215e 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -1,4 +1,5 @@
 #![allow(
+    clippy::cognitive_complexity,
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
diff --git a/src/lib.rs b/src/lib.rs
index a254581..8b3a5a0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -340,6 +340,7 @@
 #![doc(html_root_url = "https://docs.rs/cxx/0.2.5")]
 #![deny(improper_ctypes)]
 #![allow(
+    clippy::cognitive_complexity,
     clippy::declare_interior_mutable_const,
     clippy::inherent_to_string,
     clippy::large_enum_variant,

From a95b2341d085375950dc726475c87ebf5d19322f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:26:16 +0000
Subject: [PATCH 236/2232] Suppress clippy::ptr_arg triggering on &String in tests


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7df0110..68651ea 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,4 +1,8 @@
-#![allow(clippy::boxed_local, clippy::trivially_copy_pass_by_ref)]
+#![allow(
+    clippy::boxed_local,
+    clippy::ptr_arg,
+    clippy::trivially_copy_pass_by_ref
+)]
 
 use cxx::{CxxString, UniquePtr};
 use std::fmt::{self, Display};

From d20032a1727f3fd5b731be1c14604af734526f9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:42:45 +0000
Subject: [PATCH 237/2232] Deref and DerefMut for UniquePtr


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index c8c5a67..ab8b9ef 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -3,6 +3,7 @@ use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
 use std::mem;
+use std::ops::{Deref, DerefMut};
 use std::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
@@ -94,6 +95,32 @@ where
     }
 }
 
+impl<T> Deref for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        match self.as_ref() {
+            Some(target) => target,
+            None => panic!("called deref on a null UniquePtr"),
+        }
+    }
+}
+
+impl<T> DerefMut for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called deref_mut on a null UniquePtr"),
+        }
+    }
+}
+
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,

From ad26677f7bfe58f4bf9fe4d4ca96b85f84b4e1fb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:42:45 +0000
Subject: [PATCH 238/2232] Include type name in UniquePtr function table


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e9a4495..67c34e5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -475,6 +475,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
+    let name = ident.to_string();
     let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
@@ -501,6 +502,7 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
 
     quote! {
         unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+            const __NAME: &'static str = #name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index ca527d2..c8c5a67 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -122,6 +122,8 @@ where
 // codebase.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
+    const __NAME: &'static str;
+    #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
     fn __new(value: Self) -> *mut c_void
@@ -157,6 +159,7 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
+    const __NAME: &'static str = "CxxString";
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe { unique_ptr_std_string_null(&mut repr) }

From 9f318a10ad47f60e32cedb60c1c6a969313eb50b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:44:02 +0000
Subject: [PATCH 239/2232] Show UniquePtr target type name in panics


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index ab8b9ef..b50e870 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -104,7 +104,7 @@ where
     fn deref(&self) -> &Self::Target {
         match self.as_ref() {
             Some(target) => target,
-            None => panic!("called deref on a null UniquePtr"),
+            None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
         }
     }
 }
@@ -116,7 +116,7 @@ where
     fn deref_mut(&mut self) -> &mut Self::Target {
         match self.as_mut() {
             Some(target) => target,
-            None => panic!("called deref_mut on a null UniquePtr"),
+            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
         }
     }
 }

From b5609f86cadb7f1ce80640a1ec3322ef9f9b2bb2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:44:23 +0000
Subject: [PATCH 240/2232] Add UniquePtr test


---

diff --git a/tests/unique_ptr.rs b/tests/unique_ptr.rs
new file mode 100644
index 0000000..e5eb66b
--- /dev/null
+++ b/tests/unique_ptr.rs
@@ -0,0 +1,8 @@
+use cxx::{CxxString, UniquePtr};
+
+#[test]
+#[should_panic = "called deref on a null UniquePtr<CxxString>"]
+fn test_deref_null() {
+    let unique_ptr = UniquePtr::<CxxString>::null();
+    let _: &CxxString = &unique_ptr;
+}

From b455d0a0a176a747301060eebfa096d978b2c0ef Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 06:58:38 +0000
Subject: [PATCH 241/2232] Merge pull request #95 from dtolnay/deref


Deref and DerefMut for UniquePtr
---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index c8c5a67..b50e870 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -3,6 +3,7 @@ use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
 use std::mem;
+use std::ops::{Deref, DerefMut};
 use std::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
@@ -94,6 +95,32 @@ where
     }
 }
 
+impl<T> Deref for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        match self.as_ref() {
+            Some(target) => target,
+            None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+}
+
+impl<T> DerefMut for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+}
+
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,
diff --git a/tests/unique_ptr.rs b/tests/unique_ptr.rs
new file mode 100644
index 0000000..e5eb66b
--- /dev/null
+++ b/tests/unique_ptr.rs
@@ -0,0 +1,8 @@
+use cxx::{CxxString, UniquePtr};
+
+#[test]
+#[should_panic = "called deref on a null UniquePtr<CxxString>"]
+fn test_deref_null() {
+    let unique_ptr = UniquePtr::<CxxString>::null();
+    let _: &CxxString = &unique_ptr;
+}

From 4b972729954b19d0b8535b550997e5caec7fc901 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 07:48:18 +0000
Subject: [PATCH 242/2232] Release 0.2.6


---

diff --git a/Cargo.toml b/Cargo.toml
index 851fde8..fa5fa88 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.5" # remember to update html_root_url
+version = "0.2.6" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.5", path = "macro" }
+cxxbridge-macro = { version = "=0.2.6", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 8e46782..9b15e2e 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.5"
+version = "0.2.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index a965cf2..fe87735 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.5"
+version = "0.2.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 8b3a5a0..1904cf6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.5")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.6")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5c2cc5f..4190f2a 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.5"
+version = "0.2.6"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.5"
+version = "0.2.6"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.5"
+version = "0.2.6"
 dependencies = [
  "cxx",
  "proc-macro2",

From b8a6fb27559bf27c80e0a9f1ab899f8545002d8b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 18:17:28 +0000
Subject: [PATCH 243/2232] Define rust::isize with Windows support


---

diff --git a/gen/write.rs b/gen/write.rs
index 217a591..9d6ef6e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -110,6 +110,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_str = false;
     let mut needs_rust_box = false;
     let mut needs_rust_fn = false;
+    let mut needs_rust_isize = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -124,6 +125,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Type::Fn(_) => {
                 needs_rust_fn = true;
             }
+            ty if ty == Isize => {
+                needs_rust_isize = true;
+            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -181,6 +185,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_rust_box
         || needs_rust_fn
         || needs_rust_error
+        || needs_rust_isize
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
@@ -199,6 +204,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
     if needs_manually_drop {
@@ -689,7 +695,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I16) => write!(out, "int16_t"),
             Some(I32) => write!(out, "int32_t"),
             Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "ssize_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
             Some(F32) => write!(out, "float"),
             Some(F64) => write!(out, "double"),
             Some(CxxString) => write!(out, "::std::string"),
diff --git a/include/cxx.h b/include/cxx.h
index 5de479c..6fe55d0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,6 +180,15 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_ERROR
 
+#ifndef CXXBRIDGE02_RUST_ISIZE
+#define CXXBRIDGE02_RUST_ISIZE
+#if defined(_WIN32)
+using isize = SSIZE_T;
+#else
+using isize = ssize_t;
+#endif
+#endif // CXXBRIDGE02_RUST_ISIZE
+
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 

From 59b5ba1f1433a89865f52e2cbaa231a0f7ad1940 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 18:36:08 +0000
Subject: [PATCH 244/2232] Include BaseTsd.h to get SSIZE_T


---

diff --git a/gen/include.rs b/gen/include.rs
index e3a9dd7..8f38fe3 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -38,6 +38,7 @@ pub struct Includes {
     pub string: bool,
     pub type_traits: bool,
     pub utility: bool,
+    pub base_tsd: bool,
 }
 
 impl Includes {
@@ -88,6 +89,11 @@ impl Display for Includes {
         if self.utility {
             writeln!(f, "#include <utility>")?;
         }
+        if self.base_tsd {
+            writeln!(f, "#if defined(_WIN32)")?;
+            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#endif")?;
+        }
         if *self != Self::default() {
             writeln!(f)?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index 9d6ef6e..d80e957 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -126,6 +126,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_fn = true;
             }
             ty if ty == Isize => {
+                out.include.base_tsd = true;
                 needs_rust_isize = true;
             }
             ty if ty == RustString => {
diff --git a/include/cxx.h b/include/cxx.h
index 6fe55d0..27034f0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -7,6 +7,9 @@
 #include <string>
 #include <type_traits>
 #include <utility>
+#if defined(_WIN32)
+#include <BaseTsd.h>
+#endif
 
 namespace rust {
 inline namespace cxxbridge02 {

From 59b7c12ffc75c45f16009da2ae1119a66f1ec910 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 19:04:08 +0000
Subject: [PATCH 245/2232] Merge pull request #97 from dtolnay/isize


Define rust::isize with Windows support
---

diff --git a/gen/include.rs b/gen/include.rs
index e3a9dd7..8f38fe3 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -38,6 +38,7 @@ pub struct Includes {
     pub string: bool,
     pub type_traits: bool,
     pub utility: bool,
+    pub base_tsd: bool,
 }
 
 impl Includes {
@@ -88,6 +89,11 @@ impl Display for Includes {
         if self.utility {
             writeln!(f, "#include <utility>")?;
         }
+        if self.base_tsd {
+            writeln!(f, "#if defined(_WIN32)")?;
+            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#endif")?;
+        }
         if *self != Self::default() {
             writeln!(f)?;
         }
diff --git a/gen/write.rs b/gen/write.rs
index 217a591..d80e957 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -110,6 +110,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_str = false;
     let mut needs_rust_box = false;
     let mut needs_rust_fn = false;
+    let mut needs_rust_isize = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -124,6 +125,10 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Type::Fn(_) => {
                 needs_rust_fn = true;
             }
+            ty if ty == Isize => {
+                out.include.base_tsd = true;
+                needs_rust_isize = true;
+            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -181,6 +186,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_rust_box
         || needs_rust_fn
         || needs_rust_error
+        || needs_rust_isize
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
@@ -199,6 +205,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
     if needs_manually_drop {
@@ -689,7 +696,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             Some(I16) => write!(out, "int16_t"),
             Some(I32) => write!(out, "int32_t"),
             Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "ssize_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
             Some(F32) => write!(out, "float"),
             Some(F64) => write!(out, "double"),
             Some(CxxString) => write!(out, "::std::string"),
diff --git a/include/cxx.h b/include/cxx.h
index 5de479c..27034f0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -7,6 +7,9 @@
 #include <string>
 #include <type_traits>
 #include <utility>
+#if defined(_WIN32)
+#include <BaseTsd.h>
+#endif
 
 namespace rust {
 inline namespace cxxbridge02 {
@@ -180,6 +183,15 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_ERROR
 
+#ifndef CXXBRIDGE02_RUST_ISIZE
+#define CXXBRIDGE02_RUST_ISIZE
+#if defined(_WIN32)
+using isize = SSIZE_T;
+#else
+using isize = ssize_t;
+#endif
+#endif // CXXBRIDGE02_RUST_ISIZE
+
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 

From 40b932fc455824039fe0a1fb08896b90e7265436 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 19:08:11 +0000
Subject: [PATCH 246/2232] Release 0.2.7


---

diff --git a/Cargo.toml b/Cargo.toml
index fa5fa88..c92e1c8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.6" # remember to update html_root_url
+version = "0.2.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.6", path = "macro" }
+cxxbridge-macro = { version = "=0.2.7", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 9b15e2e..9a6b8f5 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.6"
+version = "0.2.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index fe87735..f9a9904 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.6"
+version = "0.2.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 1904cf6..2d8facf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.7")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4190f2a..a6d15ad 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.6"
+version = "0.2.7"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.6"
+version = "0.2.7"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.6"
+version = "0.2.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From 8e0866125c1974c0425f928728a5e4b9c1ebaee7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 19:20:49 +0000
Subject: [PATCH 247/2232] Verify that header sections are found even if not used


This prevents typos in the endif part of the section even when test
coverage is not perfect.

---

diff --git a/gen/write.rs b/gen/write.rs
index d80e957..4eed1b4 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -261,9 +261,10 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
+    let section = include::get(section);
     if needed {
         out.next_section();
-        for line in include::get(section).lines() {
+        for line in section.lines() {
             if !line.trim_start().starts_with("//") {
                 writeln!(out, "{}", line);
             }

From 8e2771409d1c8a4e4b97798d48f2682cc33bcdbd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 10 2020 20:35:51 +0000
Subject: [PATCH 248/2232] Add a CI build on our minimum supported compiler


---

diff --git a/.travis.yml b/.travis.yml
index 1cc7806..28ad110 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -53,3 +53,5 @@ matrix:
       script:
         - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
+    - name: Minimum rustc
+      rust: 1.42.0

From ce5af5485b3ffa8982b903e4a39f5435c3447f96 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 01:08:30 +0000
Subject: [PATCH 249/2232] Accept RUST_CXX_NO_EXCEPTIONS to disable throwing


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 35dcc95..6656041 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,9 +1,20 @@
 #include "../include/cxx.h"
+#include <cstdlib>
 #include <cstring>
 #include <iostream>
 #include <memory>
 #include <stdexcept>
 
+template <typename Exception>
+[[noreturn]] static void panic(const char *msg) {
+#if defined(RUST_CXX_NO_EXCEPTIONS)
+  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
+  std::abort();
+#else
+  throw Exception(msg);
+#endif
+}
+
 extern "C" {
 const char *cxxbridge02$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -47,14 +58,14 @@ String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
   if (!cxxbridge02$string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String::String(const char *s) {
   auto len = std::strlen(s);
   if (!cxxbridge02$string$from(this, s, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
@@ -101,13 +112,13 @@ Str::Str(const Str &) noexcept = default;
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
   if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 

From 31b5aad39b16bab7634c39a1a8c7db082cd7d5b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 02:35:47 +0000
Subject: [PATCH 250/2232] Use more obvious words as the "name in C++" of Result


---

diff --git a/README.md b/README.md
index b5c57fd..0b3aab3 100644
--- a/README.md
+++ b/README.md
@@ -303,7 +303,7 @@ returns of functions.
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
-<tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/src/lib.rs b/src/lib.rs
index 2d8facf..f918b29 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -311,7 +311,7 @@
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
-//! <tr><td>Result&lt;T&gt;</td><td>error &lt;=&gt; exception</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+//! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file

From 47b3cf22836024d088909770e17d7f14c0295f81 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 07:54:39 +0000
Subject: [PATCH 251/2232] Add constructor to move T into Box


---

diff --git a/include/cxx.h b/include/cxx.h
index 27034f0..338dafe 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -98,6 +98,10 @@ public:
     this->uninit();
     ::new (this->ptr) T(val);
   }
+  Box(T &&val) {
+    this->uninit();
+    ::new (this->ptr) T(std::move(val));
+  }
   Box &operator=(const Box &other) {
     if (this != &other) {
       if (this->ptr) {

From 7ce59fc9e86e42d804243e04957db969a64e93ad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 18:53:29 +0000
Subject: [PATCH 252/2232] Add in_place constructor for Box


---

diff --git a/include/cxx.h b/include/cxx.h
index 338dafe..157c31e 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -132,6 +132,14 @@ public:
   T *operator->() noexcept { return this->ptr; }
   T &operator*() noexcept { return *this->ptr; }
 
+  template <typename... Fields>
+  static Box in_place(Fields&&... fields) {
+    Box box;
+    box.uninit();
+    ::new (box.ptr) T{std::forward<Fields>(fields)...};
+    return box;
+  }
+
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
   static Box from_raw(T *raw) noexcept {

From bbbce5a7d0bcac0bb4d4a044fafe8a0b03603384 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 21:10:24 +0000
Subject: [PATCH 253/2232] Merge pull request #101 from dtolnay/no-exceptions


Accept RUST_CXX_NO_EXCEPTIONS to disable throwing
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 35dcc95..6656041 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,9 +1,20 @@
 #include "../include/cxx.h"
+#include <cstdlib>
 #include <cstring>
 #include <iostream>
 #include <memory>
 #include <stdexcept>
 
+template <typename Exception>
+[[noreturn]] static void panic(const char *msg) {
+#if defined(RUST_CXX_NO_EXCEPTIONS)
+  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
+  std::abort();
+#else
+  throw Exception(msg);
+#endif
+}
+
 extern "C" {
 const char *cxxbridge02$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -47,14 +58,14 @@ String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
   if (!cxxbridge02$string$from(this, ptr, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String::String(const char *s) {
   auto len = std::strlen(s);
   if (!cxxbridge02$string$from(this, s, len)) {
-    throw std::invalid_argument("data for rust::String is not utf-8");
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
@@ -101,13 +112,13 @@ Str::Str(const Str &) noexcept = default;
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
   if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
-    throw std::invalid_argument("data for rust::Str is not utf-8");
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 

From dd8d06c4b9ffe3eacb06bda051250c1a1682ddcd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 21:10:48 +0000
Subject: [PATCH 254/2232] Merge pull request #106 from dtolnay/inplace


Add in_place constructor for Box
---

diff --git a/include/cxx.h b/include/cxx.h
index 338dafe..157c31e 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -132,6 +132,14 @@ public:
   T *operator->() noexcept { return this->ptr; }
   T &operator*() noexcept { return *this->ptr; }
 
+  template <typename... Fields>
+  static Box in_place(Fields&&... fields) {
+    Box box;
+    box.uninit();
+    ::new (box.ptr) T{std::forward<Fields>(fields)...};
+    return box;
+  }
+
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
   static Box from_raw(T *raw) noexcept {

From 7db7dade2481ff7113242b943a0f2362aeaacc5a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 21:12:49 +0000
Subject: [PATCH 255/2232] Make it explicit when going from T to Box<T>


---

diff --git a/include/cxx.h b/include/cxx.h
index 157c31e..2ffacc5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -94,11 +94,11 @@ public:
 
   Box(const Box &other) : Box(*other) {}
   Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  Box(const T &val) {
+  explicit Box(const T &val) {
     this->uninit();
     ::new (this->ptr) T(val);
   }
-  Box(T &&val) {
+  explicit Box(T &&val) {
     this->uninit();
     ::new (this->ptr) T(std::move(val));
   }

From d678cddb1e49eb25f54a8e88ac5ad840854e08d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 11 2020 21:38:07 +0000
Subject: [PATCH 256/2232] Merge pull request #107 from dtolnay/explicit


Make it explicit when going from T to Box<T>
---

diff --git a/include/cxx.h b/include/cxx.h
index 157c31e..2ffacc5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -94,11 +94,11 @@ public:
 
   Box(const Box &other) : Box(*other) {}
   Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  Box(const T &val) {
+  explicit Box(const T &val) {
     this->uninit();
     ::new (this->ptr) T(val);
   }
-  Box(T &&val) {
+  explicit Box(T &&val) {
     this->uninit();
     ::new (this->ptr) T(std::move(val));
   }

From 71918ec8224b6e68400abc70d66f58c6bfec08b9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 12 2020 04:52:09 +0000
Subject: [PATCH 257/2232] Use terminate instead of abort in no-exceptions mode


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 6656041..8834581 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,6 +1,6 @@
 #include "../include/cxx.h"
-#include <cstdlib>
 #include <cstring>
+#include <exception>
 #include <iostream>
 #include <memory>
 #include <stdexcept>
@@ -9,7 +9,7 @@ template <typename Exception>
 [[noreturn]] static void panic(const char *msg) {
 #if defined(RUST_CXX_NO_EXCEPTIONS)
   std::cerr << "Error: " << msg << ". Aborting." << std::endl;
-  std::abort();
+  std::terminate();
 #else
   throw Exception(msg);
 #endif

From a3d92bf9924d4d1277654c885d6ed09bcb0a7969 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 12 2020 05:04:13 +0000
Subject: [PATCH 258/2232] Merge pull request #112 from dtolnay/terminate


Use terminate instead of abort in no-exceptions mode
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 6656041..8834581 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,6 +1,6 @@
 #include "../include/cxx.h"
-#include <cstdlib>
 #include <cstring>
+#include <exception>
 #include <iostream>
 #include <memory>
 #include <stdexcept>
@@ -9,7 +9,7 @@ template <typename Exception>
 [[noreturn]] static void panic(const char *msg) {
 #if defined(RUST_CXX_NO_EXCEPTIONS)
   std::cerr << "Error: " << msg << ". Aborting." << std::endl;
-  std::abort();
+  std::terminate();
 #else
   throw Exception(msg);
 #endif

From c2279000a926db64c0bb0caa69025031174d576a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 12 2020 05:06:00 +0000
Subject: [PATCH 259/2232] Format with clangfmt


---

diff --git a/include/cxx.h b/include/cxx.h
index 2ffacc5..f7decd8 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -132,8 +132,7 @@ public:
   T *operator->() noexcept { return this->ptr; }
   T &operator*() noexcept { return *this->ptr; }
 
-  template <typename... Fields>
-  static Box in_place(Fields&&... fields) {
+  template <typename... Fields> static Box in_place(Fields &&... fields) {
     Box box;
     box.uninit();
     ::new (box.ptr) T{std::forward<Fields>(fields)...};
diff --git a/src/cxx.cc b/src/cxx.cc
index 8834581..e8ec979 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -5,8 +5,7 @@
 #include <memory>
 #include <stdexcept>
 
-template <typename Exception>
-[[noreturn]] static void panic(const char *msg) {
+template <typename Exception> static void panic [[noreturn]] (const char *msg) {
 #if defined(RUST_CXX_NO_EXCEPTIONS)
   std::cerr << "Error: " << msg << ". Aborting." << std::endl;
   std::terminate();

From f262d38671d156a2de089ae512d6e325b20dc564 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 12 2020 05:14:44 +0000
Subject: [PATCH 260/2232] AlwaysBreakTemplateDeclarations: true


I felt that the clangfmt changes in c2279000a926db64c0bb0caa69025031174d576a
were not making the code better.

---

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..181605d
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+AlwaysBreakTemplateDeclarations: true
diff --git a/include/cxx.h b/include/cxx.h
index f7decd8..a8239a1 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -85,7 +85,8 @@ private:
 
 #ifndef CXXBRIDGE02_RUST_BOX
 #define CXXBRIDGE02_RUST_BOX
-template <typename T> class Box final {
+template <typename T>
+class Box final {
 public:
   using value_type = T;
   using const_pointer = typename std::add_pointer<
@@ -132,7 +133,8 @@ public:
   T *operator->() noexcept { return this->ptr; }
   T &operator*() noexcept { return *this->ptr; }
 
-  template <typename... Fields> static Box in_place(Fields &&... fields) {
+  template <typename... Fields>
+  static Box in_place(Fields &&... fields) {
     Box box;
     box.uninit();
     ::new (box.ptr) T{std::forward<Fields>(fields)...};
@@ -163,7 +165,8 @@ private:
 
 #ifndef CXXBRIDGE02_RUST_FN
 #define CXXBRIDGE02_RUST_FN
-template <typename Signature, bool Throws = false> class Fn;
+template <typename Signature, bool Throws = false>
+class Fn;
 
 template <typename Ret, typename... Args, bool Throws>
 class Fn<Ret(Args...), Throws> {
@@ -176,7 +179,8 @@ private:
   void *fn;
 };
 
-template <typename Signature> using TryFn = Fn<Signature, true>;
+template <typename Signature>
+using TryFn = Fn<Signature, true>;
 #endif // CXXBRIDGE02_RUST_FN
 
 #ifndef CXXBRIDGE02_RUST_ERROR
@@ -209,11 +213,13 @@ std::ostream &operator<<(std::ostream &, const Str &);
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;
-template <class T> using box = Box<T>;
+template <class T>
+using box = Box<T>;
 using error = Error;
 template <typename Signature, bool Throws = false>
 using fn = Fn<Signature, Throws>;
-template <typename Signature> using try_fn = TryFn<Signature>;
+template <typename Signature>
+using try_fn = TryFn<Signature>;
 
 #ifndef CXXBRIDGE02_RUST_BITCOPY
 #define CXXBRIDGE02_RUST_BITCOPY
diff --git a/src/cxx.cc b/src/cxx.cc
index e8ec979..b64333c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -5,7 +5,8 @@
 #include <memory>
 #include <stdexcept>
 
-template <typename Exception> static void panic [[noreturn]] (const char *msg) {
+template <typename Exception>
+static void panic [[noreturn]] (const char *msg) {
 #if defined(RUST_CXX_NO_EXCEPTIONS)
   std::cerr << "Error: " << msg << ". Aborting." << std::endl;
   std::terminate();

From 7f635f360e279d3c3a00f78a8911cca32d90991a Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Apr 13 2020 05:04:11 +0000
Subject: [PATCH 261/2232] Specify author explicitly.


For those building without Cargo, it may be a little awkward to specify
the CARGO_PKG_AUTHORS environment variable (in some cases perhaps
requiring a wrapper script around rustc).

---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index d0a215e..8c407ad 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -17,7 +17,7 @@ use structopt::StructOpt;
 #[derive(StructOpt, Debug)]
 #[structopt(
     name = "cxxbridge",
-    author,
+    author = "dtolnay@gmail.com",
     about = "https://github.com/dtolnay/cxx",
     usage = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout

From 60a30832318343afec4df3757df9f521fe91b833 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 13 2020 06:19:37 +0000
Subject: [PATCH 262/2232] Merge pull request #113 from adetaylor/with-author


Specify author explicitly.
---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index d0a215e..8c407ad 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -17,7 +17,7 @@ use structopt::StructOpt;
 #[derive(StructOpt, Debug)]
 #[structopt(
     name = "cxxbridge",
-    author,
+    author = "dtolnay@gmail.com",
     about = "https://github.com/dtolnay/cxx",
     usage = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout

From bf787c587eb4b9a94d2ce88e1fb1248dc2ed3321 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 13 2020 06:20:21 +0000
Subject: [PATCH 263/2232] Update cmd author to match author in Cargo.toml


---

diff --git a/cmd/src/main.rs b/cmd/src/main.rs
index 8c407ad..a20179f 100644
--- a/cmd/src/main.rs
+++ b/cmd/src/main.rs
@@ -17,7 +17,7 @@ use structopt::StructOpt;
 #[derive(StructOpt, Debug)]
 #[structopt(
     name = "cxxbridge",
-    author = "dtolnay@gmail.com",
+    author = "David Tolnay <dtolnay@gmail.com>",
     about = "https://github.com/dtolnay/cxx",
     usage = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout

From efa9edae9f84ecf7eb596374a357544e127bc8bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 03:30:12 +0000
Subject: [PATCH 264/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 3bc34db..af14713 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -171,14 +171,14 @@ rust_library(
 
 rust_library(
     name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.14/src/**"]),
+    srcs = glob(["vendor/thiserror-1.0.15/src/**"]),
     visibility = ["PUBLIC"],
     deps = [":thiserror-impl"],
 )
 
 rust_library(
     name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.14/src/**"]),
+    srcs = glob(["vendor/thiserror-impl-1.0.15/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
diff --git a/third-party/BUILD b/third-party/BUILD
index 8e47d3d..25a3dd6 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -176,14 +176,14 @@ rust_library(
 
 rust_library(
     name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.14/src/**"]),
+    srcs = glob(["vendor/thiserror-1.0.15/src/**"]),
     visibility = ["//visibility:public"],
     deps = [":thiserror-impl"],
 )
 
 rust_library(
     name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.14/src/**"]),
+    srcs = glob(["vendor/thiserror-impl-1.0.15/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a6d15ad..48552bc 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -156,9 +156,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.68"
+version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
+checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
 
 [[package]]
 name = "link-cplusplus"
@@ -333,18 +333,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae"
+checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd"
+checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd"
 dependencies = [
  "proc-macro2",
  "quote",

From 48b09e94ef034dc155bb32c42ad25fa097fdd195 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 03:31:09 +0000
Subject: [PATCH 265/2232] Release 0.2.8


---

diff --git a/Cargo.toml b/Cargo.toml
index c92e1c8..044095b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.7" # remember to update html_root_url
+version = "0.2.8" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.7", path = "macro" }
+cxxbridge-macro = { version = "=0.2.8", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 9a6b8f5..4a4cde2 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.7"
+version = "0.2.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index f9a9904..c85062f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.7"
+version = "0.2.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index f918b29..7ee2bfe 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.8")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 48552bc..fce3ce0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.7"
+version = "0.2.8"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.7"
+version = "0.2.8"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.7"
+version = "0.2.8"
 dependencies = [
  "cxx",
  "proc-macro2",

From 9b894fb96e6155166823a0e09140eef3fef48952 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 18:13:25 +0000
Subject: [PATCH 266/2232] Handle failures to symlink on windows


---

diff --git a/src/paths.rs b/src/paths.rs
index 62fbb6e..ca183d9 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -1,7 +1,6 @@
 use crate::error::{Error, Result};
 use std::env;
 use std::fs;
-use std::os;
 use std::path::{Path, PathBuf};
 
 fn out_dir() -> Result<PathBuf> {
@@ -28,22 +27,17 @@ pub(crate) fn symlink_header(path: &Path, original: &Path) {
 }
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
-    #[cfg(unix)]
-    use os::unix::fs::symlink;
-    #[cfg(windows)]
-    use os::windows::fs::symlink_file as symlink;
-
     let suffix = relative_to_parent_of_target_dir(original)?;
     let ref dst = include_dir()?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
-    symlink(path, dst)?;
+    symlink_or_copy(path, dst)?;
 
     let mut file_name = dst.file_name().unwrap().to_os_string();
     file_name.push(".h");
-    let dst2 = dst.with_file_name(file_name);
-    symlink(path, dst2)?;
+    let ref dst2 = dst.with_file_name(file_name);
+    symlink_or_copy(path, dst2)?;
 
     Ok(())
 }
@@ -102,3 +96,21 @@ fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
     // https://github.com/alexcrichton/cc-rs/issues/169
     Ok(env::current_dir()?.join(path))
 }
+
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_or_copy;
+
+#[cfg(windows)]
+fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+    use std::os::windows::fs::symlink_file;
+
+    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
+    // require Developer Mode. If it fails, fall back to copying the file.
+    if symlink_file(src, dst).is_err() {
+        fs::copy(src, dst)?;
+    }
+    Ok(())
+}
+
+#[cfg(not(any(unix, windows)))]
+use std::fs::copy as symlink_or_copy;

From 850ca90849e7fb2c045fecdd428f865686e3bb4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 18:53:00 +0000
Subject: [PATCH 267/2232] Merge pull request #116 from dtolnay/symlink


Handle failures to symlink on windows
---

diff --git a/src/paths.rs b/src/paths.rs
index 62fbb6e..ca183d9 100644
--- a/src/paths.rs
+++ b/src/paths.rs
@@ -1,7 +1,6 @@
 use crate::error::{Error, Result};
 use std::env;
 use std::fs;
-use std::os;
 use std::path::{Path, PathBuf};
 
 fn out_dir() -> Result<PathBuf> {
@@ -28,22 +27,17 @@ pub(crate) fn symlink_header(path: &Path, original: &Path) {
 }
 
 fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
-    #[cfg(unix)]
-    use os::unix::fs::symlink;
-    #[cfg(windows)]
-    use os::windows::fs::symlink_file as symlink;
-
     let suffix = relative_to_parent_of_target_dir(original)?;
     let ref dst = include_dir()?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
-    symlink(path, dst)?;
+    symlink_or_copy(path, dst)?;
 
     let mut file_name = dst.file_name().unwrap().to_os_string();
     file_name.push(".h");
-    let dst2 = dst.with_file_name(file_name);
-    symlink(path, dst2)?;
+    let ref dst2 = dst.with_file_name(file_name);
+    symlink_or_copy(path, dst2)?;
 
     Ok(())
 }
@@ -102,3 +96,21 @@ fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
     // https://github.com/alexcrichton/cc-rs/issues/169
     Ok(env::current_dir()?.join(path))
 }
+
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_or_copy;
+
+#[cfg(windows)]
+fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+    use std::os::windows::fs::symlink_file;
+
+    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
+    // require Developer Mode. If it fails, fall back to copying the file.
+    if symlink_file(src, dst).is_err() {
+        fs::copy(src, dst)?;
+    }
+    Ok(())
+}
+
+#[cfg(not(any(unix, windows)))]
+use std::fs::copy as symlink_or_copy;

From f5dd552036cf28b7d7975c3bc37b0d8308a2500d Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Apr 14 2020 21:13:48 +0000
Subject: [PATCH 268/2232] Adding &[u8] support.


This change adds specifically, support for &[u8] with a corresponding
rust::Slice<uint8_t> type. No other types of slice are permitted. The
rationale is that it may be common to pass binary data back and forth
across the FFI boundary, so it's more urgent to get this in place sooner.
Broader support for other slices can wait for the future.

But, both C++ and Rust-side bindings should allow the existing support
to be broadened to other Slice types in future without code changes.

A few specific notes:

* The name "rust::Slice" might be better as "rust::SliceRef" but I'm
  following the precedent of "rust::Str".
* It would be good to add constructors from std::span but as that's
  a C++20 feature, that may have to wait until C++ feature detection
  is resolved.
* Internally, this follows the pattern of &str, where the parser will
  initially recognize this as Type::Ref (of Type::Slice) but then
  will replace that with Type::SliceRefU8. Type::Slice should not
  persist through later stages. As we later come to support other
  types of slice, we would probably want to remove Type::SliceRefU8.

---

diff --git a/README.md b/README.md
index 0b3aab3..ad14b57 100644
--- a/README.md
+++ b/README.md
@@ -299,6 +299,7 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
+<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td>(no other slice types currently supported)</td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -316,7 +317,6 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;[T]</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/gen/write.rs b/gen/write.rs
index 4eed1b4..3f3cf4b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -365,6 +365,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
         Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
+        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, "::rust::Slice<uint8_t>::Repr("),
         _ => {}
     }
     write!(out, "{}$(", efn.ident);
@@ -395,7 +396,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -566,6 +567,7 @@ fn write_rust_function_shim_impl(
             }
             match &arg.ty {
                 Type::Str(_) => write!(out, "::rust::Str::Repr("),
+                Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
                 ty if types.needs_indirect_abi(ty) => write!(out, "&"),
                 _ => {}
             }
@@ -573,7 +575,7 @@ fn write_rust_function_shim_impl(
             match &arg.ty {
                 Type::RustBox(_) => write!(out, ".into_raw()"),
                 Type::UniquePtr(_) => write!(out, ".release()"),
-                Type::Str(_) => write!(out, ")"),
+                Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
                 ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
                 _ => {}
             }
@@ -637,6 +639,7 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write!(out, " *");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr"),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
         _ => write_type(out, ty),
     }
 }
@@ -645,7 +648,7 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
     write_indirect_return_type(out, ty);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
-        Type::Str(_) => write!(out, " "),
+        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
         _ => write_space_after_type(out, ty),
     }
 }
@@ -664,6 +667,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
             write!(out, " *");
         }
         Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
+        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -676,6 +680,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write!(out, "*");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr "),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -721,9 +726,16 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &r.inner);
             write!(out, " &");
         }
+        Type::Slice(_) => {
+            // For now, only U8 slices are supported, which are covered separately below
+            unreachable!()
+        }
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
+        Type::SliceRefU8(_) => {
+            write!(out, "::rust::Slice<uint8_t>");
+        }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
             match &f.ret {
@@ -750,11 +762,11 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
 
 fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
-        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::Fn(_) => {
+        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) | Type::Fn(_) => {
             write!(out, " ")
         }
         Type::Ref(_) => {}
-        Type::Void(_) => unreachable!(),
+        Type::Void(_) | Type::Slice(_) => unreachable!(),
     }
 }
 
diff --git a/include/cxx.h b/include/cxx.h
index a8239a1..57a6e24 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -16,6 +16,43 @@ inline namespace cxxbridge02 {
 
 struct unsafe_bitcopy_t;
 
+#ifndef CXXBRIDGE02_RUST_SLICE
+#define CXXBRIDGE02_RUST_SLICE
+template<typename T>
+class Slice final {
+public:
+  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+  Slice(const Slice<T> &) noexcept = default;
+
+  Slice(const T* s, size_t size) : repr(Repr{s, size}) {}
+
+  Slice &operator=(Slice<T> other) noexcept {
+    this->repr = other.repr;
+    return *this;
+  }
+
+  const T *data() const noexcept { return this->repr.ptr; }
+  size_t size() const noexcept { return this->repr.len; }
+  size_t length() const noexcept { return this->repr.len; }
+
+  // Repr is PRIVATE; must not be used other than by our generated code.
+  //
+  // At present this class is only used for &[u8] slices.
+  // Not necessarily ABI compatible with &[u8]. Codegen will translate to
+  // cxx::rust_slice_u8::RustSlice which matches this layout.
+  struct Repr {
+    const T *ptr;
+    size_t len;
+  };
+  Slice(Repr repr_) noexcept : repr(repr_) {}
+  explicit operator Repr() noexcept { return this->repr; }
+
+private:
+  Repr repr;
+};
+
+#endif // CXXBRIDGE02_RUST_SLICE
+
 #ifndef CXXBRIDGE02_RUST_STRING
 #define CXXBRIDGE02_RUST_STRING
 class String final {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 67c34e5..146d21b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -184,6 +184,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
+            Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
         }
@@ -255,6 +256,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
+            Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
             _ => None,
         })
     } else {
@@ -267,6 +269,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
+            Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
             _ => None,
         })
     }
@@ -375,6 +378,7 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
+            Type::SliceRefU8(_) => quote!(#ident.as_slice()),
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -402,6 +406,7 @@ fn expand_rust_function_shim_impl(
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
+            Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))),
             _ => None,
         })
         .unwrap_or(call);
@@ -572,6 +577,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             _ => quote!(#ty),
         },
         Type::Str(_) => quote!(::cxx::private::RustStr),
+        Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
         _ => quote!(#ty),
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index f918b29..60750fb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -367,6 +367,7 @@ mod gen;
 mod opaque;
 mod paths;
 mod result;
+mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod syntax;
@@ -384,6 +385,7 @@ pub mod private {
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
+    pub use crate::rust_sliceu8::RustSliceU8;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
new file mode 100644
index 0000000..56d37b3
--- /dev/null
+++ b/src/rust_sliceu8.rs
@@ -0,0 +1,26 @@
+use std::mem;
+use std::slice;
+use std::ptr::NonNull;
+
+// Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct RustSliceU8 {
+    pub(crate) ptr: NonNull<u8>,
+    pub(crate) len: usize,
+}
+
+impl RustSliceU8 {
+    pub fn from(s: &[u8]) -> Self {
+        RustSliceU8 {
+            ptr: NonNull::from(s).cast::<u8>(),
+            len: s.len(),
+        }
+    }
+
+    pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
+        slice::from_raw_parts(self.ptr.as_ptr(), self.len)
+    }
+}
+
+const_assert!(mem::size_of::<Option<RustSliceU8>>() == mem::size_of::<RustSliceU8>());
diff --git a/syntax/check.rs b/syntax/check.rs
index 2826a85..c71295e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -245,6 +245,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Slice(_) => "slice".to_owned(),
+        Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 34fb851..b040753 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type};
+use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
@@ -21,6 +21,8 @@ impl Hash for Type {
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
+            Type::Slice(t) => t.hash(state),
+            Type::SliceRefU8(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -37,6 +39,8 @@ impl PartialEq for Type {
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
+            (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
+            (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
@@ -106,6 +110,32 @@ impl Hash for Ref {
     }
 }
 
+impl Eq for Slice {}
+
+impl PartialEq for Slice {
+    fn eq(&self, other: &Slice) -> bool {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        let Slice {
+            bracket: _,
+            inner: inner2,
+        } = other;
+        inner == inner2
+    }
+}
+
+impl Hash for Slice {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        inner.hash(state);
+    }
+}
+
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 0d0328b..4eaf81e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,7 +15,7 @@ pub mod types;
 use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
-use syn::token::{Brace, Paren};
+use syn::token::{Brace, Bracket, Paren};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
@@ -84,6 +84,8 @@ pub enum Type {
     Str(Box<Ref>),
     Fn(Box<Signature>),
     Void(Span),
+    Slice(Box<Slice>),
+    SliceRefU8(Box<Ref>),
 }
 
 pub struct Ty1 {
@@ -99,6 +101,11 @@ pub struct Ref {
     pub inner: Type,
 }
 
+pub struct Slice {
+    pub bracket: Bracket,
+    pub inner: Type,
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum Lang {
     Cxx,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8e674bd..6156a69 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,6 +1,6 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Struct,
-    Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::{format_ident, quote};
@@ -8,7 +8,7 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
     ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
-    TypeBareFn, TypePath, TypeReference,
+    TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -222,10 +222,25 @@ fn parse_type(ty: &RustType) -> Result<Type> {
         RustType::Path(ty) => parse_type_path(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
+        RustType::Slice(ty) => parse_type_slice(ty),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
+    let which = match &inner {
+        Type::Ident(ident) if ident == "u8" => {
+            Type::Slice
+        },
+        _ => return Err(Error::new_spanned(ty, "unsupported type"))
+    };
+    Ok(which(Box::new(Slice {
+        bracket: ty.bracket_token,
+        inner
+    })))
+}
+
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
@@ -236,6 +251,14 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
                 Type::Str
             }
         }
+        Type::Slice(inner2) => {
+            match &inner2.inner {
+                Type::Ident(ident) if ident == "u8" => {
+                    Type::SliceRefU8
+                }
+                _ => return Err(Error::new_spanned(ty, "unsupported type"))
+            }
+        }
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 51592dd..df11852 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Ref, Signature, Slice, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::Token;
@@ -15,7 +15,8 @@ impl ToTokens for Type {
                 ident.to_tokens(tokens);
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
-            Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
+            Type::Slice(s) => s.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
@@ -51,6 +52,14 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Slice {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.bracket.surround(tokens, |tokens| {
+            self.inner.to_tokens(tokens);
+        });
+    }
+}
+
 impl ToTokens for Derive {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let name = match self {
diff --git a/syntax/types.rs b/syntax/types.rs
index f65b12f..6f3af09 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -23,9 +23,10 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 68651ea..adcd4fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -24,6 +24,7 @@ pub mod ffi {
         fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_str(shared: &Shared) -> &str;
+        fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
 
@@ -34,6 +35,7 @@ pub mod ffi {
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
+        fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_callback(callback: fn(String) -> usize);
@@ -44,6 +46,7 @@ pub mod ffi {
         fn c_try_return_box() -> Result<Box<R>>;
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
+        fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
     }
@@ -67,6 +70,7 @@ pub mod ffi {
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
+        fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
 
@@ -160,6 +164,11 @@ fn r_take_rust_string(s: String) {
     assert_eq!(s, "2020");
 }
 
+fn r_take_sliceu8(s: &[u8]) {
+    assert_eq!(s.len(), 5);
+    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\u{0}");
+}
+
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4aad3a2..307b7e5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -9,6 +9,8 @@ extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
 
 namespace tests {
 
+const char* SLICE_DATA = "2020";
+
 C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
@@ -32,6 +34,11 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
+rust::Slice<uint8_t> c_return_sliceu8(const Shared& shared) {
+  (void)shared;
+  return rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5);
+}
+
 rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
@@ -80,6 +87,12 @@ void c_take_str(rust::Str s) {
   }
 }
 
+void c_take_sliceu8(rust::Slice<uint8_t> s) {
+  if (std::string((const char*)s.data(), s.size()) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
@@ -108,6 +121,8 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; }
 
 rust::Str c_try_return_str(rust::Str s) { return s; }
 
+rust::Slice<uint8_t> c_try_return_sliceU8(rust::Slice<uint8_t> s) { return s; }
+
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
@@ -146,6 +161,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
+  r_take_sliceu8(rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6713614..a68be5c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -23,6 +23,7 @@ rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 rust::Str c_return_str(const Shared &shared);
+rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
@@ -33,6 +34,7 @@ void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_str(rust::Str s);
+void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
@@ -43,6 +45,7 @@ size_t c_fail_return_primitive();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
+rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 
diff --git a/tests/test.rs b/tests/test.rs
index f8e9ca8..ae2fc0c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -71,6 +71,7 @@ fn test_c_take() {
     check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
     check!(ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
+    check!(ffi::c_take_sliceu8(b"2020"));
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From ec9430e6576655464b3835372d23f4a1e03f4bf0 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Apr 14 2020 23:12:21 +0000
Subject: [PATCH 269/2232] Adding missing tests; fixing typo.


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 307b7e5..bf5e76d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -121,7 +121,7 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; }
 
 rust::Str c_try_return_str(rust::Str s) { return s; }
 
-rust::Slice<uint8_t> c_try_return_sliceU8(rust::Slice<uint8_t> s) { return s; }
+rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t> s) { return s; }
 
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
diff --git a/tests/test.rs b/tests/test.rs
index ae2fc0c..511c52b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -29,6 +29,7 @@ fn test_c_return() {
     ffi::c_return_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
+    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!(
         "2020",
@@ -51,6 +52,7 @@ fn test_c_try_return() {
     assert_eq!(2020, *ffi::c_try_return_box().unwrap());
     assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
+    assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
     assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
     assert_eq!(
         "2020",

From f677f0aafa476757dc213a329a039917d6767ecb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:41:52 +0000
Subject: [PATCH 270/2232] Merge pull request #117 from adetaylor/sliceu8


Adding &[u8] support.
---

diff --git a/README.md b/README.md
index 0b3aab3..ad14b57 100644
--- a/README.md
+++ b/README.md
@@ -299,6 +299,7 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
+<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td>(no other slice types currently supported)</td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -316,7 +317,6 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;[T]</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/gen/write.rs b/gen/write.rs
index 4eed1b4..3f3cf4b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -365,6 +365,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
         Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
+        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, "::rust::Slice<uint8_t>::Repr("),
         _ => {}
     }
     write!(out, "{}$(", efn.ident);
@@ -395,7 +396,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -566,6 +567,7 @@ fn write_rust_function_shim_impl(
             }
             match &arg.ty {
                 Type::Str(_) => write!(out, "::rust::Str::Repr("),
+                Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
                 ty if types.needs_indirect_abi(ty) => write!(out, "&"),
                 _ => {}
             }
@@ -573,7 +575,7 @@ fn write_rust_function_shim_impl(
             match &arg.ty {
                 Type::RustBox(_) => write!(out, ".into_raw()"),
                 Type::UniquePtr(_) => write!(out, ".release()"),
-                Type::Str(_) => write!(out, ")"),
+                Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
                 ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
                 _ => {}
             }
@@ -637,6 +639,7 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write!(out, " *");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr"),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
         _ => write_type(out, ty),
     }
 }
@@ -645,7 +648,7 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
     write_indirect_return_type(out, ty);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
-        Type::Str(_) => write!(out, " "),
+        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
         _ => write_space_after_type(out, ty),
     }
 }
@@ -664,6 +667,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
             write!(out, " *");
         }
         Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
+        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -676,6 +680,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
             write!(out, "*");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr "),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if types.needs_indirect_abi(&arg.ty) {
@@ -721,9 +726,16 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &r.inner);
             write!(out, " &");
         }
+        Type::Slice(_) => {
+            // For now, only U8 slices are supported, which are covered separately below
+            unreachable!()
+        }
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
+        Type::SliceRefU8(_) => {
+            write!(out, "::rust::Slice<uint8_t>");
+        }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
             match &f.ret {
@@ -750,11 +762,11 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
 
 fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
-        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::Fn(_) => {
+        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) | Type::Fn(_) => {
             write!(out, " ")
         }
         Type::Ref(_) => {}
-        Type::Void(_) => unreachable!(),
+        Type::Void(_) | Type::Slice(_) => unreachable!(),
     }
 }
 
diff --git a/include/cxx.h b/include/cxx.h
index a8239a1..57a6e24 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -16,6 +16,43 @@ inline namespace cxxbridge02 {
 
 struct unsafe_bitcopy_t;
 
+#ifndef CXXBRIDGE02_RUST_SLICE
+#define CXXBRIDGE02_RUST_SLICE
+template<typename T>
+class Slice final {
+public:
+  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+  Slice(const Slice<T> &) noexcept = default;
+
+  Slice(const T* s, size_t size) : repr(Repr{s, size}) {}
+
+  Slice &operator=(Slice<T> other) noexcept {
+    this->repr = other.repr;
+    return *this;
+  }
+
+  const T *data() const noexcept { return this->repr.ptr; }
+  size_t size() const noexcept { return this->repr.len; }
+  size_t length() const noexcept { return this->repr.len; }
+
+  // Repr is PRIVATE; must not be used other than by our generated code.
+  //
+  // At present this class is only used for &[u8] slices.
+  // Not necessarily ABI compatible with &[u8]. Codegen will translate to
+  // cxx::rust_slice_u8::RustSlice which matches this layout.
+  struct Repr {
+    const T *ptr;
+    size_t len;
+  };
+  Slice(Repr repr_) noexcept : repr(repr_) {}
+  explicit operator Repr() noexcept { return this->repr; }
+
+private:
+  Repr repr;
+};
+
+#endif // CXXBRIDGE02_RUST_SLICE
+
 #ifndef CXXBRIDGE02_RUST_STRING
 #define CXXBRIDGE02_RUST_STRING
 class String final {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 67c34e5..146d21b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -184,6 +184,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
+            Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
         }
@@ -255,6 +256,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
+            Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
             _ => None,
         })
     } else {
@@ -267,6 +269,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
+            Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
             _ => None,
         })
     }
@@ -375,6 +378,7 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
+            Type::SliceRefU8(_) => quote!(#ident.as_slice()),
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -402,6 +406,7 @@ fn expand_rust_function_shim_impl(
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
+            Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))),
             _ => None,
         })
         .unwrap_or(call);
@@ -572,6 +577,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             _ => quote!(#ty),
         },
         Type::Str(_) => quote!(::cxx::private::RustStr),
+        Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
         _ => quote!(#ty),
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 7ee2bfe..1ceef52 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -367,6 +367,7 @@ mod gen;
 mod opaque;
 mod paths;
 mod result;
+mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod syntax;
@@ -384,6 +385,7 @@ pub mod private {
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
+    pub use crate::rust_sliceu8::RustSliceU8;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
new file mode 100644
index 0000000..56d37b3
--- /dev/null
+++ b/src/rust_sliceu8.rs
@@ -0,0 +1,26 @@
+use std::mem;
+use std::slice;
+use std::ptr::NonNull;
+
+// Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct RustSliceU8 {
+    pub(crate) ptr: NonNull<u8>,
+    pub(crate) len: usize,
+}
+
+impl RustSliceU8 {
+    pub fn from(s: &[u8]) -> Self {
+        RustSliceU8 {
+            ptr: NonNull::from(s).cast::<u8>(),
+            len: s.len(),
+        }
+    }
+
+    pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
+        slice::from_raw_parts(self.ptr.as_ptr(), self.len)
+    }
+}
+
+const_assert!(mem::size_of::<Option<RustSliceU8>>() == mem::size_of::<RustSliceU8>());
diff --git a/syntax/check.rs b/syntax/check.rs
index 2826a85..c71295e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -245,6 +245,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Slice(_) => "slice".to_owned(),
+        Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 34fb851..b040753 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type};
+use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::Deref;
@@ -21,6 +21,8 @@ impl Hash for Type {
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
+            Type::Slice(t) => t.hash(state),
+            Type::SliceRefU8(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -37,6 +39,8 @@ impl PartialEq for Type {
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
+            (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
+            (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
@@ -106,6 +110,32 @@ impl Hash for Ref {
     }
 }
 
+impl Eq for Slice {}
+
+impl PartialEq for Slice {
+    fn eq(&self, other: &Slice) -> bool {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        let Slice {
+            bracket: _,
+            inner: inner2,
+        } = other;
+        inner == inner2
+    }
+}
+
+impl Hash for Slice {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Slice {
+            bracket: _,
+            inner,
+        } = self;
+        inner.hash(state);
+    }
+}
+
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 0d0328b..4eaf81e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,7 +15,7 @@ pub mod types;
 use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
-use syn::token::{Brace, Paren};
+use syn::token::{Brace, Bracket, Paren};
 use syn::{LitStr, Token};
 
 pub use self::atom::Atom;
@@ -84,6 +84,8 @@ pub enum Type {
     Str(Box<Ref>),
     Fn(Box<Signature>),
     Void(Span),
+    Slice(Box<Slice>),
+    SliceRefU8(Box<Ref>),
 }
 
 pub struct Ty1 {
@@ -99,6 +101,11 @@ pub struct Ref {
     pub inner: Type,
 }
 
+pub struct Slice {
+    pub bracket: Bracket,
+    pub inner: Type,
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum Lang {
     Cxx,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8e674bd..6156a69 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,6 +1,6 @@
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Struct,
-    Ty1, Type, Var,
+    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Var,
 };
 use proc_macro2::Ident;
 use quote::{format_ident, quote};
@@ -8,7 +8,7 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
     ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
-    TypeBareFn, TypePath, TypeReference,
+    TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -222,10 +222,25 @@ fn parse_type(ty: &RustType) -> Result<Type> {
         RustType::Path(ty) => parse_type_path(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
+        RustType::Slice(ty) => parse_type_slice(ty),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
+    let which = match &inner {
+        Type::Ident(ident) if ident == "u8" => {
+            Type::Slice
+        },
+        _ => return Err(Error::new_spanned(ty, "unsupported type"))
+    };
+    Ok(which(Box::new(Slice {
+        bracket: ty.bracket_token,
+        inner
+    })))
+}
+
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
@@ -236,6 +251,14 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
                 Type::Str
             }
         }
+        Type::Slice(inner2) => {
+            match &inner2.inner {
+                Type::Ident(ident) if ident == "u8" => {
+                    Type::SliceRefU8
+                }
+                _ => return Err(Error::new_spanned(ty, "unsupported type"))
+            }
+        }
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 51592dd..df11852 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Ref, Signature, Slice, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::Token;
@@ -15,7 +15,8 @@ impl ToTokens for Type {
                 ident.to_tokens(tokens);
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
-            Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
+            Type::Slice(s) => s.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
@@ -51,6 +52,14 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Slice {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.bracket.surround(tokens, |tokens| {
+            self.inner.to_tokens(tokens);
+        });
+    }
+}
+
 impl ToTokens for Derive {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let name = match self {
diff --git a/syntax/types.rs b/syntax/types.rs
index f65b12f..6f3af09 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -23,9 +23,10 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
                 Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 68651ea..adcd4fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -24,6 +24,7 @@ pub mod ffi {
         fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_str(shared: &Shared) -> &str;
+        fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
 
@@ -34,6 +35,7 @@ pub mod ffi {
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
+        fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_callback(callback: fn(String) -> usize);
@@ -44,6 +46,7 @@ pub mod ffi {
         fn c_try_return_box() -> Result<Box<R>>;
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
+        fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
     }
@@ -67,6 +70,7 @@ pub mod ffi {
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
+        fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
 
@@ -160,6 +164,11 @@ fn r_take_rust_string(s: String) {
     assert_eq!(s, "2020");
 }
 
+fn r_take_sliceu8(s: &[u8]) {
+    assert_eq!(s.len(), 5);
+    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\u{0}");
+}
+
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4aad3a2..bf5e76d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -9,6 +9,8 @@ extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
 
 namespace tests {
 
+const char* SLICE_DATA = "2020";
+
 C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
@@ -32,6 +34,11 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
+rust::Slice<uint8_t> c_return_sliceu8(const Shared& shared) {
+  (void)shared;
+  return rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5);
+}
+
 rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
@@ -80,6 +87,12 @@ void c_take_str(rust::Str s) {
   }
 }
 
+void c_take_sliceu8(rust::Slice<uint8_t> s) {
+  if (std::string((const char*)s.data(), s.size()) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
@@ -108,6 +121,8 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; }
 
 rust::Str c_try_return_str(rust::Str s) { return s; }
 
+rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t> s) { return s; }
+
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
@@ -146,6 +161,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
+  r_take_sliceu8(rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6713614..a68be5c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -23,6 +23,7 @@ rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 rust::Str c_return_str(const Shared &shared);
+rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 
@@ -33,6 +34,7 @@ void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_str(rust::Str s);
+void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
@@ -43,6 +45,7 @@ size_t c_fail_return_primitive();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
+rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 
diff --git a/tests/test.rs b/tests/test.rs
index f8e9ca8..511c52b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -29,6 +29,7 @@ fn test_c_return() {
     ffi::c_return_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
+    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!(
         "2020",
@@ -51,6 +52,7 @@ fn test_c_try_return() {
     assert_eq!(2020, *ffi::c_try_return_box().unwrap());
     assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
+    assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
     assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
     assert_eq!(
         "2020",
@@ -71,6 +73,7 @@ fn test_c_take() {
     check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
     check!(ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
+    check!(ffi::c_take_sliceu8(b"2020"));
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From eb952bac142ac4755d8fd2c854c9fbc1d697d557 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 271/2232] Format with rustfmt and clang-format


---

diff --git a/gen/write.rs b/gen/write.rs
index 3f3cf4b..f930d52 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -365,7 +365,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
         Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
-        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, "::rust::Slice<uint8_t>::Repr("),
+        Some(Type::SliceRefU8(_)) if !indirect_return => {
+            write!(out, "::rust::Slice<uint8_t>::Repr(")
+        }
         _ => {}
     }
     write!(out, "{}$(", efn.ident);
@@ -762,9 +764,12 @@ fn write_type_space(out: &mut OutFile, ty: &Type) {
 
 fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     match ty {
-        Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) | Type::Fn(_) => {
-            write!(out, " ")
-        }
+        Type::Ident(_)
+        | Type::RustBox(_)
+        | Type::UniquePtr(_)
+        | Type::Str(_)
+        | Type::SliceRefU8(_)
+        | Type::Fn(_) => write!(out, " "),
         Type::Ref(_) => {}
         Type::Void(_) | Type::Slice(_) => unreachable!(),
     }
diff --git a/include/cxx.h b/include/cxx.h
index 57a6e24..e63790b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -18,13 +18,13 @@ struct unsafe_bitcopy_t;
 
 #ifndef CXXBRIDGE02_RUST_SLICE
 #define CXXBRIDGE02_RUST_SLICE
-template<typename T>
+template <typename T>
 class Slice final {
 public:
   Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
   Slice(const Slice<T> &) noexcept = default;
 
-  Slice(const T* s, size_t size) : repr(Repr{s, size}) {}
+  Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
 
   Slice &operator=(Slice<T> other) noexcept {
     this->repr = other.repr;
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index 56d37b3..a0c348b 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -1,6 +1,6 @@
 use std::mem;
-use std::slice;
 use std::ptr::NonNull;
+use std::slice;
 
 // Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
 #[repr(C)]
diff --git a/syntax/impls.rs b/syntax/impls.rs
index b040753..d3c4b0f 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -114,10 +114,7 @@ impl Eq for Slice {}
 
 impl PartialEq for Slice {
     fn eq(&self, other: &Slice) -> bool {
-        let Slice {
-            bracket: _,
-            inner,
-        } = self;
+        let Slice { bracket: _, inner } = self;
         let Slice {
             bracket: _,
             inner: inner2,
@@ -128,10 +125,7 @@ impl PartialEq for Slice {
 
 impl Hash for Slice {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        let Slice {
-            bracket: _,
-            inner,
-        } = self;
+        let Slice { bracket: _, inner } = self;
         inner.hash(state);
     }
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 6156a69..95dd67c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -230,14 +230,12 @@ fn parse_type(ty: &RustType) -> Result<Type> {
 fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
-        Type::Ident(ident) if ident == "u8" => {
-            Type::Slice
-        },
-        _ => return Err(Error::new_spanned(ty, "unsupported type"))
+        Type::Ident(ident) if ident == "u8" => Type::Slice,
+        _ => return Err(Error::new_spanned(ty, "unsupported type")),
     };
     Ok(which(Box::new(Slice {
         bracket: ty.bracket_token,
-        inner
+        inner,
     })))
 }
 
@@ -251,14 +249,10 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
                 Type::Str
             }
         }
-        Type::Slice(inner2) => {
-            match &inner2.inner {
-                Type::Ident(ident) if ident == "u8" => {
-                    Type::SliceRefU8
-                }
-                _ => return Err(Error::new_spanned(ty, "unsupported type"))
-            }
-        }
+        Type::Slice(inner2) => match &inner2.inner {
+            Type::Ident(ident) if ident == "u8" => Type::SliceRefU8,
+            _ => return Err(Error::new_spanned(ty, "unsupported type")),
+        },
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index bf5e76d..8b89ae8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -9,7 +9,7 @@ extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
 
 namespace tests {
 
-const char* SLICE_DATA = "2020";
+const char *SLICE_DATA = "2020";
 
 C::C(size_t n) : n(n) {}
 
@@ -34,9 +34,9 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
-rust::Slice<uint8_t> c_return_sliceu8(const Shared& shared) {
+rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared) {
   (void)shared;
-  return rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5);
+  return rust::Slice<uint8_t>((const unsigned char *)SLICE_DATA, 5);
 }
 
 rust::String c_return_rust_string() { return "2020"; }
@@ -88,7 +88,7 @@ void c_take_str(rust::Str s) {
 }
 
 void c_take_sliceu8(rust::Slice<uint8_t> s) {
-  if (std::string((const char*)s.data(), s.size()) == "2020") {
+  if (std::string((const char *)s.data(), s.size()) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
@@ -161,7 +161,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<uint8_t>((const unsigned char*)SLICE_DATA, 5));
+  r_take_sliceu8(rust::Slice<uint8_t>((const unsigned char *)SLICE_DATA, 5));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));

From efe81052e75d3d401d3708e403a3d569c5c4df5b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 272/2232] Touch up &[u8] PR


---

diff --git a/README.md b/README.md
index ad14b57..f51a1ac 100644
--- a/README.md
+++ b/README.md
@@ -299,7 +299,7 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td>(no other slice types currently supported)</td></tr>
+<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/include/cxx.h b/include/cxx.h
index e63790b..cf79cfb 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -16,43 +16,6 @@ inline namespace cxxbridge02 {
 
 struct unsafe_bitcopy_t;
 
-#ifndef CXXBRIDGE02_RUST_SLICE
-#define CXXBRIDGE02_RUST_SLICE
-template <typename T>
-class Slice final {
-public:
-  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
-  Slice(const Slice<T> &) noexcept = default;
-
-  Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
-
-  Slice &operator=(Slice<T> other) noexcept {
-    this->repr = other.repr;
-    return *this;
-  }
-
-  const T *data() const noexcept { return this->repr.ptr; }
-  size_t size() const noexcept { return this->repr.len; }
-  size_t length() const noexcept { return this->repr.len; }
-
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
-  // At present this class is only used for &[u8] slices.
-  // Not necessarily ABI compatible with &[u8]. Codegen will translate to
-  // cxx::rust_slice_u8::RustSlice which matches this layout.
-  struct Repr {
-    const T *ptr;
-    size_t len;
-  };
-  Slice(Repr repr_) noexcept : repr(repr_) {}
-  explicit operator Repr() noexcept { return this->repr; }
-
-private:
-  Repr repr;
-};
-
-#endif // CXXBRIDGE02_RUST_SLICE
-
 #ifndef CXXBRIDGE02_RUST_STRING
 #define CXXBRIDGE02_RUST_STRING
 class String final {
@@ -120,6 +83,42 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_STR
 
+#ifndef CXXBRIDGE02_RUST_SLICE
+#define CXXBRIDGE02_RUST_SLICE
+template <typename T>
+class Slice final {
+public:
+  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+  Slice(const Slice<T> &) noexcept = default;
+
+  Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
+
+  Slice &operator=(Slice<T> other) noexcept {
+    this->repr = other.repr;
+    return *this;
+  }
+
+  const T *data() const noexcept { return this->repr.ptr; }
+  size_t size() const noexcept { return this->repr.len; }
+  size_t length() const noexcept { return this->repr.len; }
+
+  // Repr is PRIVATE; must not be used other than by our generated code.
+  //
+  // At present this class is only used for &[u8] slices.
+  // Not necessarily ABI compatible with &[u8]. Codegen will translate to
+  // cxx::rust_slice_u8::RustSlice which matches this layout.
+  struct Repr {
+    const T *ptr;
+    size_t len;
+  };
+  Slice(Repr repr_) noexcept : repr(repr_) {}
+  explicit operator Repr() noexcept { return this->repr; }
+
+private:
+  Repr repr;
+};
+#endif // CXXBRIDGE02_RUST_SLICE
+
 #ifndef CXXBRIDGE02_RUST_BOX
 #define CXXBRIDGE02_RUST_BOX
 template <typename T>
diff --git a/src/lib.rs b/src/lib.rs
index 1ceef52..6348cf4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -307,6 +307,7 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
+//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -324,7 +325,6 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th></tr>
-//! <tr><td>&amp;[T]</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index adcd4fc..8afa841 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -166,7 +166,7 @@ fn r_take_rust_string(s: String) {
 
 fn r_take_sliceu8(s: &[u8]) {
     assert_eq!(s.len(), 5);
-    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\u{0}");
+    assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
 }
 
 fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {

From e710af1dd78575894621dcf628ba3ca9763e318f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 273/2232] Fix typo in Slice repr comment


---

diff --git a/include/cxx.h b/include/cxx.h
index cf79cfb..637372a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -106,7 +106,7 @@ public:
   //
   // At present this class is only used for &[u8] slices.
   // Not necessarily ABI compatible with &[u8]. Codegen will translate to
-  // cxx::rust_slice_u8::RustSlice which matches this layout.
+  // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
   struct Repr {
     const T *ptr;
     size_t len;

From eebe9b7289d1b01da10fbb4ea5e698bddb9c4ce1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 274/2232] Improve type checking and error messages for slice type


---

diff --git a/syntax/check.rs b/syntax/check.rs
index c71295e..181c530 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Struct, Ty1, Type, Types};
+use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Slice, Struct, Ty1, Type, Types};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
@@ -29,6 +29,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
         }
     }
@@ -107,6 +108,10 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     cx.error(ty, "unsupported reference type");
 }
 
+fn check_type_slice(cx: &mut Check, ty: &Slice) {
+    cx.error(ty, "only &[u8] is supported so far, not other slice types");
+}
+
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
@@ -201,7 +206,7 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
-        Type::Void(_) => return true,
+        Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 95dd67c..6e5b36e 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
     Struct, Ty1, Type, Var,
@@ -220,25 +221,13 @@ fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
         RustType::Path(ty) => parse_type_path(ty),
+        RustType::Slice(ty) => parse_type_slice(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
-        RustType::Slice(ty) => parse_type_slice(ty),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
-    let which = match &inner {
-        Type::Ident(ident) if ident == "u8" => Type::Slice,
-        _ => return Err(Error::new_spanned(ty, "unsupported type")),
-    };
-    Ok(which(Box::new(Slice {
-        bracket: ty.bracket_token,
-        inner,
-    })))
-}
-
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
@@ -249,9 +238,9 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
                 Type::Str
             }
         }
-        Type::Slice(inner2) => match &inner2.inner {
-            Type::Ident(ident) if ident == "u8" => Type::SliceRefU8,
-            _ => return Err(Error::new_spanned(ty, "unsupported type")),
+        Type::Slice(slice) => match &slice.inner {
+            Type::Ident(ident) if ident == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            _ => Type::Ref,
         },
         _ => Type::Ref,
     };
@@ -298,6 +287,14 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
+    Ok(Type::Slice(Box::new(Slice {
+        bracket: ty.bracket_token,
+        inner,
+    })))
+}
+
 fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(

From 4770b4783b6ec408a6d1b97bf5c685b1874fa038 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 275/2232] Include the right headers when using a slice


---

diff --git a/gen/write.rs b/gen/write.rs
index f930d52..322ca08 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -100,6 +100,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
+            Type::SliceRefU8(_) => out.include.cstdint = true,
             _ => {}
         }
     }
@@ -108,6 +109,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
 fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_string = false;
     let mut needs_rust_str = false;
+    let mut needs_rust_slice = false;
     let mut needs_rust_box = false;
     let mut needs_rust_fn = false;
     let mut needs_rust_isize = false;
@@ -125,6 +127,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Type::Fn(_) => {
                 needs_rust_fn = true;
             }
+            Type::Slice(_) | Type::SliceRefU8(_) => {
+                needs_rust_slice = true;
+            }
             ty if ty == Isize => {
                 out.include.base_tsd = true;
                 needs_rust_isize = true;
@@ -183,6 +188,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 
     if needs_rust_string
         || needs_rust_str
+        || needs_rust_slice
         || needs_rust_box
         || needs_rust_fn
         || needs_rust_error
@@ -202,6 +208,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 
     write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
+    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");

From 633b1f5f1f65f730885e358f5063a8b589ebdb71 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:42:06 +0000
Subject: [PATCH 276/2232] Switch C-style casting to reinterpret_casts


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8b89ae8..d72bfd0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -36,7 +36,7 @@ rust::Str c_return_str(const Shared &shared) {
 
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared) {
   (void)shared;
-  return rust::Slice<uint8_t>((const unsigned char *)SLICE_DATA, 5);
+  return rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA), 5);
 }
 
 rust::String c_return_rust_string() { return "2020"; }
@@ -88,7 +88,8 @@ void c_take_str(rust::Str s) {
 }
 
 void c_take_sliceu8(rust::Slice<uint8_t> s) {
-  if (std::string((const char *)s.data(), s.size()) == "2020") {
+  if (std::string(reinterpret_cast<const char *>(s.data()), s.size()) ==
+      "2020") {
     cxx_test_suite_set_correct();
   }
 }
@@ -161,7 +162,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<uint8_t>((const unsigned char *)SLICE_DATA, 5));
+  r_take_sliceu8(
+      rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA), 5));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));

From 4272d98530c9813d36c26ea626efc20a75d1055b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 14 2020 23:57:00 +0000
Subject: [PATCH 277/2232] Release 0.2.9


---

diff --git a/Cargo.toml b/Cargo.toml
index 044095b..f9d9b52 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.8" # remember to update html_root_url
+version = "0.2.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.8", path = "macro" }
+cxxbridge-macro = { version = "=0.2.9", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 4a4cde2..7c0739b 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.8"
+version = "0.2.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index c85062f..386c9dd 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.8"
+version = "0.2.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 6348cf4..609db59 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.8")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.9")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index fce3ce0..71ad826 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.8"
+version = "0.2.9"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.8"
+version = "0.2.9"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.8"
+version = "0.2.9"
 dependencies = [
  "cxx",
  "proc-macro2",

From 3d4f612b348607bb19d0f2013e383485eb18bb2c Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 16 2020 23:24:48 +0000
Subject: [PATCH 278/2232] Support calling C++ methods from Rust


These methods can be declared in the bridge by naming the first
argument self and making it a reference to the containing class, e.g.,
  fn get(self: &C) -> usize;
  fn set(self: &mut C, n: usize);
This syntax requires Rust 1.43.

Note that the implementation also changes the internal naming of shim
functions so that they also contain the name of the owning class, if
any.  This allows defining multiple methods with the same name on
different objects.

---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..6fc2465 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,12 +9,15 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
+const std::string &ThingC::get_name() const {
+  std::cout << "I'm a C++ method!" << std::endl;
+  return this->appname;
+}
+
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
 void do_thing(SharedThing state) { print_r(*state.y); }
 
 } // namespace example
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index fafc474..885293f 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -12,12 +12,13 @@ public:
   ~ThingC();
 
   std::string appname;
+
+  const std::string &get_name() const;
 };
 
 struct SharedThing;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
 } // namespace example
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 66dfc79..759bbe1 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -11,8 +11,9 @@ mod ffi {
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
+        fn get_name(self: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
+
     }
 
     extern "Rust" {
@@ -29,7 +30,7 @@ fn print_r(r: &ThingR) {
 
 fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
+    println!("this is a {}", x.as_ref().unwrap().get_name());
 
     ffi::do_thing(ffi::SharedThing {
         z: 222,
diff --git a/gen/write.rs b/gen/write.rs
index 322ca08..41b5b37 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@ use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Signature, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, Receiver, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -327,8 +327,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write_extern_return_type_space(out, &efn.ret, types);
     }
     write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
+    if let Some(base) = &efn.receiver {
+        write!(out, "{} *__receiver$", base.ident);
+    }
     for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
+        if i > 0 || efn.receiver.is_some() {
             write!(out, ", ");
         }
         if arg.ty == RustString {
@@ -347,14 +350,27 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     writeln!(out, ") noexcept {{");
     write!(out, "  ");
     write_return_type(out, &efn.ret);
-    write!(out, "(*{}$)(", efn.ident);
+    match &efn.receiver {
+        None => write!(out, "(*{}$)(", efn.ident),
+        Some(base) => write!(out, "({}::*{}$)(", base.ident, efn.ident),
+    }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
         write_type(out, &arg.ty);
     }
-    writeln!(out, ") = {};", efn.ident);
+    write!(out, ")");
+    match &efn.receiver {
+        Some(Receiver { mutability: None, ident: _ }) => write!(out, " const"),
+        _ => {},
+    }
+    write!(out, " = ");
+    match &efn.receiver {
+        None => write!(out, "{}", efn.ident),
+        Some(base) => write!(out, "&{}::{}", base.ident, efn.ident),
+    }
+    writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
@@ -377,7 +393,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         _ => {}
     }
-    write!(out, "{}$(", efn.ident);
+    match &efn.receiver {
+        None => write!(out, "{}$(", efn.ident),
+        Some(_) => write!(out, "(__receiver$->*{}$)(", efn.ident),
+    }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 146d21b..998b47e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -123,6 +123,13 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
+    let receiver = efn.receiver.iter().map(|base| {
+        let ident = &base.ident;
+        match base.mutability {
+            None => quote!(_: &#ident),
+            Some(_) => quote!(_: &mut #ident),
+        }
+    });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -136,6 +143,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
             quote!(#ident: #ty)
         }
     });
+    let all_args = receiver.chain(args);
     let ret = if efn.throws {
         quote!(-> ::cxx::private::Result)
     } else {
@@ -150,7 +158,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
-        fn #local_name(#(#args,)* #outparam) #ret;
+        fn #local_name(#(#all_args,)* #outparam) #ret;
     }
 }
 
@@ -158,7 +166,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
-    let args = &efn.args;
+    let receiver = efn.receiver.iter().map(|base| match base.mutability {
+        None => quote!(&self),
+        Some(_) => quote!(&mut self),
+    });
+    let args = efn.args.iter().map(|arg| quote!(#arg));
+    let all_args = receiver.chain(args);
     let ret = if efn.throws {
         let ok = match &efn.ret {
             Some(ret) => quote!(#ret),
@@ -169,7 +182,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         expand_return_type(&efn.ret)
     };
     let indirect_return = indirect_return(efn, types);
-    let vars = efn.args.iter().map(|arg| {
+    let receiver_var = efn.receiver.iter().map(|_| quote!(self));
+    let arg_vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
             Type::Ident(ident) if ident == RustString => {
@@ -189,6 +203,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             _ => quote!(#var),
         }
     });
+    let vars = receiver_var.chain(arg_vars);
     let trampolines = efn
         .args
         .iter()
@@ -274,18 +289,36 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     }
     .unwrap_or(call);
-    quote! {
-        #doc
-        pub fn #ident(#args) #ret {
-            extern "C" {
-                #decl
+    let receiver_ident = efn.receiver.as_ref().map(|base| &base.ident);
+    match receiver_ident {
+        None => quote! {
+            #doc
+            pub fn #ident(#(#all_args,)*) #ret {
+                extern "C" {
+                    #decl
+                }
+                #trampolines
+                unsafe {
+                    #setup
+                    #expr
+                }
             }
-            #trampolines
-            unsafe {
-                #setup
-                #expr
+        },
+        Some(base_ident) => quote! {
+            #doc
+            impl #base_ident {
+                pub fn #ident(#(#all_args,)*) #ret {
+                    extern "C" {
+                        #decl
+                    }
+                    #trampolines
+                    unsafe {
+                        #setup
+                        #expr
+                    }
+                }
             }
-        }
+        },
     }
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index 181c530..3b6937a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -195,6 +195,10 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
         }
     }
 
+    if efn.receiver.is_some() {
+        reference_args += 1;
+    }
+
     if reference_args != 1 {
         cx.error(
             efn,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 8afa841..a720a80 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -49,6 +49,9 @@ pub mod ffi {
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
+
+        fn get(self: &C) -> usize;
+        fn set(self: &mut C, n: usize) -> usize;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d72bfd0..2daae53 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -15,6 +15,11 @@ C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
 
+size_t C::set(size_t n) {
+  this->n = n;
+  return this->n;
+}
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index a68be5c..43ac229 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -12,6 +12,7 @@ class C {
 public:
   C(size_t n);
   size_t get() const;
+  size_t set(size_t n);
 
 private:
   size_t n;
diff --git a/tests/test.rs b/tests/test.rs
index 511c52b..36de8f9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -107,6 +107,18 @@ fn test_c_call_r() {
     check!(cxx_run_test());
 }
 
+#[test]
+fn test_c_method_calls() {
+    let mut unique_ptr = ffi::c_return_unique_ptr();
+
+    let old_value = unique_ptr.as_ref().unwrap().get();
+    assert_eq!(2020, old_value);
+    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
+    assert_eq!(2021, unique_ptr.as_ref().unwrap().get());
+    assert_eq!(old_value, unique_ptr.as_mut().unwrap().set(old_value));
+    assert_eq!(old_value, unique_ptr.as_ref().unwrap().get())
+}
+
 #[no_mangle]
 extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
     Box::into_raw(Box::new(2020usize))

From c1c4e7ac6b92ad33f134882f848a6ad034ef3de2 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 16 2020 23:25:04 +0000
Subject: [PATCH 279/2232] Support calling Rust methods from C++


These methods can be declared in the bridge by naming the first
argument self and making it a reference to the containing class, e.g.,
  fn get(self: &R) -> usize;
  fn set(self: &mut R, n: usize);
This syntax requires Rust 1.43.

---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 6fc2465..bc0d976 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -18,7 +18,10 @@ std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
-void do_thing(SharedThing state) { print_r(*state.y); }
+void do_thing(SharedThing state) {
+  print_r(*state.y);
+  state.y->print();
+}
 
 } // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 759bbe1..713a1d1 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -19,6 +19,7 @@ mod ffi {
     extern "Rust" {
         type ThingR;
         fn print_r(r: &ThingR);
+        fn print(self: &ThingR);
     }
 }
 
@@ -28,6 +29,12 @@ fn print_r(r: &ThingR) {
     println!("called back with r={}", r.0);
 }
 
+impl ThingR {
+    fn print(&self) {
+        println!("method called back with r={}", self.0);
+    }
+}
+
 fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
     println!("this is a {}", x.as_ref().unwrap().get_name());
diff --git a/gen/write.rs b/gen/write.rs
index 41b5b37..7e1caac 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,7 @@ use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Receiver, Signature, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -45,9 +45,25 @@ pub(super) fn gen(
     }
 
     for api in apis {
-        if let Api::Struct(strct) = api {
-            out.next_section();
-            write_struct(out, strct);
+        match api {
+            Api::Struct(strct) => {
+                out.next_section();
+                write_struct(out, strct);
+            }
+            Api::RustType(ety) => {
+                let methods = apis.iter().filter_map(|api| match api {
+                    Api::RustFunction(efn) => match &efn.sig.receiver {
+                        Some(rcvr) if rcvr.ident == ety.ident => Some(efn),
+                        _ => None,
+                    },
+                    _ => None,
+                }).collect::<Vec<_>>();
+                if !methods.is_empty() {
+                    out.next_section();
+                    write_struct_with_methods(out, ety, methods);
+                }
+            }
+            _ => {}
         }
     }
 
@@ -300,6 +316,21 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: Vec<&ExternFn>) {
+    for line in ety.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", ety.ident);
+    for method in &methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, None, false);
+        writeln!(out, ";");
+    }
+    writeln!(out, "}};");
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
@@ -326,7 +357,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    write!(out, "{}cxxbridge02${}${}(", out.namespace, receiver_type, efn.ident);
     if let Some(base) = &efn.receiver {
         write!(out, "{} *__receiver$", base.ident);
     }
@@ -471,7 +506,11 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let link_name = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -490,6 +529,10 @@ fn write_rust_function_decl_impl(
     }
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
+    if let Some(base) = &sig.receiver {
+        write!(out, "{} &__receiver$", base.ident);
+        needs_comma = true;
+    }
     for arg in &sig.args {
         if needs_comma {
             write!(out, ", ");
@@ -519,20 +562,26 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = efn.ident.to_string();
-    let invoke = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let invoke = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
 
-fn write_rust_function_shim_impl(
+fn write_rust_function_shim_decl(
     out: &mut OutFile,
     local_name: &str,
     sig: &Signature,
-    types: &Types,
-    invoke: &str,
+    receiver: Option<&Receiver>,
     indirect_call: bool,
 ) {
     write_return_type(out, &sig.ret);
+    if let Some(base) = receiver {
+        write!(out, "{}::", base.ident);
+    }
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
@@ -551,6 +600,21 @@ fn write_rust_function_shim_impl(
     if !sig.throws {
         write!(out, " noexcept");
     }
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &str,
+    indirect_call: bool,
+) {
+    if out.header && sig.receiver.is_some() {
+        // We've already defined this inside the struct.
+        return;
+    }
+    write_rust_function_shim_decl(out, local_name, sig, sig.receiver.as_ref(), indirect_call);
     if out.header {
         writeln!(out, ";");
     } else {
@@ -589,8 +653,11 @@ fn write_rust_function_shim_impl(
             write!(out, "::rust::Str::Repr error$ = ");
         }
         write!(out, "{}(", invoke);
+        if let Some(_) = &sig.receiver {
+            write!(out, "*this");
+        }
         for (i, arg) in sig.args.iter().enumerate() {
-            if i > 0 {
+            if i > 0 || sig.receiver.is_some() {
                 write!(out, ", ");
             }
             match &arg.ty {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 998b47e..2d3166a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -154,7 +154,11 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
@@ -366,7 +370,11 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     let invoke = Some(ident);
@@ -388,6 +396,13 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
+    let receiver = sig.receiver.iter().map(|base| {
+        let ident = &base.ident;
+        match base.mutability {
+            None => quote!(__receiver: &#ident),
+            Some(_) => quote!(__receiver: &mut #ident),
+        }
+    });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -397,6 +412,7 @@ fn expand_rust_function_shim_impl(
             quote!(#ident: #ty)
         }
     });
+    let all_args = receiver.chain(args);
 
     let vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
@@ -418,7 +434,10 @@ fn expand_rust_function_shim_impl(
     });
 
     let mut call = match invoke {
-        Some(ident) => quote!(super::#ident),
+        Some(ident) => match sig.receiver {
+            None => quote!(super::#ident),
+            Some(_) => quote!(__receiver.#ident),
+        },
         None => quote!(__extern),
     };
     call.extend(quote! { (#(#vars),*) });
@@ -476,7 +495,7 @@ fn expand_rust_function_shim_impl(
     quote! {
         #[doc(hidden)]
         #[export_name = #link_name]
-        unsafe extern "C" fn #local_name(#(#args,)* #outparam #pointer) #ret {
+        unsafe extern "C" fn #local_name(#(#all_args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
             #expr
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index a720a80..4da5740 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -56,6 +56,7 @@ pub mod ffi {
 
     extern "Rust" {
         type R;
+        type R2;
 
         fn r_return_primitive() -> usize;
         fn r_return_shared() -> Shared;
@@ -80,11 +81,28 @@ pub mod ffi {
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
         fn r_fail_return_primitive() -> Result<usize>;
+
+        fn r_return_r2(n: usize) -> Box<R2>;
+        fn get(self: &R2) -> usize;
+        fn set(self: &mut R2, n: usize) -> usize;
     }
 }
 
 pub type R = usize;
 
+pub struct R2(usize);
+
+impl R2 {
+    fn get(&self) -> usize {
+        self.0
+    }
+
+    fn set(&mut self, n: usize) -> usize {
+        self.0 = n;
+        n
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
@@ -187,3 +205,7 @@ fn r_try_return_primitive() -> Result<usize, Error> {
 fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }
+
+fn r_return_r2(n: usize) -> Box<R2> {
+    Box::new(R2(n))
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2daae53..8893ee8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -181,6 +181,13 @@ extern "C" const char *cxx_run_test() noexcept {
     ASSERT(std::strcmp(e.what(), "rust error") == 0);
   }
 
+  auto r2 = r_return_r2(2020);
+  ASSERT(r2->get() == 2020);
+  ASSERT(r2->set(2021) == 2021);
+  ASSERT(r2->get() == 2021);
+  ASSERT(r2->set(2020) == 2020);
+  ASSERT(r2->get() == 2020);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 968738f12741b34fd9b6b4e8888bd576ca46cd92 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 16 2020 23:25:04 +0000
Subject: [PATCH 280/2232] Optimize the computation of the methods of a struct


---

diff --git a/Cargo.toml b/Cargo.toml
index f9d9b52..eff5820 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.9", path = "macro" }
+itertools = "0.9"
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/gen/write.rs b/gen/write.rs
index 7e1caac..21fbc8c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -3,6 +3,7 @@ use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
+use itertools::Itertools;
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -44,6 +45,14 @@ pub(super) fn gen(
         }
     }
 
+    let methods_for_type = apis.iter().filter_map(|api| match api {
+        Api::RustFunction(efn) => match &efn.sig.receiver {
+            Some(rcvr) => Some((&rcvr.ident, efn)),
+            _ => None,
+        },
+        _ => None,
+    }).into_group_map();
+
     for api in apis {
         match api {
             Api::Struct(strct) => {
@@ -51,16 +60,12 @@ pub(super) fn gen(
                 write_struct(out, strct);
             }
             Api::RustType(ety) => {
-                let methods = apis.iter().filter_map(|api| match api {
-                    Api::RustFunction(efn) => match &efn.sig.receiver {
-                        Some(rcvr) if rcvr.ident == ety.ident => Some(efn),
-                        _ => None,
+                match methods_for_type.get(&ety.ident) {
+                    Some(methods) => {
+                        out.next_section();
+                        write_struct_with_methods(out, ety, methods);
                     },
-                    _ => None,
-                }).collect::<Vec<_>>();
-                if !methods.is_empty() {
-                    out.next_section();
-                    write_struct_with_methods(out, ety, methods);
+                    _ => {}
                 }
             }
             _ => {}
@@ -316,12 +321,12 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: Vec<&ExternFn>) {
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &Vec<&ExternFn>) {
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
     writeln!(out, "struct {} final {{", ety.ident);
-    for method in &methods {
+    for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
         let local_name = method.ident.to_string();

From f937996fc7c3b4ff9694c1afb36ea0901284e65c Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 16 2020 23:25:04 +0000
Subject: [PATCH 281/2232] Update documentation


---

diff --git a/README.md b/README.md
index f51a1ac..3f7399a 100644
--- a/README.md
+++ b/README.md
@@ -84,8 +84,10 @@ mod ffi {
 
         // Functions implemented in C++.
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
+
+        // Methods implemented in C++.
+        fn get_name(self: &ThingC) -> &CxxString;
     }
 
     extern "Rust" {
@@ -95,6 +97,9 @@ mod ffi {
 
         // Functions implemented in Rust.
         fn print_r(r: &ThingR);
+
+        // Methods implemented in Rust.
+        fn print(self: &ThingR);
     }
 }
 ```
@@ -335,8 +340,6 @@ This is still early days for CXX; I am releasing it as a minimum viable product
 to collect feedback on the direction and invite collaborators. Here are some of
 the facets that I still intend for this project to tackle:
 
-- [ ] Support associated methods: `extern "Rust" { fn f(self: &Struct); }`
-- [ ] Support C++ member functions
 - [ ] Support structs with type parameters
 - [ ] Support async functions
 
diff --git a/src/lib.rs b/src/lib.rs
index 609db59..780a26e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -79,8 +79,10 @@
 //!
 //!         // Functions implemented in C++.
 //!         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-//!         fn get_name(thing: &ThingC) -> &CxxString;
 //!         fn do_thing(state: SharedThing);
+//!
+//!         // Methods implemented in C++.
+//!         fn get_name(self: &ThingC) -> &CxxString;
 //!     }
 //!
 //!     extern "Rust" {
@@ -90,6 +92,9 @@
 //!
 //!         // Functions implemented in Rust.
 //!         fn print_r(r: &ThingR);
+//!
+//!         // Methods implemented in Rust.
+//!         fn print(self: &ThingR);
 //!     }
 //! }
 //! #
@@ -99,6 +104,12 @@
 //! #     println!("called back with r={}", r.0);
 //! # }
 //! #
+//! # impl ThingR {
+//! #     fn print(&self) {
+//! #         println!("method called back with r={}", self.0);
+//! #     }
+//! # }
+//! #
 //! # fn main() {}
 //! ```
 //!

From 187588eeacea37574d98e892d824776dce86867b Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 17 2020 23:19:54 +0000
Subject: [PATCH 282/2232] Mark default and copy constructors as deleted.


---

diff --git a/gen/write.rs b/gen/write.rs
index 21fbc8c..b8d17df 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -326,6 +326,8 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &Vec<
         writeln!(out, "//{}", line);
     }
     writeln!(out, "struct {} final {{", ety.ident);
+    writeln!(out, "  {}() = delete;", ety.ident);
+    writeln!(out, "  {}(const {}&) = delete;", ety.ident, ety.ident);
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;

From af74d661de1960843091514b2206d8bf1deeea82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:43:51 +0000
Subject: [PATCH 283/2232] Merge pull request #121 from jgalenson/methods


Support calling C++ and Rust methods
---

diff --git a/Cargo.toml b/Cargo.toml
index f9d9b52..eff5820 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.9", path = "macro" }
+itertools = "0.9"
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/README.md b/README.md
index f51a1ac..3f7399a 100644
--- a/README.md
+++ b/README.md
@@ -84,8 +84,10 @@ mod ffi {
 
         // Functions implemented in C++.
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
+
+        // Methods implemented in C++.
+        fn get_name(self: &ThingC) -> &CxxString;
     }
 
     extern "Rust" {
@@ -95,6 +97,9 @@ mod ffi {
 
         // Functions implemented in Rust.
         fn print_r(r: &ThingR);
+
+        // Methods implemented in Rust.
+        fn print(self: &ThingR);
     }
 }
 ```
@@ -335,8 +340,6 @@ This is still early days for CXX; I am releasing it as a minimum viable product
 to collect feedback on the direction and invite collaborators. Here are some of
 the facets that I still intend for this project to tackle:
 
-- [ ] Support associated methods: `extern "Rust" { fn f(self: &Struct); }`
-- [ ] Support C++ member functions
 - [ ] Support structs with type parameters
 - [ ] Support async functions
 
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..bc0d976 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,13 +9,19 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
+const std::string &ThingC::get_name() const {
+  std::cout << "I'm a C++ method!" << std::endl;
+  return this->appname;
+}
+
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
-void do_thing(SharedThing state) { print_r(*state.y); }
+void do_thing(SharedThing state) {
+  print_r(*state.y);
+  state.y->print();
+}
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index fafc474..885293f 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -12,12 +12,13 @@ public:
   ~ThingC();
 
   std::string appname;
+
+  const std::string &get_name() const;
 };
 
 struct SharedThing;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
 } // namespace example
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 66dfc79..713a1d1 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -11,13 +11,15 @@ mod ffi {
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
+        fn get_name(self: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
+
     }
 
     extern "Rust" {
         type ThingR;
         fn print_r(r: &ThingR);
+        fn print(self: &ThingR);
     }
 }
 
@@ -27,9 +29,15 @@ fn print_r(r: &ThingR) {
     println!("called back with r={}", r.0);
 }
 
+impl ThingR {
+    fn print(&self) {
+        println!("method called back with r={}", self.0);
+    }
+}
+
 fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
+    println!("this is a {}", x.as_ref().unwrap().get_name());
 
     ffi::do_thing(ffi::SharedThing {
         z: 222,
diff --git a/gen/write.rs b/gen/write.rs
index 322ca08..b8d17df 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,8 @@ use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{Api, ExternFn, Signature, Struct, Type, Types, Var};
+use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
+use itertools::Itertools;
 use proc_macro2::Ident;
 
 pub(super) fn gen(
@@ -44,10 +45,30 @@ pub(super) fn gen(
         }
     }
 
+    let methods_for_type = apis.iter().filter_map(|api| match api {
+        Api::RustFunction(efn) => match &efn.sig.receiver {
+            Some(rcvr) => Some((&rcvr.ident, efn)),
+            _ => None,
+        },
+        _ => None,
+    }).into_group_map();
+
     for api in apis {
-        if let Api::Struct(strct) = api {
-            out.next_section();
-            write_struct(out, strct);
+        match api {
+            Api::Struct(strct) => {
+                out.next_section();
+                write_struct(out, strct);
+            }
+            Api::RustType(ety) => {
+                match methods_for_type.get(&ety.ident) {
+                    Some(methods) => {
+                        out.next_section();
+                        write_struct_with_methods(out, ety, methods);
+                    },
+                    _ => {}
+                }
+            }
+            _ => {}
         }
     }
 
@@ -300,6 +321,23 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &Vec<&ExternFn>) {
+    for line in ety.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", ety.ident);
+    writeln!(out, "  {}() = delete;", ety.ident);
+    writeln!(out, "  {}(const {}&) = delete;", ety.ident, ety.ident);
+    for method in methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, None, false);
+        writeln!(out, ";");
+    }
+    writeln!(out, "}};");
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
@@ -326,9 +364,16 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    write!(out, "{}cxxbridge02${}(", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    write!(out, "{}cxxbridge02${}${}(", out.namespace, receiver_type, efn.ident);
+    if let Some(base) = &efn.receiver {
+        write!(out, "{} *__receiver$", base.ident);
+    }
     for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
+        if i > 0 || efn.receiver.is_some() {
             write!(out, ", ");
         }
         if arg.ty == RustString {
@@ -347,14 +392,27 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     writeln!(out, ") noexcept {{");
     write!(out, "  ");
     write_return_type(out, &efn.ret);
-    write!(out, "(*{}$)(", efn.ident);
+    match &efn.receiver {
+        None => write!(out, "(*{}$)(", efn.ident),
+        Some(base) => write!(out, "({}::*{}$)(", base.ident, efn.ident),
+    }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
         write_type(out, &arg.ty);
     }
-    writeln!(out, ") = {};", efn.ident);
+    write!(out, ")");
+    match &efn.receiver {
+        Some(Receiver { mutability: None, ident: _ }) => write!(out, " const"),
+        _ => {},
+    }
+    write!(out, " = ");
+    match &efn.receiver {
+        None => write!(out, "{}", efn.ident),
+        Some(base) => write!(out, "&{}::{}", base.ident, efn.ident),
+    }
+    writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
         writeln!(out, "::rust::Str::Repr throw$;");
@@ -377,7 +435,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         _ => {}
     }
-    write!(out, "{}$(", efn.ident);
+    match &efn.receiver {
+        None => write!(out, "{}$(", efn.ident),
+        Some(_) => write!(out, "(__receiver$->*{}$)(", efn.ident),
+    }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
@@ -452,7 +513,11 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let link_name = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -471,6 +536,10 @@ fn write_rust_function_decl_impl(
     }
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
+    if let Some(base) = &sig.receiver {
+        write!(out, "{} &__receiver$", base.ident);
+        needs_comma = true;
+    }
     for arg in &sig.args {
         if needs_comma {
             write!(out, ", ");
@@ -500,20 +569,26 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = efn.ident.to_string();
-    let invoke = format!("{}cxxbridge02${}", out.namespace, efn.ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let invoke = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
 
-fn write_rust_function_shim_impl(
+fn write_rust_function_shim_decl(
     out: &mut OutFile,
     local_name: &str,
     sig: &Signature,
-    types: &Types,
-    invoke: &str,
+    receiver: Option<&Receiver>,
     indirect_call: bool,
 ) {
     write_return_type(out, &sig.ret);
+    if let Some(base) = receiver {
+        write!(out, "{}::", base.ident);
+    }
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
@@ -532,6 +607,21 @@ fn write_rust_function_shim_impl(
     if !sig.throws {
         write!(out, " noexcept");
     }
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &str,
+    indirect_call: bool,
+) {
+    if out.header && sig.receiver.is_some() {
+        // We've already defined this inside the struct.
+        return;
+    }
+    write_rust_function_shim_decl(out, local_name, sig, sig.receiver.as_ref(), indirect_call);
     if out.header {
         writeln!(out, ";");
     } else {
@@ -570,8 +660,11 @@ fn write_rust_function_shim_impl(
             write!(out, "::rust::Str::Repr error$ = ");
         }
         write!(out, "{}(", invoke);
+        if let Some(_) = &sig.receiver {
+            write!(out, "*this");
+        }
         for (i, arg) in sig.args.iter().enumerate() {
-            if i > 0 {
+            if i > 0 || sig.receiver.is_some() {
                 write!(out, ", ");
             }
             match &arg.ty {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 146d21b..2d3166a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -123,6 +123,13 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
+    let receiver = efn.receiver.iter().map(|base| {
+        let ident = &base.ident;
+        match base.mutability {
+            None => quote!(_: &#ident),
+            Some(_) => quote!(_: &mut #ident),
+        }
+    });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -136,6 +143,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
             quote!(#ident: #ty)
         }
     });
+    let all_args = receiver.chain(args);
     let ret = if efn.throws {
         quote!(-> ::cxx::private::Result)
     } else {
@@ -146,11 +154,15 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
-        fn #local_name(#(#args,)* #outparam) #ret;
+        fn #local_name(#(#all_args,)* #outparam) #ret;
     }
 }
 
@@ -158,7 +170,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
-    let args = &efn.args;
+    let receiver = efn.receiver.iter().map(|base| match base.mutability {
+        None => quote!(&self),
+        Some(_) => quote!(&mut self),
+    });
+    let args = efn.args.iter().map(|arg| quote!(#arg));
+    let all_args = receiver.chain(args);
     let ret = if efn.throws {
         let ok = match &efn.ret {
             Some(ret) => quote!(#ret),
@@ -169,7 +186,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         expand_return_type(&efn.ret)
     };
     let indirect_return = indirect_return(efn, types);
-    let vars = efn.args.iter().map(|arg| {
+    let receiver_var = efn.receiver.iter().map(|_| quote!(self));
+    let arg_vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
             Type::Ident(ident) if ident == RustString => {
@@ -189,6 +207,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             _ => quote!(#var),
         }
     });
+    let vars = receiver_var.chain(arg_vars);
     let trampolines = efn
         .args
         .iter()
@@ -274,18 +293,36 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     }
     .unwrap_or(call);
-    quote! {
-        #doc
-        pub fn #ident(#args) #ret {
-            extern "C" {
-                #decl
+    let receiver_ident = efn.receiver.as_ref().map(|base| &base.ident);
+    match receiver_ident {
+        None => quote! {
+            #doc
+            pub fn #ident(#(#all_args,)*) #ret {
+                extern "C" {
+                    #decl
+                }
+                #trampolines
+                unsafe {
+                    #setup
+                    #expr
+                }
             }
-            #trampolines
-            unsafe {
-                #setup
-                #expr
+        },
+        Some(base_ident) => quote! {
+            #doc
+            impl #base_ident {
+                pub fn #ident(#(#all_args,)*) #ret {
+                    extern "C" {
+                        #decl
+                    }
+                    #trampolines
+                    unsafe {
+                        #setup
+                        #expr
+                    }
+                }
             }
-        }
+        },
     }
 }
 
@@ -333,7 +370,11 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let link_name = format!("{}cxxbridge02${}", namespace, ident);
+    let receiver_type = match &efn.receiver {
+        Some(base) => base.ident.to_string(),
+        None => "_".to_string(),
+    };
+    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     let invoke = Some(ident);
@@ -355,6 +396,13 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
+    let receiver = sig.receiver.iter().map(|base| {
+        let ident = &base.ident;
+        match base.mutability {
+            None => quote!(__receiver: &#ident),
+            Some(_) => quote!(__receiver: &mut #ident),
+        }
+    });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -364,6 +412,7 @@ fn expand_rust_function_shim_impl(
             quote!(#ident: #ty)
         }
     });
+    let all_args = receiver.chain(args);
 
     let vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
@@ -385,7 +434,10 @@ fn expand_rust_function_shim_impl(
     });
 
     let mut call = match invoke {
-        Some(ident) => quote!(super::#ident),
+        Some(ident) => match sig.receiver {
+            None => quote!(super::#ident),
+            Some(_) => quote!(__receiver.#ident),
+        },
         None => quote!(__extern),
     };
     call.extend(quote! { (#(#vars),*) });
@@ -443,7 +495,7 @@ fn expand_rust_function_shim_impl(
     quote! {
         #[doc(hidden)]
         #[export_name = #link_name]
-        unsafe extern "C" fn #local_name(#(#args,)* #outparam #pointer) #ret {
+        unsafe extern "C" fn #local_name(#(#all_args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
             #expr
         }
diff --git a/src/lib.rs b/src/lib.rs
index 609db59..780a26e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -79,8 +79,10 @@
 //!
 //!         // Functions implemented in C++.
 //!         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-//!         fn get_name(thing: &ThingC) -> &CxxString;
 //!         fn do_thing(state: SharedThing);
+//!
+//!         // Methods implemented in C++.
+//!         fn get_name(self: &ThingC) -> &CxxString;
 //!     }
 //!
 //!     extern "Rust" {
@@ -90,6 +92,9 @@
 //!
 //!         // Functions implemented in Rust.
 //!         fn print_r(r: &ThingR);
+//!
+//!         // Methods implemented in Rust.
+//!         fn print(self: &ThingR);
 //!     }
 //! }
 //! #
@@ -99,6 +104,12 @@
 //! #     println!("called back with r={}", r.0);
 //! # }
 //! #
+//! # impl ThingR {
+//! #     fn print(&self) {
+//! #         println!("method called back with r={}", self.0);
+//! #     }
+//! # }
+//! #
 //! # fn main() {}
 //! ```
 //!
diff --git a/syntax/check.rs b/syntax/check.rs
index 181c530..3b6937a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -195,6 +195,10 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
         }
     }
 
+    if efn.receiver.is_some() {
+        reference_args += 1;
+    }
+
     if reference_args != 1 {
         cx.error(
             efn,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 8afa841..4da5740 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -49,10 +49,14 @@ pub mod ffi {
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
+
+        fn get(self: &C) -> usize;
+        fn set(self: &mut C, n: usize) -> usize;
     }
 
     extern "Rust" {
         type R;
+        type R2;
 
         fn r_return_primitive() -> usize;
         fn r_return_shared() -> Shared;
@@ -77,11 +81,28 @@ pub mod ffi {
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
         fn r_fail_return_primitive() -> Result<usize>;
+
+        fn r_return_r2(n: usize) -> Box<R2>;
+        fn get(self: &R2) -> usize;
+        fn set(self: &mut R2, n: usize) -> usize;
     }
 }
 
 pub type R = usize;
 
+pub struct R2(usize);
+
+impl R2 {
+    fn get(&self) -> usize {
+        self.0
+    }
+
+    fn set(&mut self, n: usize) -> usize {
+        self.0 = n;
+        n
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
@@ -184,3 +205,7 @@ fn r_try_return_primitive() -> Result<usize, Error> {
 fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }
+
+fn r_return_r2(n: usize) -> Box<R2> {
+    Box::new(R2(n))
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d72bfd0..8893ee8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -15,6 +15,11 @@ C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
 
+size_t C::set(size_t n) {
+  this->n = n;
+  return this->n;
+}
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -176,6 +181,13 @@ extern "C" const char *cxx_run_test() noexcept {
     ASSERT(std::strcmp(e.what(), "rust error") == 0);
   }
 
+  auto r2 = r_return_r2(2020);
+  ASSERT(r2->get() == 2020);
+  ASSERT(r2->set(2021) == 2021);
+  ASSERT(r2->get() == 2021);
+  ASSERT(r2->set(2020) == 2020);
+  ASSERT(r2->get() == 2020);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index a68be5c..43ac229 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -12,6 +12,7 @@ class C {
 public:
   C(size_t n);
   size_t get() const;
+  size_t set(size_t n);
 
 private:
   size_t n;
diff --git a/tests/test.rs b/tests/test.rs
index 511c52b..36de8f9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -107,6 +107,18 @@ fn test_c_call_r() {
     check!(cxx_run_test());
 }
 
+#[test]
+fn test_c_method_calls() {
+    let mut unique_ptr = ffi::c_return_unique_ptr();
+
+    let old_value = unique_ptr.as_ref().unwrap().get();
+    assert_eq!(2020, old_value);
+    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
+    assert_eq!(2021, unique_ptr.as_ref().unwrap().get());
+    assert_eq!(old_value, unique_ptr.as_mut().unwrap().set(old_value));
+    assert_eq!(old_value, unique_ptr.as_ref().unwrap().get())
+}
+
 #[no_mangle]
 extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
     Box::into_raw(Box::new(2020usize))

From 46a54e7abe3c38aba4d5f2afb69d7477c5d4f240 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 284/2232] Format with rustfmt 2020-03-11


---

diff --git a/gen/write.rs b/gen/write.rs
index b8d17df..9a2e4c8 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -45,13 +45,16 @@ pub(super) fn gen(
         }
     }
 
-    let methods_for_type = apis.iter().filter_map(|api| match api {
-        Api::RustFunction(efn) => match &efn.sig.receiver {
-            Some(rcvr) => Some((&rcvr.ident, efn)),
+    let methods_for_type = apis
+        .iter()
+        .filter_map(|api| match api {
+            Api::RustFunction(efn) => match &efn.sig.receiver {
+                Some(rcvr) => Some((&rcvr.ident, efn)),
+                _ => None,
+            },
             _ => None,
-        },
-        _ => None,
-    }).into_group_map();
+        })
+        .into_group_map();
 
     for api in apis {
         match api {
@@ -59,15 +62,13 @@ pub(super) fn gen(
                 out.next_section();
                 write_struct(out, strct);
             }
-            Api::RustType(ety) => {
-                match methods_for_type.get(&ety.ident) {
-                    Some(methods) => {
-                        out.next_section();
-                        write_struct_with_methods(out, ety, methods);
-                    },
-                    _ => {}
+            Api::RustType(ety) => match methods_for_type.get(&ety.ident) {
+                Some(methods) => {
+                    out.next_section();
+                    write_struct_with_methods(out, ety, methods);
                 }
-            }
+                _ => {}
+            },
             _ => {}
         }
     }
@@ -368,7 +369,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         Some(base) => base.ident.to_string(),
         None => "_".to_string(),
     };
-    write!(out, "{}cxxbridge02${}${}(", out.namespace, receiver_type, efn.ident);
+    write!(
+        out,
+        "{}cxxbridge02${}${}(",
+        out.namespace, receiver_type, efn.ident
+    );
     if let Some(base) = &efn.receiver {
         write!(out, "{} *__receiver$", base.ident);
     }
@@ -404,8 +409,11 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     write!(out, ")");
     match &efn.receiver {
-        Some(Receiver { mutability: None, ident: _ }) => write!(out, " const"),
-        _ => {},
+        Some(Receiver {
+            mutability: None,
+            ident: _,
+        }) => write!(out, " const"),
+        _ => {}
     }
     write!(out, " = ");
     match &efn.receiver {
@@ -517,7 +525,10 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         Some(base) => base.ident.to_string(),
         None => "_".to_string(),
     };
-    let link_name = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
+    let link_name = format!(
+        "{}cxxbridge02${}${}",
+        out.namespace, receiver_type, efn.ident
+    );
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -573,7 +584,10 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         Some(base) => base.ident.to_string(),
         None => "_".to_string(),
     };
-    let invoke = format!("{}cxxbridge02${}${}", out.namespace, receiver_type, efn.ident);
+    let invoke = format!(
+        "{}cxxbridge02${}${}",
+        out.namespace, receiver_type, efn.ident
+    );
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }

From f94bef1ba2cf16b7b6ce1efe4bef88768b34d0a4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 285/2232] Replace itertools dependency


---

diff --git a/Cargo.toml b/Cargo.toml
index eff5820..f9d9b52 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,6 @@ anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.9", path = "macro" }
-itertools = "0.9"
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/gen/write.rs b/gen/write.rs
index 9a2e4c8..a77c658 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -3,8 +3,8 @@ use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
-use itertools::Itertools;
 use proc_macro2::Ident;
+use std::collections::HashMap;
 
 pub(super) fn gen(
     namespace: Namespace,
@@ -45,16 +45,17 @@ pub(super) fn gen(
         }
     }
 
-    let methods_for_type = apis
-        .iter()
-        .filter_map(|api| match api {
-            Api::RustFunction(efn) => match &efn.sig.receiver {
-                Some(rcvr) => Some((&rcvr.ident, efn)),
-                _ => None,
-            },
-            _ => None,
-        })
-        .into_group_map();
+    let mut methods_for_type = HashMap::new();
+    for api in apis {
+        if let Api::RustFunction(efn) = api {
+            if let Some(receiver) = &efn.sig.receiver {
+                methods_for_type
+                    .entry(&receiver.ident)
+                    .or_insert_with(Vec::new)
+                    .push(efn);
+            }
+        }
+    }
 
     for api in apis {
         match api {

From 5e29b217c3226866587bff4a572d9c1e55f99aff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 286/2232] Rely on UniquePtr Deref impl in tests


---

diff --git a/tests/test.rs b/tests/test.rs
index 36de8f9..eb14d36 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -31,14 +31,7 @@ fn test_c_return() {
     assert_eq!("2020", ffi::c_return_str(&shared));
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
-    assert_eq!(
-        "2020",
-        ffi::c_return_unique_ptr_string()
-            .as_ref()
-            .unwrap()
-            .to_str()
-            .unwrap()
-    );
+    assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
 }
 
 #[test]
@@ -54,13 +47,7 @@ fn test_c_try_return() {
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
     assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
     assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
-    assert_eq!(
-        "2020",
-        ffi::c_try_return_unique_ptr_string()
-            .unwrap()
-            .as_ref()
-            .unwrap()
-    );
+    assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap());
 }
 
 #[test]
@@ -70,7 +57,7 @@ fn test_c_take() {
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
-    check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap()));
+    check!(ffi::c_take_ref_c(&unique_ptr));
     check!(ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
@@ -111,12 +98,12 @@ fn test_c_call_r() {
 fn test_c_method_calls() {
     let mut unique_ptr = ffi::c_return_unique_ptr();
 
-    let old_value = unique_ptr.as_ref().unwrap().get();
+    let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
-    assert_eq!(2021, unique_ptr.as_ref().unwrap().get());
-    assert_eq!(old_value, unique_ptr.as_mut().unwrap().set(old_value));
-    assert_eq!(old_value, unique_ptr.as_ref().unwrap().get())
+    assert_eq!(2021, unique_ptr.set(2021));
+    assert_eq!(2021, unique_ptr.get());
+    assert_eq!(old_value, unique_ptr.set(old_value));
+    assert_eq!(old_value, unique_ptr.get())
 }
 
 #[no_mangle]

From b6a5f67b193f861dc89cb874bbdcb8d96118a722 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 287/2232] Remove methods from intro example code


I'd like to keep this first code snippet as focused as possible on the
most important concepts. We'll need to figure out somewhere else to put
exhaustive documentation of the full feature set.

---

diff --git a/README.md b/README.md
index 3f7399a..508d43d 100644
--- a/README.md
+++ b/README.md
@@ -84,10 +84,8 @@ mod ffi {
 
         // Functions implemented in C++.
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
+        fn get_name(thing: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
-
-        // Methods implemented in C++.
-        fn get_name(self: &ThingC) -> &CxxString;
     }
 
     extern "Rust" {
@@ -97,9 +95,6 @@ mod ffi {
 
         // Functions implemented in Rust.
         fn print_r(r: &ThingR);
-
-        // Methods implemented in Rust.
-        fn print(self: &ThingR);
     }
 }
 ```
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index bc0d976..cd447ea 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,19 +9,13 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-const std::string &ThingC::get_name() const {
-  std::cout << "I'm a C++ method!" << std::endl;
-  return this->appname;
-}
-
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
-void do_thing(SharedThing state) {
-  print_r(*state.y);
-  state.y->print();
-}
+const std::string &get_name(const ThingC &thing) { return thing.appname; }
+
+void do_thing(SharedThing state) { print_r(*state.y); }
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 885293f..fafc474 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -12,13 +12,12 @@ public:
   ~ThingC();
 
   std::string appname;
-
-  const std::string &get_name() const;
 };
 
 struct SharedThing;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
+const std::string &get_name(const ThingC &thing);
 void do_thing(SharedThing state);
 
 } // namespace example
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 713a1d1..66dfc79 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -11,15 +11,13 @@ mod ffi {
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(self: &ThingC) -> &CxxString;
+        fn get_name(thing: &ThingC) -> &CxxString;
         fn do_thing(state: SharedThing);
-
     }
 
     extern "Rust" {
         type ThingR;
         fn print_r(r: &ThingR);
-        fn print(self: &ThingR);
     }
 }
 
@@ -29,15 +27,9 @@ fn print_r(r: &ThingR) {
     println!("called back with r={}", r.0);
 }
 
-impl ThingR {
-    fn print(&self) {
-        println!("method called back with r={}", self.0);
-    }
-}
-
 fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", x.as_ref().unwrap().get_name());
+    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
 
     ffi::do_thing(ffi::SharedThing {
         z: 222,
diff --git a/src/lib.rs b/src/lib.rs
index 780a26e..609db59 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -79,10 +79,8 @@
 //!
 //!         // Functions implemented in C++.
 //!         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
+//!         fn get_name(thing: &ThingC) -> &CxxString;
 //!         fn do_thing(state: SharedThing);
-//!
-//!         // Methods implemented in C++.
-//!         fn get_name(self: &ThingC) -> &CxxString;
 //!     }
 //!
 //!     extern "Rust" {
@@ -92,9 +90,6 @@
 //!
 //!         // Functions implemented in Rust.
 //!         fn print_r(r: &ThingR);
-//!
-//!         // Methods implemented in Rust.
-//!         fn print(self: &ThingR);
 //!     }
 //! }
 //! #
@@ -104,12 +99,6 @@
 //! #     println!("called back with r={}", r.0);
 //! # }
 //! #
-//! # impl ThingR {
-//! #     fn print(&self) {
-//! #         println!("method called back with r={}", self.0);
-//! #     }
-//! # }
-//! #
 //! # fn main() {}
 //! ```
 //!

From 70711f6d987c7fc929ba326280cde26cc24efa8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 288/2232] Run exhaustive test suite on 1.43+ only


The `self: &T` syntax in extern functions doesn't work yet in 1.42. The
intro demo code should work though.

---

diff --git a/.travis.yml b/.travis.yml
index 28ad110..49bacbd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,6 @@ language: rust
 rust:
   - nightly
   - beta
-  - stable
 
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml
@@ -55,3 +54,5 @@ matrix:
         - bazel test ... --verbose_failures --noshow_progress
     - name: Minimum rustc
       rust: 1.42.0
+      script:
+        - cargo run --manifest-path demo-rs/Cargo.toml

From c1fe0055ca8fb90c27faecc5772eb9f7459b8722 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:44:03 +0000
Subject: [PATCH 289/2232] Touch up PR 121


---

diff --git a/gen/write.rs b/gen/write.rs
index a77c658..4c7b0ae 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -63,13 +63,12 @@ pub(super) fn gen(
                 out.next_section();
                 write_struct(out, strct);
             }
-            Api::RustType(ety) => match methods_for_type.get(&ety.ident) {
-                Some(methods) => {
+            Api::RustType(ety) => {
+                if let Some(methods) = methods_for_type.get(&ety.ident) {
                     out.next_section();
                     write_struct_with_methods(out, ety, methods);
                 }
-                _ => {}
-            },
+            }
             _ => {}
         }
     }
@@ -323,7 +322,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &Vec<&ExternFn>) {
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }

From 8537f2ac8f3c0d51b96e944dfd5f3da87ef9e54d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 17 2020 23:58:18 +0000
Subject: [PATCH 290/2232] Update bazel CI to 1.43-beta to support extern method syntax


---

diff --git a/WORKSPACE b/WORKSPACE
index 4357b70..435086f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,15 +24,17 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_42_linux",
+    name = "rust_1_43_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [],
-    version = "1.42.0",
+    iso_date = "2020-04-07",
+    version = "beta",
 )
 
 rust_repository_set(
-    name = "rust_1_42_darwin",
+    name = "rust_1_43_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
     extra_target_triples = [],
-    version = "1.42.0",
+    iso_date = "2020-04-07",
+    version = "beta",
 )

From de96ae805a0409f2b5732278bad4b6f0923c5a08 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 19 2020 17:52:35 +0000
Subject: [PATCH 291/2232] Pull in 1.43.0-beta.6


---

diff --git a/WORKSPACE b/WORKSPACE
index 435086f..f39808c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -27,7 +27,7 @@ rust_repository_set(
     name = "rust_1_43_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
     extra_target_triples = [],
-    iso_date = "2020-04-07",
+    iso_date = "2020-04-19",
     version = "beta",
 )
 
@@ -35,6 +35,6 @@ rust_repository_set(
     name = "rust_1_43_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
     extra_target_triples = [],
-    iso_date = "2020-04-07",
+    iso_date = "2020-04-19",
     version = "beta",
 )

From 44395e335b603764a3fe2b3bc6b0055168999a38 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 19 2020 21:52:55 +0000
Subject: [PATCH 292/2232] Match clang-format's style more consistently in generated code


---

diff --git a/gen/write.rs b/gen/write.rs
index 4c7b0ae..460a55f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -328,7 +328,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     }
     writeln!(out, "struct {} final {{", ety.ident);
     writeln!(out, "  {}() = delete;", ety.ident);
-    writeln!(out, "  {}(const {}&) = delete;", ety.ident, ety.ident);
+    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;

From 26804bd83b5e37da5338971e626c835fe2b52fdc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 03:06:51 +0000
Subject: [PATCH 293/2232] Use receiver name that resembles the Rust input more closely


---

diff --git a/gen/write.rs b/gen/write.rs
index 460a55f..7a57111 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -375,7 +375,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         out.namespace, receiver_type, efn.ident
     );
     if let Some(base) = &efn.receiver {
-        write!(out, "{} *__receiver$", base.ident);
+        write!(out, "{} *self$", base.ident);
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -445,7 +445,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(__receiver$->*{}$)(", efn.ident),
+        Some(_) => write!(out, "(self$->*{}$)(", efn.ident),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -548,7 +548,7 @@ fn write_rust_function_decl_impl(
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
     if let Some(base) = &sig.receiver {
-        write!(out, "{} &__receiver$", base.ident);
+        write!(out, "{} &self$", base.ident);
         needs_comma = true;
     }
     for arg in &sig.args {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2d3166a..ac39e4e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -399,8 +399,8 @@ fn expand_rust_function_shim_impl(
     let receiver = sig.receiver.iter().map(|base| {
         let ident = &base.ident;
         match base.mutability {
-            None => quote!(__receiver: &#ident),
-            Some(_) => quote!(__receiver: &mut #ident),
+            None => quote!(__self: &#ident),
+            Some(_) => quote!(__self: &mut #ident),
         }
     });
     let args = sig.args.iter().map(|arg| {
@@ -436,7 +436,7 @@ fn expand_rust_function_shim_impl(
     let mut call = match invoke {
         Some(ident) => match sig.receiver {
             None => quote!(super::#ident),
-            Some(_) => quote!(__receiver.#ident),
+            Some(_) => quote!(__self.#ident),
         },
         None => quote!(__extern),
     };

From 0841930d34460e531d6397c34513b1fbb43c8383 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 03:38:28 +0000
Subject: [PATCH 294/2232] Share one Namespace type between gen and macro


---

diff --git a/gen/mod.rs b/gen/mod.rs
index 523ba1d..998cd14 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -3,12 +3,11 @@
 
 mod error;
 pub(super) mod include;
-mod namespace;
 pub(super) mod out;
 mod write;
 
 use self::error::format_err;
-use self::namespace::Namespace;
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{self, check, ident, Types};
 use quote::quote;
 use std::fs;
diff --git a/gen/namespace.rs b/gen/namespace.rs
deleted file mode 100644
index 557e331..0000000
--- a/gen/namespace.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::fmt::{self, Display};
-use std::slice::Iter;
-
-#[derive(Clone)]
-pub struct Namespace {
-    segments: Vec<String>,
-}
-
-impl Namespace {
-    pub fn new(segments: Vec<String>) -> Self {
-        Namespace { segments }
-    }
-
-    pub fn iter(&self) -> Iter<String> {
-        self.segments.iter()
-    }
-}
-
-impl Display for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for segment in self {
-            f.write_str(segment)?;
-            f.write_str("$")?;
-        }
-        Ok(())
-    }
-}
-
-impl<'a> IntoIterator for &'a Namespace {
-    type Item = &'a String;
-    type IntoIter = Iter<'a, String>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
diff --git a/gen/out.rs b/gen/out.rs
index 35f2cd7..08bf85f 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,5 +1,5 @@
 use crate::gen::include::Includes;
-use crate::gen::namespace::Namespace;
+use crate::syntax::namespace::Namespace;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
diff --git a/gen/write.rs b/gen/write.rs
index 7a57111..28a2d3b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,7 +1,7 @@
-use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ac39e4e..373bfee 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,5 @@
-use crate::namespace::Namespace;
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 59433c1..49c4f42 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -13,7 +13,7 @@ mod expand;
 mod namespace;
 mod syntax;
 
-use crate::namespace::Namespace;
+use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
 use syn::{parse_macro_input, ItemMod};
 
diff --git a/macro/src/namespace.rs b/macro/src/namespace.rs
index d2b3e1c..2d14aa2 100644
--- a/macro/src/namespace.rs
+++ b/macro/src/namespace.rs
@@ -1,4 +1,5 @@
 use crate::syntax::ident;
+use crate::syntax::namespace::Namespace;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use syn::parse::{Parse, ParseStream, Result};
@@ -8,10 +9,6 @@ mod kw {
     syn::custom_keyword!(namespace);
 }
 
-pub struct Namespace {
-    segments: Vec<String>,
-}
-
 impl Parse for Namespace {
     fn parse(input: ParseStream) -> Result<Self> {
         let mut segments = Vec::new();
@@ -25,17 +22,7 @@ impl Parse for Namespace {
             }
             input.parse::<Option<Token![,]>>()?;
         }
-        Ok(Namespace { segments })
-    }
-}
-
-impl Display for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for segment in &self.segments {
-            f.write_str(segment)?;
-            f.write_str("$")?;
-        }
-        Ok(())
+        Ok(Namespace::new(segments))
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4eaf81e..21ff447 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod doc;
 pub mod error;
 pub mod ident;
 mod impls;
+pub mod namespace;
 mod parse;
 pub mod set;
 mod tokens;
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
new file mode 100644
index 0000000..557e331
--- /dev/null
+++ b/syntax/namespace.rs
@@ -0,0 +1,35 @@
+use std::fmt::{self, Display};
+use std::slice::Iter;
+
+#[derive(Clone)]
+pub struct Namespace {
+    segments: Vec<String>,
+}
+
+impl Namespace {
+    pub fn new(segments: Vec<String>) -> Self {
+        Namespace { segments }
+    }
+
+    pub fn iter(&self) -> Iter<String> {
+        self.segments.iter()
+    }
+}
+
+impl Display for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for segment in self {
+            f.write_str(segment)?;
+            f.write_str("$")?;
+        }
+        Ok(())
+    }
+}
+
+impl<'a> IntoIterator for &'a Namespace {
+    type Item = &'a String;
+    type IntoIter = Iter<'a, String>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}

From b6cf314a45b2cdda3e6e996fe034bbc83d8619b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 03:59:20 +0000
Subject: [PATCH 295/2232] Unify Namespace parsing code


---

diff --git a/gen/mod.rs b/gen/mod.rs
index 998cd14..4c3a292 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -8,13 +8,12 @@ mod write;
 
 use self::error::format_err;
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{self, check, ident, Types};
+use crate::syntax::{self, check, Types};
 use quote::quote;
 use std::fs;
 use std::io;
 use std::path::Path;
-use syn::parse::ParseStream;
-use syn::{Attribute, File, Item, Token};
+use syn::{Attribute, File, Item};
 use thiserror::Error;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
@@ -86,8 +85,7 @@ fn find_bridge_mod(syntax: File) -> Result<Input> {
                             )));
                         }
                     };
-                    let namespace_segments = parse_args(attr)?;
-                    let namespace = Namespace::new(namespace_segments);
+                    let namespace = parse_args(attr)?;
                     return Ok(Input { namespace, module });
                 }
             }
@@ -96,24 +94,10 @@ fn find_bridge_mod(syntax: File) -> Result<Input> {
     Err(Error::NoBridgeMod)
 }
 
-fn parse_args(attr: &Attribute) -> syn::Result<Vec<String>> {
+fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
     if attr.tokens.is_empty() {
-        return Ok(Vec::new());
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
     }
-    attr.parse_args_with(|input: ParseStream| {
-        mod kw {
-            syn::custom_keyword!(namespace);
-        }
-        input.parse::<kw::namespace>()?;
-        input.parse::<Token![=]>()?;
-        let path = syn::Path::parse_mod_style(input)?;
-        input.parse::<Option<Token![,]>>()?;
-        path.segments
-            .into_iter()
-            .map(|seg| {
-                ident::check(&seg.ident)?;
-                Ok(seg.ident.to_string())
-            })
-            .collect()
-    })
 }
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 49c4f42..b56f58e 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -10,7 +10,6 @@
 extern crate proc_macro;
 
 mod expand;
-mod namespace;
 mod syntax;
 
 use crate::syntax::namespace::Namespace;
diff --git a/macro/src/namespace.rs b/macro/src/namespace.rs
deleted file mode 100644
index 2d14aa2..0000000
--- a/macro/src/namespace.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-use crate::syntax::ident;
-use crate::syntax::namespace::Namespace;
-use quote::IdentFragment;
-use std::fmt::{self, Display};
-use syn::parse::{Parse, ParseStream, Result};
-use syn::{Path, Token};
-
-mod kw {
-    syn::custom_keyword!(namespace);
-}
-
-impl Parse for Namespace {
-    fn parse(input: ParseStream) -> Result<Self> {
-        let mut segments = Vec::new();
-        if !input.is_empty() {
-            input.parse::<kw::namespace>()?;
-            input.parse::<Token![=]>()?;
-            let path = input.call(Path::parse_mod_style)?;
-            for segment in path.segments {
-                ident::check(&segment.ident)?;
-                segments.push(segment.ident.to_string());
-            }
-            input.parse::<Option<Token![,]>>()?;
-        }
-        Ok(Namespace::new(segments))
-    }
-}
-
-impl IdentFragment for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(self, f)
-    }
-}
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 557e331..d26bb9e 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,5 +1,13 @@
+use crate::syntax::ident;
+use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{Path, Token};
+
+mod kw {
+    syn::custom_keyword!(namespace);
+}
 
 #[derive(Clone)]
 pub struct Namespace {
@@ -7,8 +15,10 @@ pub struct Namespace {
 }
 
 impl Namespace {
-    pub fn new(segments: Vec<String>) -> Self {
-        Namespace { segments }
+    pub fn none() -> Self {
+        Namespace {
+            segments: Vec::new(),
+        }
     }
 
     pub fn iter(&self) -> Iter<String> {
@@ -16,6 +26,23 @@ impl Namespace {
     }
 }
 
+impl Parse for Namespace {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let mut segments = Vec::new();
+        if !input.is_empty() {
+            input.parse::<kw::namespace>()?;
+            input.parse::<Token![=]>()?;
+            let path = input.call(Path::parse_mod_style)?;
+            for segment in path.segments {
+                ident::check(&segment.ident)?;
+                segments.push(segment.ident.to_string());
+            }
+            input.parse::<Option<Token![,]>>()?;
+        }
+        Ok(Namespace { segments })
+    }
+}
+
 impl Display for Namespace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for segment in self {
@@ -26,6 +53,12 @@ impl Display for Namespace {
     }
 }
 
+impl IdentFragment for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(self, f)
+    }
+}
+
 impl<'a> IntoIterator for &'a Namespace {
     type Item = &'a String;
     type IntoIter = Iter<'a, String>;

From f878e591a650439a168de5a112cd953be6c0bdb3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 04:12:56 +0000
Subject: [PATCH 296/2232] Merge pull request #127 from dtolnay/namespace


Unify the Namespace types used by both code generators
---

diff --git a/gen/mod.rs b/gen/mod.rs
index 523ba1d..4c3a292 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -3,19 +3,17 @@
 
 mod error;
 pub(super) mod include;
-mod namespace;
 pub(super) mod out;
 mod write;
 
 use self::error::format_err;
-use self::namespace::Namespace;
-use crate::syntax::{self, check, ident, Types};
+use crate::syntax::namespace::Namespace;
+use crate::syntax::{self, check, Types};
 use quote::quote;
 use std::fs;
 use std::io;
 use std::path::Path;
-use syn::parse::ParseStream;
-use syn::{Attribute, File, Item, Token};
+use syn::{Attribute, File, Item};
 use thiserror::Error;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
@@ -87,8 +85,7 @@ fn find_bridge_mod(syntax: File) -> Result<Input> {
                             )));
                         }
                     };
-                    let namespace_segments = parse_args(attr)?;
-                    let namespace = Namespace::new(namespace_segments);
+                    let namespace = parse_args(attr)?;
                     return Ok(Input { namespace, module });
                 }
             }
@@ -97,24 +94,10 @@ fn find_bridge_mod(syntax: File) -> Result<Input> {
     Err(Error::NoBridgeMod)
 }
 
-fn parse_args(attr: &Attribute) -> syn::Result<Vec<String>> {
+fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
     if attr.tokens.is_empty() {
-        return Ok(Vec::new());
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
     }
-    attr.parse_args_with(|input: ParseStream| {
-        mod kw {
-            syn::custom_keyword!(namespace);
-        }
-        input.parse::<kw::namespace>()?;
-        input.parse::<Token![=]>()?;
-        let path = syn::Path::parse_mod_style(input)?;
-        input.parse::<Option<Token![,]>>()?;
-        path.segments
-            .into_iter()
-            .map(|seg| {
-                ident::check(&seg.ident)?;
-                Ok(seg.ident.to_string())
-            })
-            .collect()
-    })
 }
diff --git a/gen/namespace.rs b/gen/namespace.rs
deleted file mode 100644
index 557e331..0000000
--- a/gen/namespace.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::fmt::{self, Display};
-use std::slice::Iter;
-
-#[derive(Clone)]
-pub struct Namespace {
-    segments: Vec<String>,
-}
-
-impl Namespace {
-    pub fn new(segments: Vec<String>) -> Self {
-        Namespace { segments }
-    }
-
-    pub fn iter(&self) -> Iter<String> {
-        self.segments.iter()
-    }
-}
-
-impl Display for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for segment in self {
-            f.write_str(segment)?;
-            f.write_str("$")?;
-        }
-        Ok(())
-    }
-}
-
-impl<'a> IntoIterator for &'a Namespace {
-    type Item = &'a String;
-    type IntoIter = Iter<'a, String>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.iter()
-    }
-}
diff --git a/gen/out.rs b/gen/out.rs
index 35f2cd7..08bf85f 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,5 +1,5 @@
 use crate::gen::include::Includes;
-use crate::gen::namespace::Namespace;
+use crate::syntax::namespace::Namespace;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
diff --git a/gen/write.rs b/gen/write.rs
index 7a57111..28a2d3b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,7 +1,7 @@
-use crate::gen::namespace::Namespace;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ac39e4e..373bfee 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,5 @@
-use crate::namespace::Namespace;
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 59433c1..b56f58e 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -10,10 +10,9 @@
 extern crate proc_macro;
 
 mod expand;
-mod namespace;
 mod syntax;
 
-use crate::namespace::Namespace;
+use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
 use syn::{parse_macro_input, ItemMod};
 
diff --git a/macro/src/namespace.rs b/macro/src/namespace.rs
deleted file mode 100644
index d2b3e1c..0000000
--- a/macro/src/namespace.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-use crate::syntax::ident;
-use quote::IdentFragment;
-use std::fmt::{self, Display};
-use syn::parse::{Parse, ParseStream, Result};
-use syn::{Path, Token};
-
-mod kw {
-    syn::custom_keyword!(namespace);
-}
-
-pub struct Namespace {
-    segments: Vec<String>,
-}
-
-impl Parse for Namespace {
-    fn parse(input: ParseStream) -> Result<Self> {
-        let mut segments = Vec::new();
-        if !input.is_empty() {
-            input.parse::<kw::namespace>()?;
-            input.parse::<Token![=]>()?;
-            let path = input.call(Path::parse_mod_style)?;
-            for segment in path.segments {
-                ident::check(&segment.ident)?;
-                segments.push(segment.ident.to_string());
-            }
-            input.parse::<Option<Token![,]>>()?;
-        }
-        Ok(Namespace { segments })
-    }
-}
-
-impl Display for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for segment in &self.segments {
-            f.write_str(segment)?;
-            f.write_str("$")?;
-        }
-        Ok(())
-    }
-}
-
-impl IdentFragment for Namespace {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(self, f)
-    }
-}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4eaf81e..21ff447 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod doc;
 pub mod error;
 pub mod ident;
 mod impls;
+pub mod namespace;
 mod parse;
 pub mod set;
 mod tokens;
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
new file mode 100644
index 0000000..d26bb9e
--- /dev/null
+++ b/syntax/namespace.rs
@@ -0,0 +1,68 @@
+use crate::syntax::ident;
+use quote::IdentFragment;
+use std::fmt::{self, Display};
+use std::slice::Iter;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{Path, Token};
+
+mod kw {
+    syn::custom_keyword!(namespace);
+}
+
+#[derive(Clone)]
+pub struct Namespace {
+    segments: Vec<String>,
+}
+
+impl Namespace {
+    pub fn none() -> Self {
+        Namespace {
+            segments: Vec::new(),
+        }
+    }
+
+    pub fn iter(&self) -> Iter<String> {
+        self.segments.iter()
+    }
+}
+
+impl Parse for Namespace {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let mut segments = Vec::new();
+        if !input.is_empty() {
+            input.parse::<kw::namespace>()?;
+            input.parse::<Token![=]>()?;
+            let path = input.call(Path::parse_mod_style)?;
+            for segment in path.segments {
+                ident::check(&segment.ident)?;
+                segments.push(segment.ident.to_string());
+            }
+            input.parse::<Option<Token![,]>>()?;
+        }
+        Ok(Namespace { segments })
+    }
+}
+
+impl Display for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for segment in self {
+            f.write_str(segment)?;
+            f.write_str("$")?;
+        }
+        Ok(())
+    }
+}
+
+impl IdentFragment for Namespace {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(self, f)
+    }
+}
+
+impl<'a> IntoIterator for &'a Namespace {
+    type Item = &'a String;
+    type IntoIter = Iter<'a, String>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}

From 4e7123f26f72508d03aeb27376e6cad309128611 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 04:13:05 +0000
Subject: [PATCH 297/2232] Resolve clippy single_match lint


---

diff --git a/gen/write.rs b/gen/write.rs
index 28a2d3b..9ae114d 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -408,12 +408,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write_type(out, &arg.ty);
     }
     write!(out, ")");
-    match &efn.receiver {
-        Some(Receiver {
-            mutability: None,
-            ident: _,
-        }) => write!(out, " const"),
-        _ => {}
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
     }
     write!(out, " = ");
     match &efn.receiver {

From 9b5cfe183644ef66d068c40a8a8aa41781a205f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 04:13:06 +0000
Subject: [PATCH 298/2232] Resolve clippy redundant_pattern_matching lint


---

diff --git a/gen/write.rs b/gen/write.rs
index 9ae114d..59e12ed 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -672,7 +672,7 @@ fn write_rust_function_shim_impl(
             write!(out, "::rust::Str::Repr error$ = ");
         }
         write!(out, "{}(", invoke);
-        if let Some(_) = &sig.receiver {
+        if sig.receiver.is_some() {
             write!(out, "*this");
         }
         for (i, arg) in sig.args.iter().enumerate() {

From 3caa50ac99cb77fca136906299b5d1486cf26759 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 04:38:44 +0000
Subject: [PATCH 299/2232] Share function link name mangling logic


---

diff --git a/gen/write.rs b/gen/write.rs
index 59e12ed..4df404c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,9 @@ use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -365,15 +367,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    write!(
-        out,
-        "{}cxxbridge02${}${}(",
-        out.namespace, receiver_type, efn.ident
-    );
+    let mangled = mangle::extern_fn(&out.namespace, efn);
+    write!(out, "{}(", mangled);
     if let Some(base) = &efn.receiver {
         write!(out, "{} *self$", base.ident);
     }
@@ -519,14 +514,7 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!(
-        "{}cxxbridge02${}${}",
-        out.namespace, receiver_type, efn.ident
-    );
+    let link_name = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -578,14 +566,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = efn.ident.to_string();
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let invoke = format!(
-        "{}cxxbridge02${}${}",
-        out.namespace, receiver_type, efn.ident
-    );
+    let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 373bfee..d8bd241 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,6 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
+use crate::syntax::{
+    self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
+};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
@@ -154,11 +156,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
+    let link_name = mangle::extern_fn(namespace, efn);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
@@ -370,11 +368,7 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
+    let link_name = mangle::extern_fn(namespace, efn);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     let invoke = Some(ident);
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
new file mode 100644
index 0000000..9e6bb8a
--- /dev/null
+++ b/syntax/mangle.rs
@@ -0,0 +1,10 @@
+use crate::syntax::namespace::Namespace;
+use crate::syntax::ExternFn;
+
+pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
+    let receiver_type = match &efn.receiver {
+        Some(receiver) => receiver.ident.to_string(),
+        None => "_".to_string(),
+    };
+    format!("{}cxxbridge02${}${}", namespace, receiver_type, efn.ident)
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 21ff447..b7ca6b7 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod doc;
 pub mod error;
 pub mod ident;
 mod impls;
+pub mod mangle;
 pub mod namespace;
 mod parse;
 pub mod set;

From 4d46c03231e833dcf608551b96a4b3e07df6778d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 06:34:50 +0000
Subject: [PATCH 300/2232] Merge pull request #128 from dtolnay/mangle


Share function link name mangling logic
---

diff --git a/gen/write.rs b/gen/write.rs
index 59e12ed..4df404c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,7 +2,9 @@ use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -365,15 +367,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    write!(
-        out,
-        "{}cxxbridge02${}${}(",
-        out.namespace, receiver_type, efn.ident
-    );
+    let mangled = mangle::extern_fn(&out.namespace, efn);
+    write!(out, "{}(", mangled);
     if let Some(base) = &efn.receiver {
         write!(out, "{} *self$", base.ident);
     }
@@ -519,14 +514,7 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!(
-        "{}cxxbridge02${}${}",
-        out.namespace, receiver_type, efn.ident
-    );
+    let link_name = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -578,14 +566,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = efn.ident.to_string();
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let invoke = format!(
-        "{}cxxbridge02${}${}",
-        out.namespace, receiver_type, efn.ident
-    );
+    let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 373bfee..d8bd241 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,6 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{self, check, Api, ExternFn, ExternType, Signature, Struct, Type, Types};
+use crate::syntax::{
+    self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
+};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
@@ -154,11 +156,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
+    let link_name = mangle::extern_fn(namespace, efn);
     let local_name = format_ident!("__{}", ident);
     quote! {
         #[link_name = #link_name]
@@ -370,11 +368,7 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let receiver_type = match &efn.receiver {
-        Some(base) => base.ident.to_string(),
-        None => "_".to_string(),
-    };
-    let link_name = format!("{}cxxbridge02${}${}", namespace, receiver_type, ident);
+    let link_name = mangle::extern_fn(namespace, efn);
     let local_name = format_ident!("__{}", ident);
     let catch_unwind_label = format!("::{}", ident);
     let invoke = Some(ident);
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
new file mode 100644
index 0000000..9e6bb8a
--- /dev/null
+++ b/syntax/mangle.rs
@@ -0,0 +1,10 @@
+use crate::syntax::namespace::Namespace;
+use crate::syntax::ExternFn;
+
+pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
+    let receiver_type = match &efn.receiver {
+        Some(receiver) => receiver.ident.to_string(),
+        None => "_".to_string(),
+    };
+    format!("{}cxxbridge02${}${}", namespace, receiver_type, efn.ident)
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 21ff447..b7ca6b7 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod doc;
 pub mod error;
 pub mod ident;
 mod impls;
+pub mod mangle;
 pub mod namespace;
 mod parse;
 pub mod set;

From 9d8d80bd811811067c6bae4f13cbdea152550887 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 06:35:02 +0000
Subject: [PATCH 301/2232] Remove '_' segment from symbol of non-associated functions


---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 9e6bb8a..a109951 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -2,9 +2,9 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::ExternFn;
 
 pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
-    let receiver_type = match &efn.receiver {
-        Some(receiver) => receiver.ident.to_string(),
-        None => "_".to_string(),
+    let receiver = match &efn.receiver {
+        Some(receiver) => receiver.ident.to_string() + "$",
+        None => String::new(),
     };
-    format!("{}cxxbridge02${}${}", namespace, receiver_type, efn.ident)
+    format!("{}cxxbridge02${}{}", namespace, receiver, efn.ident)
 }

From 5ea922a2112e6208df99354aad02a61beb3468ab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 06:35:54 +0000
Subject: [PATCH 302/2232] Centralize mangled symbol joining


---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index a109951..f2616d2 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,10 +1,18 @@
 use crate::syntax::namespace::Namespace;
-use crate::syntax::ExternFn;
+use crate::syntax::{symbol, ExternFn};
 
-pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
-    let receiver = match &efn.receiver {
-        Some(receiver) => receiver.ident.to_string() + "$",
-        None => String::new(),
+const CXXBRIDGE: &str = "cxxbridge02";
+
+macro_rules! join {
+    ($($segment:expr),*) => {
+        symbol::join(&[$(&$segment),*])
     };
-    format!("{}cxxbridge02${}{}", namespace, receiver, efn.ident)
+}
+
+pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
+    match &efn.receiver {
+        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ident, efn.ident),
+        None => join!(namespace, CXXBRIDGE, efn.ident),
+    }
+    .to_string()
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b7ca6b7..81b1a2f 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -11,6 +11,7 @@ pub mod mangle;
 pub mod namespace;
 mod parse;
 pub mod set;
+mod symbol;
 mod tokens;
 pub mod types;
 
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
new file mode 100644
index 0000000..a40baaf
--- /dev/null
+++ b/syntax/symbol.rs
@@ -0,0 +1,66 @@
+use crate::syntax::namespace::Namespace;
+use proc_macro2::{Ident, TokenStream};
+use quote::ToTokens;
+use std::fmt::{self, Display, Write};
+
+// A mangled symbol consisting of segments separated by '$'.
+// For example: cxxbridge02$string$new
+pub struct Symbol(String);
+
+impl Display for Symbol {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.0, formatter)
+    }
+}
+
+impl ToTokens for Symbol {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        ToTokens::to_tokens(&self.0, tokens);
+    }
+}
+
+impl Symbol {
+    fn push(&mut self, segment: &dyn Display) {
+        let len_before = self.0.len();
+        if !self.0.is_empty() {
+            self.0.push('$');
+        }
+        self.0.write_fmt(format_args!("{}", segment)).unwrap();
+        assert!(self.0.len() > len_before);
+    }
+}
+
+pub trait Segment: Display {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+
+impl Segment for str {}
+impl Segment for Ident {}
+
+impl Segment for Namespace {
+    fn write(&self, symbol: &mut Symbol) {
+        for segment in self {
+            symbol.push(segment);
+        }
+    }
+}
+
+impl<T> Segment for &'_ T
+where
+    T: ?Sized + Segment,
+{
+    fn write(&self, symbol: &mut Symbol) {
+        (**self).write(symbol);
+    }
+}
+
+pub fn join(segments: &[&dyn Segment]) -> Symbol {
+    let mut symbol = Symbol(String::new());
+    for segment in segments {
+        segment.write(&mut symbol);
+    }
+    assert!(!symbol.0.is_empty());
+    symbol
+}

From 891061bc7fdaceeebe81afb0ec195a63868f77f6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 06:35:54 +0000
Subject: [PATCH 303/2232] Use Symbol for mangled names throughout code generators


---

diff --git a/gen/write.rs b/gen/write.rs
index 4df404c..c100691 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -2,6 +2,7 @@ use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     mangle, Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var,
 };
@@ -334,7 +335,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.to_string();
+        let local_name = Symbol::from(&method.ident);
         write_rust_function_shim_decl(out, &local_name, sig, None, false);
         writeln!(out, ";");
     }
@@ -504,12 +505,12 @@ fn write_function_pointer_trampoline(
     types: &Types,
 ) {
     out.next_section();
-    let r_trampoline = format!("{}cxxbridge02${}${}$1", out.namespace, efn.ident, var);
+    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
     let indirect_call = true;
     write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
 
     out.next_section();
-    let c_trampoline = format!("{}cxxbridge02${}${}$0", out.namespace, efn.ident, var);
+    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var);
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
@@ -521,7 +522,7 @@ fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 
 fn write_rust_function_decl_impl(
     out: &mut OutFile,
-    link_name: &str,
+    link_name: &Symbol,
     sig: &Signature,
     types: &Types,
     indirect_call: bool,
@@ -565,7 +566,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    let local_name = efn.ident.to_string();
+    let local_name = Symbol::from(&efn.ident);
     let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
@@ -573,7 +574,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 
 fn write_rust_function_shim_decl(
     out: &mut OutFile,
-    local_name: &str,
+    local_name: &Symbol,
     sig: &Signature,
     receiver: Option<&Receiver>,
     indirect_call: bool,
@@ -604,10 +605,10 @@ fn write_rust_function_shim_decl(
 
 fn write_rust_function_shim_impl(
     out: &mut OutFile,
-    local_name: &str,
+    local_name: &Symbol,
     sig: &Signature,
     types: &Types,
-    invoke: &str,
+    invoke: &Symbol,
     indirect_call: bool,
 ) {
     if out.header && sig.receiver.is_some() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d8bd241..2155ba0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
@@ -331,8 +332,8 @@ fn expand_function_pointer_trampoline(
     sig: &Signature,
     types: &Types,
 ) -> TokenStream {
-    let c_trampoline = format!("{}cxxbridge02${}${}$0", namespace, efn.ident, var);
-    let r_trampoline = format!("{}cxxbridge02${}${}$1", namespace, efn.ident, var);
+    let c_trampoline = mangle::c_trampoline(namespace, efn, var);
+    let r_trampoline = mangle::r_trampoline(namespace, efn, var);
     let local_name = parse_quote!(__);
     let catch_unwind_label = format!("::{}::{}", efn.ident, var);
     let shim = expand_rust_function_shim_impl(
@@ -385,7 +386,7 @@ fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Type
 fn expand_rust_function_shim_impl(
     sig: &Signature,
     types: &Types,
-    link_name: &str,
+    link_name: &Symbol,
     local_name: Ident,
     catch_unwind_label: String,
     invoke: Option<&Ident>,
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index f2616d2..6f4e0d8 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,5 +1,7 @@
 use crate::syntax::namespace::Namespace;
-use crate::syntax::{symbol, ExternFn};
+use crate::syntax::symbol::{self, Symbol};
+use crate::syntax::ExternFn;
+use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge02";
 
@@ -9,10 +11,19 @@ macro_rules! join {
     };
 }
 
-pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> String {
+pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
     match &efn.receiver {
         Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ident, efn.ident),
         None => join!(namespace, CXXBRIDGE, efn.ident),
     }
-    .to_string()
+}
+
+// The C half of a function pointer trampoline.
+pub fn c_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
+    join!(extern_fn(namespace, efn), var, 0)
+}
+
+// The Rust half of a function pointer trampoline.
+pub fn r_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
+    join!(extern_fn(namespace, efn), var, 1)
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 81b1a2f..49bb299 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -11,7 +11,7 @@ pub mod mangle;
 pub mod namespace;
 mod parse;
 pub mod set;
-mod symbol;
+pub mod symbol;
 mod tokens;
 pub mod types;
 
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index a40baaf..fa8e587 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -19,6 +19,12 @@ impl ToTokens for Symbol {
     }
 }
 
+impl From<&Ident> for Symbol {
+    fn from(ident: &Ident) -> Self {
+        Symbol(ident.to_string())
+    }
+}
+
 impl Symbol {
     fn push(&mut self, segment: &dyn Display) {
         let len_before = self.0.len();
@@ -37,7 +43,9 @@ pub trait Segment: Display {
 }
 
 impl Segment for str {}
+impl Segment for usize {}
 impl Segment for Ident {}
+impl Segment for Symbol {}
 
 impl Segment for Namespace {
     fn write(&self, symbol: &mut Symbol) {

From e439c772aa9417615d4940b73dfcb1920dbcfef6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 07:24:58 +0000
Subject: [PATCH 304/2232] Consistently use "receiver" for method self type


---

diff --git a/gen/write.rs b/gen/write.rs
index c100691..05c646a 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -370,8 +370,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     let mangled = mangle::extern_fn(&out.namespace, efn);
     write!(out, "{}(", mangled);
-    if let Some(base) = &efn.receiver {
-        write!(out, "{} *self$", base.ident);
+    if let Some(receiver) = &efn.receiver {
+        write!(out, "{} *self$", receiver.ident);
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -395,7 +395,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write_return_type(out, &efn.ret);
     match &efn.receiver {
         None => write!(out, "(*{}$)(", efn.ident),
-        Some(base) => write!(out, "({}::*{}$)(", base.ident, efn.ident),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ident, efn.ident),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -412,7 +412,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, " = ");
     match &efn.receiver {
         None => write!(out, "{}", efn.ident),
-        Some(base) => write!(out, "&{}::{}", base.ident, efn.ident),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ident, efn.ident),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -534,8 +534,8 @@ fn write_rust_function_decl_impl(
     }
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
-    if let Some(base) = &sig.receiver {
-        write!(out, "{} &self$", base.ident);
+    if let Some(receiver) = &sig.receiver {
+        write!(out, "{} &self$", receiver.ident);
         needs_comma = true;
     }
     for arg in &sig.args {
@@ -580,8 +580,8 @@ fn write_rust_function_shim_decl(
     indirect_call: bool,
 ) {
     write_return_type(out, &sig.ret);
-    if let Some(base) = receiver {
-        write!(out, "{}::", base.ident);
+    if let Some(receiver) = receiver {
+        write!(out, "{}::", receiver.ident);
     }
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2155ba0..d6c0c83 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -126,9 +126,9 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let receiver = efn.receiver.iter().map(|base| {
-        let ident = &base.ident;
-        match base.mutability {
+    let receiver = efn.receiver.iter().map(|receiver| {
+        let ident = &receiver.ident;
+        match receiver.mutability {
             None => quote!(_: &#ident),
             Some(_) => quote!(_: &mut #ident),
         }
@@ -169,10 +169,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
-    let receiver = efn.receiver.iter().map(|base| match base.mutability {
-        None => quote!(&self),
-        Some(_) => quote!(&mut self),
-    });
+    let receiver = efn
+        .receiver
+        .iter()
+        .map(|receiver| match receiver.mutability {
+            None => quote!(&self),
+            Some(_) => quote!(&mut self),
+        });
     let args = efn.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
     let ret = if efn.throws {
@@ -292,8 +295,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     }
     .unwrap_or(call);
-    let receiver_ident = efn.receiver.as_ref().map(|base| &base.ident);
-    match receiver_ident {
+    let receiver_type = efn.receiver.as_ref().map(|receiver| &receiver.ident);
+    match receiver_type {
         None => quote! {
             #doc
             pub fn #ident(#(#all_args,)*) #ret {
@@ -307,9 +310,9 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 }
             }
         },
-        Some(base_ident) => quote! {
+        Some(receiver_type) => quote! {
             #doc
-            impl #base_ident {
+            impl #receiver_type {
                 pub fn #ident(#(#all_args,)*) #ret {
                     extern "C" {
                         #decl
@@ -391,9 +394,9 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
-    let receiver = sig.receiver.iter().map(|base| {
-        let ident = &base.ident;
-        match base.mutability {
+    let receiver = sig.receiver.iter().map(|receiver| {
+        let ident = &receiver.ident;
+        match receiver.mutability {
             None => quote!(__self: &#ident),
             Some(_) => quote!(__self: &mut #ident),
         }

From 86710616bb628fa0b3d71921a1daeeb76f71a45e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 07:45:16 +0000
Subject: [PATCH 305/2232] Fix const in methods with shared reference receivers


---

diff --git a/gen/write.rs b/gen/write.rs
index 05c646a..631be52 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -371,6 +371,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     let mangled = mangle::extern_fn(&out.namespace, efn);
     write!(out, "{}(", mangled);
     if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
         write!(out, "{} *self$", receiver.ident);
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -535,6 +538,9 @@ fn write_rust_function_decl_impl(
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
     if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
         write!(out, "{} &self$", receiver.ident);
         needs_comma = true;
     }
@@ -598,6 +604,11 @@ fn write_rust_function_shim_decl(
         write!(out, "void *extern$");
     }
     write!(out, ")");
+    if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
+    }
     if !sig.throws {
         write!(out, " noexcept");
     }

From 439cde212949f6b15cd3f9d83febfd9051a22ea1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 07:46:25 +0000
Subject: [PATCH 306/2232] Unindent a large non-header codepath


---

diff --git a/gen/write.rs b/gen/write.rs
index 631be52..8f3ecc0 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -629,94 +629,94 @@ fn write_rust_function_shim_impl(
     write_rust_function_shim_decl(out, local_name, sig, sig.receiver.as_ref(), indirect_call);
     if out.header {
         writeln!(out, ";");
-    } else {
-        writeln!(out, " {{");
-        for arg in &sig.args {
-            if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-                out.include.utility = true;
-                write!(out, "  ::rust::ManuallyDrop<");
-                write_type(out, &arg.ty);
-                writeln!(out, "> {}$(::std::move({0}));", arg.ident);
-            }
+        return;
+    }
+    writeln!(out, " {{");
+    for arg in &sig.args {
+        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
+            write!(out, "  ::rust::ManuallyDrop<");
+            write_type(out, &arg.ty);
+            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
         }
+    }
+    write!(out, "  ");
+    let indirect_return = indirect_return(sig, types);
+    if indirect_return {
+        write!(out, "::rust::MaybeUninit<");
+        write_type(out, sig.ret.as_ref().unwrap());
+        writeln!(out, "> return$;");
         write!(out, "  ");
-        let indirect_return = indirect_return(sig, types);
-        if indirect_return {
-            write!(out, "::rust::MaybeUninit<");
-            write_type(out, sig.ret.as_ref().unwrap());
-            writeln!(out, "> return$;");
-            write!(out, "  ");
-        } else if let Some(ret) = &sig.ret {
-            write!(out, "return ");
-            match ret {
-                Type::RustBox(_) => {
-                    write_type(out, ret);
-                    write!(out, "::from_raw(");
-                }
-                Type::UniquePtr(_) => {
-                    write_type(out, ret);
-                    write!(out, "(");
-                }
-                Type::Ref(_) => write!(out, "*"),
-                _ => {}
-            }
-        }
-        if sig.throws {
-            write!(out, "::rust::Str::Repr error$ = ");
-        }
-        write!(out, "{}(", invoke);
-        if sig.receiver.is_some() {
-            write!(out, "*this");
-        }
-        for (i, arg) in sig.args.iter().enumerate() {
-            if i > 0 || sig.receiver.is_some() {
-                write!(out, ", ");
-            }
-            match &arg.ty {
-                Type::Str(_) => write!(out, "::rust::Str::Repr("),
-                Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
-                ty if types.needs_indirect_abi(ty) => write!(out, "&"),
-                _ => {}
+    } else if let Some(ret) = &sig.ret {
+        write!(out, "return ");
+        match ret {
+            Type::RustBox(_) => {
+                write_type(out, ret);
+                write!(out, "::from_raw(");
             }
-            write!(out, "{}", arg.ident);
-            match &arg.ty {
-                Type::RustBox(_) => write!(out, ".into_raw()"),
-                Type::UniquePtr(_) => write!(out, ".release()"),
-                Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
-                ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
-                _ => {}
+            Type::UniquePtr(_) => {
+                write_type(out, ret);
+                write!(out, "(");
             }
+            Type::Ref(_) => write!(out, "*"),
+            _ => {}
         }
-        if indirect_return {
-            if !sig.args.is_empty() {
-                write!(out, ", ");
-            }
-            write!(out, "&return$.value");
+    }
+    if sig.throws {
+        write!(out, "::rust::Str::Repr error$ = ");
+    }
+    write!(out, "{}(", invoke);
+    if sig.receiver.is_some() {
+        write!(out, "*this");
+    }
+    for (i, arg) in sig.args.iter().enumerate() {
+        if i > 0 || sig.receiver.is_some() {
+            write!(out, ", ");
         }
-        if indirect_call {
-            if !sig.args.is_empty() || indirect_return {
-                write!(out, ", ");
-            }
-            write!(out, "extern$");
+        match &arg.ty {
+            Type::Str(_) => write!(out, "::rust::Str::Repr("),
+            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
+            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+            _ => {}
         }
-        write!(out, ")");
-        if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-                write!(out, ")");
-            }
+        write!(out, "{}", arg.ident);
+        match &arg.ty {
+            Type::RustBox(_) => write!(out, ".into_raw()"),
+            Type::UniquePtr(_) => write!(out, ".release()"),
+            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
+            _ => {}
         }
-        writeln!(out, ";");
-        if sig.throws {
-            writeln!(out, "  if (error$.ptr) {{");
-            writeln!(out, "    throw ::rust::Error(error$);");
-            writeln!(out, "  }}");
+    }
+    if indirect_return {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
         }
-        if indirect_return {
-            out.include.utility = true;
-            writeln!(out, "  return ::std::move(return$.value);");
+        write!(out, "&return$.value");
+    }
+    if indirect_call {
+        if !sig.args.is_empty() || indirect_return {
+            write!(out, ", ");
         }
-        writeln!(out, "}}");
+        write!(out, "extern$");
     }
+    write!(out, ")");
+    if let Some(ret) = &sig.ret {
+        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+            write!(out, ")");
+        }
+    }
+    writeln!(out, ";");
+    if sig.throws {
+        writeln!(out, "  if (error$.ptr) {{");
+        writeln!(out, "    throw ::rust::Error(error$);");
+        writeln!(out, "  }}");
+    }
+    if indirect_return {
+        out.include.utility = true;
+        writeln!(out, "  return ::std::move(return$.value);");
+    }
+    writeln!(out, "}}");
 }
 
 fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {

From c3f485c54bf8f19e924f2f855a2924e8a783c5e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 07:52:05 +0000
Subject: [PATCH 307/2232] Simplify variable name of receiver in C++ shims


Even without $, `self` can't collide with any of the variable names the
user has given to the other function parameters.

---

diff --git a/gen/write.rs b/gen/write.rs
index 8f3ecc0..9ab6e38 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -374,7 +374,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} *self$", receiver.ident);
+        write!(out, "{} *self", receiver.ident);
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -442,7 +442,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self$->*{}$)(", efn.ident),
+        Some(_) => write!(out, "(self->*{}$)(", efn.ident),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -541,7 +541,7 @@ fn write_rust_function_decl_impl(
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self$", receiver.ident);
+        write!(out, "{} &self", receiver.ident);
         needs_comma = true;
     }
     for arg in &sig.args {

From 41909e69d45789ce259f65d7de709cfc7c55273a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 07:55:15 +0000
Subject: [PATCH 308/2232] Consistently use C++ reference for receiver arguments


---

diff --git a/gen/write.rs b/gen/write.rs
index 9ab6e38..f7c4a19 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -374,7 +374,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} *self", receiver.ident);
+        write!(out, "{} &self", receiver.ident);
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -442,7 +442,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self->*{}$)(", efn.ident),
+        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {

From a73853b521c59f867f34da4541e0940c4ce61961 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 08:20:05 +0000
Subject: [PATCH 309/2232] Fold qualified path into local_name


---

diff --git a/gen/write.rs b/gen/write.rs
index f7c4a19..2cb8b51 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -3,9 +3,7 @@ use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{
-    mangle, Api, ExternFn, ExternType, Receiver, Signature, Struct, Type, Types, Var,
-};
+use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -335,8 +333,8 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = Symbol::from(&method.ident);
-        write_rust_function_shim_decl(out, &local_name, sig, None, false);
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
     writeln!(out, "}};");
@@ -513,7 +511,7 @@ fn write_function_pointer_trampoline(
     write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
 
     out.next_section();
-    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var);
+    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
@@ -572,7 +570,10 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    let local_name = Symbol::from(&efn.ident);
+    let local_name = match &efn.sig.receiver {
+        None => efn.ident.to_string(),
+        Some(receiver) => format!("{}::{}", receiver.ident, efn.ident),
+    };
     let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
@@ -580,15 +581,11 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
 
 fn write_rust_function_shim_decl(
     out: &mut OutFile,
-    local_name: &Symbol,
+    local_name: &str,
     sig: &Signature,
-    receiver: Option<&Receiver>,
     indirect_call: bool,
 ) {
     write_return_type(out, &sig.ret);
-    if let Some(receiver) = receiver {
-        write!(out, "{}::", receiver.ident);
-    }
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
@@ -616,7 +613,7 @@ fn write_rust_function_shim_decl(
 
 fn write_rust_function_shim_impl(
     out: &mut OutFile,
-    local_name: &Symbol,
+    local_name: &str,
     sig: &Signature,
     types: &Types,
     invoke: &Symbol,
@@ -626,7 +623,7 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    write_rust_function_shim_decl(out, local_name, sig, sig.receiver.as_ref(), indirect_call);
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");
         return;

From fb6e386cf40a36f4064358bf441b3fe5686dc326 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 08:35:08 +0000
Subject: [PATCH 310/2232] Clean up printing of Receiver to tokens


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d6c0c83..91208e6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -126,13 +126,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let receiver = efn.receiver.iter().map(|receiver| {
-        let ident = &receiver.ident;
-        match receiver.mutability {
-            None => quote!(_: &#ident),
-            Some(_) => quote!(_: &mut #ident),
-        }
-    });
+    let receiver = efn.receiver.iter().map(|receiver| quote!(_: #receiver));
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -169,13 +163,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
-    let receiver = efn
-        .receiver
-        .iter()
-        .map(|receiver| match receiver.mutability {
-            None => quote!(&self),
-            Some(_) => quote!(&mut self),
-        });
+    let receiver = efn.receiver.iter().map(|receiver| {
+        let mutability = receiver.mutability;
+        quote!(&#mutability self)
+    });
     let args = efn.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
     let ret = if efn.throws {
@@ -394,13 +385,10 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
-    let receiver = sig.receiver.iter().map(|receiver| {
-        let ident = &receiver.ident;
-        match receiver.mutability {
-            None => quote!(__self: &#ident),
-            Some(_) => quote!(__self: &mut #ident),
-        }
-    });
+    let receiver = sig
+        .receiver
+        .iter()
+        .map(|receiver| quote!(__self: #receiver));
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index d3c4b0f..3509899 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -184,8 +184,13 @@ impl Eq for Receiver {}
 
 impl PartialEq for Receiver {
     fn eq(&self, other: &Receiver) -> bool {
-        let Receiver { mutability, ident } = self;
         let Receiver {
+            ampersand: _,
+            mutability,
+            ident,
+        } = self;
+        let Receiver {
+            ampersand: _,
             mutability: mutability2,
             ident: ident2,
         } = other;
@@ -195,7 +200,11 @@ impl PartialEq for Receiver {
 
 impl Hash for Receiver {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        let Receiver { mutability, ident } = self;
+        let Receiver {
+            ampersand: _,
+            mutability,
+            ident,
+        } = self;
         mutability.is_some().hash(state);
         ident.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 49bb299..b160e5a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -75,6 +75,7 @@ pub struct Var {
 }
 
 pub struct Receiver {
+    pub ampersand: Token![&],
     pub mutability: Option<Token![mut]>,
     pub ident: Ident,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 6e5b36e..7bd36de 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -180,6 +180,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
                 if let Type::Ref(reference) = ty {
                     if let Type::Ident(ident) = reference.inner {
                         receiver = Some(Receiver {
+                            ampersand: reference.ampersand,
                             mutability: reference.mutability,
                             ident,
                         });
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index df11852..784de37 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Ref, Signature, Slice, Ty1, Type, Var};
+use crate::syntax::{Derive, ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type, Var};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::Token;
@@ -97,3 +97,11 @@ impl ToTokens for Signature {
         }
     }
 }
+
+impl ToTokens for Receiver {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.ampersand.to_tokens(tokens);
+        self.mutability.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}

From 25ca093e23ff32a9900c07d29decd0d8c3d5bf19 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 08:36:43 +0000
Subject: [PATCH 311/2232] Fix placement of doc comment on c++ method shim


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 91208e6..1bc2fd1 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -302,8 +302,8 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
         },
         Some(receiver_type) => quote! {
-            #doc
             impl #receiver_type {
+                #doc
                 pub fn #ident(#(#all_args,)*) #ret {
                     extern "C" {
                         #decl

From c66cdbb57f19212d1e0b72454901471a98d1485a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 08:41:15 +0000
Subject: [PATCH 312/2232] Reduce duplication of function vs method c++ function shim


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bc2fd1..acc74d5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -286,36 +286,25 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     }
     .unwrap_or(call);
-    let receiver_type = efn.receiver.as_ref().map(|receiver| &receiver.ident);
-    match receiver_type {
-        None => quote! {
-            #doc
-            pub fn #ident(#(#all_args,)*) #ret {
-                extern "C" {
-                    #decl
-                }
-                #trampolines
-                unsafe {
-                    #setup
-                    #expr
-                }
+    let function_shim = quote! {
+        #doc
+        pub fn #ident(#(#all_args,)*) #ret {
+            extern "C" {
+                #decl
             }
-        },
-        Some(receiver_type) => quote! {
-            impl #receiver_type {
-                #doc
-                pub fn #ident(#(#all_args,)*) #ret {
-                    extern "C" {
-                        #decl
-                    }
-                    #trampolines
-                    unsafe {
-                        #setup
-                        #expr
-                    }
-                }
+            #trampolines
+            unsafe {
+                #setup
+                #expr
             }
-        },
+        }
+    };
+    match &efn.receiver {
+        None => function_shim,
+        Some(receiver) => {
+            let receiver_type = &receiver.ident;
+            quote!(impl #receiver_type { #function_shim })
+        }
     }
 }
 

From 3a45f2d76eab423bb6f2ecef41d15d5a7cd43479 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 09:09:38 +0000
Subject: [PATCH 313/2232] Avoid autoref/deref in method shims


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index acc74d5..207682e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -389,7 +389,8 @@ fn expand_rust_function_shim_impl(
     });
     let all_args = receiver.chain(args);
 
-    let vars = sig.args.iter().map(|arg| {
+    let receiver_var = sig.receiver.iter().map(|_| quote!(__self));
+    let arg_vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
             Type::Ident(i) if i == RustString => {
@@ -407,11 +408,15 @@ fn expand_rust_function_shim_impl(
             _ => quote!(#ident),
         }
     });
+    let vars = receiver_var.chain(arg_vars);
 
     let mut call = match invoke {
-        Some(ident) => match sig.receiver {
+        Some(ident) => match &sig.receiver {
             None => quote!(super::#ident),
-            Some(_) => quote!(__self.#ident),
+            Some(receiver) => {
+                let receiver_type = &receiver.ident;
+                quote!(#receiver_type::#ident)
+            }
         },
         None => quote!(__extern),
     };

From 05e11cca1f6c2475f8f52f37155ba8de06ab5988 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 09:13:56 +0000
Subject: [PATCH 314/2232] Preserve span of self var in Receiver


---

diff --git a/gen/write.rs b/gen/write.rs
index 2cb8b51..a8e3fd4 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -51,7 +51,7 @@ pub(super) fn gen(
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
-                    .entry(&receiver.ident)
+                    .entry(&receiver.ty)
                     .or_insert_with(Vec::new)
                     .push(efn);
             }
@@ -372,7 +372,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ident);
+        write!(out, "{} &self", receiver.ty);
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -396,7 +396,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write_return_type(out, &efn.ret);
     match &efn.receiver {
         None => write!(out, "(*{}$)(", efn.ident),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ident, efn.ident),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -413,7 +413,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     write!(out, " = ");
     match &efn.receiver {
         None => write!(out, "{}", efn.ident),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ident, efn.ident),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -539,7 +539,7 @@ fn write_rust_function_decl_impl(
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ident);
+        write!(out, "{} &self", receiver.ty);
         needs_comma = true;
     }
     for arg in &sig.args {
@@ -572,7 +572,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     let local_name = match &efn.sig.receiver {
         None => efn.ident.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ident, efn.ident),
+        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
     };
     let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 207682e..4841794 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -302,7 +302,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     match &efn.receiver {
         None => function_shim,
         Some(receiver) => {
-            let receiver_type = &receiver.ident;
+            let receiver_type = &receiver.ty;
             quote!(impl #receiver_type { #function_shim })
         }
     }
@@ -414,7 +414,7 @@ fn expand_rust_function_shim_impl(
         Some(ident) => match &sig.receiver {
             None => quote!(super::#ident),
             Some(receiver) => {
-                let receiver_type = &receiver.ident;
+                let receiver_type = &receiver.ty;
                 quote!(#receiver_type::#ident)
             }
         },
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 3509899..7b2d746 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -187,14 +187,16 @@ impl PartialEq for Receiver {
         let Receiver {
             ampersand: _,
             mutability,
-            ident,
+            var: _,
+            ty,
         } = self;
         let Receiver {
             ampersand: _,
             mutability: mutability2,
-            ident: ident2,
+            var: _,
+            ty: ty2,
         } = other;
-        mutability.is_some() == mutability2.is_some() && ident == ident2
+        mutability.is_some() == mutability2.is_some() && ty == ty2
     }
 }
 
@@ -203,9 +205,10 @@ impl Hash for Receiver {
         let Receiver {
             ampersand: _,
             mutability,
-            ident,
+            var: _,
+            ty,
         } = self;
         mutability.is_some().hash(state);
-        ident.hash(state);
+        ty.hash(state);
     }
 }
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 6f4e0d8..1380704 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -13,7 +13,7 @@ macro_rules! join {
 
 pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
     match &efn.receiver {
-        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ident, efn.ident),
+        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident),
         None => join!(namespace, CXXBRIDGE, efn.ident),
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b160e5a..3a2bb93 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -77,7 +77,8 @@ pub struct Var {
 pub struct Receiver {
     pub ampersand: Token![&],
     pub mutability: Option<Token![mut]>,
-    pub ident: Ident,
+    pub var: Token![self],
+    pub ty: Ident,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7bd36de..d8bc0e5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -182,7 +182,8 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
                         receiver = Some(Receiver {
                             ampersand: reference.ampersand,
                             mutability: reference.mutability,
-                            ident,
+                            var: Token![self](ident.span()),
+                            ty: ident,
                         });
                         continue;
                     }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 784de37..6e3db9b 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -102,6 +102,6 @@ impl ToTokens for Receiver {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.ampersand.to_tokens(tokens);
         self.mutability.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
+        self.ty.to_tokens(tokens);
     }
 }

From f9ffb93365e0511fb4e66315809e110f7b1e6b32 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 09:23:14 +0000
Subject: [PATCH 315/2232] Preserve all the spans when manipulating receiver


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4841794..350ee97 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -5,7 +5,7 @@ use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
-use quote::{format_ident, quote, quote_spanned};
+use quote::{format_ident, quote, quote_spanned, ToTokens};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
@@ -164,8 +164,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
+        let ampersand = receiver.ampersand;
         let mutability = receiver.mutability;
-        quote!(&#mutability self)
+        let var = receiver.var;
+        quote!(#ampersand #mutability #var)
     });
     let args = efn.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
@@ -179,7 +181,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         expand_return_type(&efn.ret)
     };
     let indirect_return = indirect_return(efn, types);
-    let receiver_var = efn.receiver.iter().map(|_| quote!(self));
+    let receiver_var = efn
+        .receiver
+        .iter()
+        .map(|receiver| receiver.var.to_token_stream());
     let arg_vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
@@ -374,10 +379,14 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
+    let receiver_var = sig
+        .receiver
+        .as_ref()
+        .map(|receiver| quote_spanned!(receiver.var.span=> __self));
     let receiver = sig
         .receiver
-        .iter()
-        .map(|receiver| quote!(__self: #receiver));
+        .as_ref()
+        .map(|receiver| quote!(#receiver_var: #receiver));
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -387,9 +396,8 @@ fn expand_rust_function_shim_impl(
             quote!(#ident: #ty)
         }
     });
-    let all_args = receiver.chain(args);
+    let all_args = receiver.into_iter().chain(args);
 
-    let receiver_var = sig.receiver.iter().map(|_| quote!(__self));
     let arg_vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
@@ -408,7 +416,7 @@ fn expand_rust_function_shim_impl(
             _ => quote!(#ident),
         }
     });
-    let vars = receiver_var.chain(arg_vars);
+    let vars = receiver_var.into_iter().chain(arg_vars);
 
     let mut call = match invoke {
         Some(ident) => match &sig.receiver {

From 16b9068d7b9a41d61e95d472abea7af3ba2cbb24 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 20:26:16 +0000
Subject: [PATCH 316/2232] Bump bazel rules_rust to pull in optional extra_target_triples


---

diff --git a/WORKSPACE b/WORKSPACE
index f39808c..501bde0 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "abc75a5b6c8eda46a3d141921841e3577e9707b32d4d5b5cc156f7b8b28631ad",
-    strip_prefix = "rules_rust-d97f99628439df8bec89f5b7bc439f9d43d1586b",
+    sha256 = "b83154a58f95618e06845b774b079000e0c39830e185db4c7bf46e79896cb3a1",
+    strip_prefix = "rules_rust-0deef6dd8180cd3bc610878558bb26921b4e8de1",
     # Master branch as of 2020-03-07
-    url = "https://github.com/bazelbuild/rules_rust/archive/d97f99628439df8bec89f5b7bc439f9d43d1586b.tar.gz",
+    url = "https://github.com/bazelbuild/rules_rust/archive/0deef6dd8180cd3bc610878558bb26921b4e8de1.tar.gz",
 )
 
 http_archive(
@@ -26,7 +26,6 @@ load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 rust_repository_set(
     name = "rust_1_43_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    extra_target_triples = [],
     iso_date = "2020-04-19",
     version = "beta",
 )
@@ -34,7 +33,6 @@ rust_repository_set(
 rust_repository_set(
     name = "rust_1_43_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
-    extra_target_triples = [],
     iso_date = "2020-04-19",
     version = "beta",
 )

From ce855186ae3de12ea08b5a6cb95aa0e9553a44d6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 20 2020 20:38:20 +0000
Subject: [PATCH 317/2232] Merge pull request #129 from dtolnay/bazel


Bump bazel rules_rust to pull in optional extra_target_triples
---

diff --git a/WORKSPACE b/WORKSPACE
index f39808c..501bde0 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "abc75a5b6c8eda46a3d141921841e3577e9707b32d4d5b5cc156f7b8b28631ad",
-    strip_prefix = "rules_rust-d97f99628439df8bec89f5b7bc439f9d43d1586b",
+    sha256 = "b83154a58f95618e06845b774b079000e0c39830e185db4c7bf46e79896cb3a1",
+    strip_prefix = "rules_rust-0deef6dd8180cd3bc610878558bb26921b4e8de1",
     # Master branch as of 2020-03-07
-    url = "https://github.com/bazelbuild/rules_rust/archive/d97f99628439df8bec89f5b7bc439f9d43d1586b.tar.gz",
+    url = "https://github.com/bazelbuild/rules_rust/archive/0deef6dd8180cd3bc610878558bb26921b4e8de1.tar.gz",
 )
 
 http_archive(
@@ -26,7 +26,6 @@ load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 rust_repository_set(
     name = "rust_1_43_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    extra_target_triples = [],
     iso_date = "2020-04-19",
     version = "beta",
 )
@@ -34,7 +33,6 @@ rust_repository_set(
 rust_repository_set(
     name = "rust_1_43_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
-    extra_target_triples = [],
     iso_date = "2020-04-19",
     version = "beta",
 )

From e1e969d06f092428ff8d82d3c262c326b0ecc5bf Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 22 2020 15:44:49 +0000
Subject: [PATCH 318/2232] Allow &self without a type when the block only has one type


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d8bc0e5..4e78588 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -91,16 +91,28 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         Lang::Rust => Api::RustFunction,
     };
 
-    let mut items = Vec::new();
+    let mut types = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
                 check_reserved_name(&foreign.ident)?;
                 let ety = parse_extern_type(foreign)?;
-                items.push(api_type(ety));
+                types.push(ety);
             }
+            _ => {}
+        }
+    }
+    let single_type = if types.len() == 1 {
+        Some(&types[0])
+    } else {
+        None
+    };
+    let mut items = Vec::new();
+    for foreign in &foreign_mod.items {
+        match foreign {
+            ForeignItem::Type(_) => {}
             ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang)?;
+                let efn = parse_extern_fn(foreign, lang, &single_type)?;
                 items.push(api_function(efn));
             }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -110,6 +122,7 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
             _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
         }
     }
+    items.extend(types.into_iter().map(|ety| api_type(ety)));
     Ok(items)
 }
 
@@ -141,7 +154,11 @@ fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
     })
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
+fn parse_extern_fn(
+    foreign_fn: &ForeignItemFn,
+    lang: Lang,
+    single_type: &Option<&ExternType>,
+) -> Result<ExternFn> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -161,8 +178,19 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     for arg in foreign_fn.sig.inputs.pairs() {
         let (arg, comma) = arg.into_tuple();
         match arg {
-            FnArg::Receiver(receiver) => {
-                return Err(Error::new_spanned(receiver, "unsupported signature"))
+            FnArg::Receiver(rcvr) => {
+                if let Some(ety) = single_type {
+                    if let Some((and, _)) = rcvr.reference {
+                        receiver = Some(Receiver {
+                            ampersand: and,
+                            mutability: rcvr.mutability,
+                            var: Token![self](ety.ident.span()),
+                            ty: ety.ident.clone(),
+                        });
+                        continue;
+                    }
+                }
+                return Err(Error::new_spanned(rcvr, "unsupported signature"));
             }
             FnArg::Typed(arg) => {
                 let ident = match arg.pat.as_ref() {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4da5740..efdd1fa 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -52,6 +52,8 @@ pub mod ffi {
 
         fn get(self: &C) -> usize;
         fn set(self: &mut C, n: usize) -> usize;
+        fn get2(&self) -> usize;
+        fn set2(&mut self, n: usize) -> usize;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8893ee8..619485a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -15,11 +15,18 @@ C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
 
+size_t C::get2() const { return this->n; }
+
 size_t C::set(size_t n) {
   this->n = n;
   return this->n;
 }
 
+size_t C::set2(size_t n) {
+  this->n = n;
+  return this->n;
+}
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 43ac229..ed6d541 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -13,6 +13,8 @@ public:
   C(size_t n);
   size_t get() const;
   size_t set(size_t n);
+  size_t get2() const;
+  size_t set2(size_t n);
 
 private:
   size_t n;
diff --git a/tests/test.rs b/tests/test.rs
index eb14d36..1cd85df 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -102,8 +102,8 @@ fn test_c_method_calls() {
     assert_eq!(2020, old_value);
     assert_eq!(2021, unique_ptr.set(2021));
     assert_eq!(2021, unique_ptr.get());
-    assert_eq!(old_value, unique_ptr.set(old_value));
-    assert_eq!(old_value, unique_ptr.get())
+    assert_eq!(old_value, unique_ptr.set2(old_value));
+    assert_eq!(old_value, unique_ptr.get2())
 }
 
 #[no_mangle]

From c0a51946c082052738e218297a4aa6eb87a6d41c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 19:55:56 +0000
Subject: [PATCH 319/2232] Merge pull request #131 from jgalenson/methods


Allow &self without a type when the block only has one type
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d8bc0e5..4e78588 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -91,16 +91,28 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         Lang::Rust => Api::RustFunction,
     };
 
-    let mut items = Vec::new();
+    let mut types = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
                 check_reserved_name(&foreign.ident)?;
                 let ety = parse_extern_type(foreign)?;
-                items.push(api_type(ety));
+                types.push(ety);
             }
+            _ => {}
+        }
+    }
+    let single_type = if types.len() == 1 {
+        Some(&types[0])
+    } else {
+        None
+    };
+    let mut items = Vec::new();
+    for foreign in &foreign_mod.items {
+        match foreign {
+            ForeignItem::Type(_) => {}
             ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang)?;
+                let efn = parse_extern_fn(foreign, lang, &single_type)?;
                 items.push(api_function(efn));
             }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -110,6 +122,7 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
             _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
         }
     }
+    items.extend(types.into_iter().map(|ety| api_type(ety)));
     Ok(items)
 }
 
@@ -141,7 +154,11 @@ fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
     })
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
+fn parse_extern_fn(
+    foreign_fn: &ForeignItemFn,
+    lang: Lang,
+    single_type: &Option<&ExternType>,
+) -> Result<ExternFn> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -161,8 +178,19 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     for arg in foreign_fn.sig.inputs.pairs() {
         let (arg, comma) = arg.into_tuple();
         match arg {
-            FnArg::Receiver(receiver) => {
-                return Err(Error::new_spanned(receiver, "unsupported signature"))
+            FnArg::Receiver(rcvr) => {
+                if let Some(ety) = single_type {
+                    if let Some((and, _)) = rcvr.reference {
+                        receiver = Some(Receiver {
+                            ampersand: and,
+                            mutability: rcvr.mutability,
+                            var: Token![self](ety.ident.span()),
+                            ty: ety.ident.clone(),
+                        });
+                        continue;
+                    }
+                }
+                return Err(Error::new_spanned(rcvr, "unsupported signature"));
             }
             FnArg::Typed(arg) => {
                 let ident = match arg.pat.as_ref() {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4da5740..efdd1fa 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -52,6 +52,8 @@ pub mod ffi {
 
         fn get(self: &C) -> usize;
         fn set(self: &mut C, n: usize) -> usize;
+        fn get2(&self) -> usize;
+        fn set2(&mut self, n: usize) -> usize;
     }
 
     extern "Rust" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8893ee8..619485a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -15,11 +15,18 @@ C::C(size_t n) : n(n) {}
 
 size_t C::get() const { return this->n; }
 
+size_t C::get2() const { return this->n; }
+
 size_t C::set(size_t n) {
   this->n = n;
   return this->n;
 }
 
+size_t C::set2(size_t n) {
+  this->n = n;
+  return this->n;
+}
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 43ac229..ed6d541 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -13,6 +13,8 @@ public:
   C(size_t n);
   size_t get() const;
   size_t set(size_t n);
+  size_t get2() const;
+  size_t set2(size_t n);
 
 private:
   size_t n;
diff --git a/tests/test.rs b/tests/test.rs
index eb14d36..1cd85df 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -102,8 +102,8 @@ fn test_c_method_calls() {
     assert_eq!(2020, old_value);
     assert_eq!(2021, unique_ptr.set(2021));
     assert_eq!(2021, unique_ptr.get());
-    assert_eq!(old_value, unique_ptr.set(old_value));
-    assert_eq!(old_value, unique_ptr.get())
+    assert_eq!(old_value, unique_ptr.set2(old_value));
+    assert_eq!(old_value, unique_ptr.get2())
 }
 
 #[no_mangle]

From 1dd11a16b4505f30933a96d7f4185780164197fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 22:33:54 +0000
Subject: [PATCH 320/2232] Touch up &self shorthand PR


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 4e78588..8cc4e2a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -93,13 +93,10 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
 
     let mut types = Vec::new();
     for foreign in &foreign_mod.items {
-        match foreign {
-            ForeignItem::Type(foreign) => {
-                check_reserved_name(&foreign.ident)?;
-                let ety = parse_extern_type(foreign)?;
-                types.push(ety);
-            }
-            _ => {}
+        if let ForeignItem::Type(foreign) = foreign {
+            check_reserved_name(&foreign.ident)?;
+            let ety = parse_extern_type(foreign)?;
+            types.push(ety);
         }
     }
     let single_type = if types.len() == 1 {
@@ -178,19 +175,19 @@ fn parse_extern_fn(
     for arg in foreign_fn.sig.inputs.pairs() {
         let (arg, comma) = arg.into_tuple();
         match arg {
-            FnArg::Receiver(rcvr) => {
+            FnArg::Receiver(arg) => {
                 if let Some(ety) = single_type {
-                    if let Some((and, _)) = rcvr.reference {
+                    if let Some((ampersand, _)) = arg.reference {
                         receiver = Some(Receiver {
-                            ampersand: and,
-                            mutability: rcvr.mutability,
+                            ampersand,
+                            mutability: arg.mutability,
                             var: Token![self](ety.ident.span()),
                             ty: ety.ident.clone(),
                         });
                         continue;
                     }
                 }
-                return Err(Error::new_spanned(rcvr, "unsupported signature"));
+                return Err(Error::new_spanned(arg, "unsupported signature"));
             }
             FnArg::Typed(arg) => {
                 let ident = match arg.pat.as_ref() {

From 18ba92ce821ff9935bb42cdf74defd9909940e63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:22:47 +0000
Subject: [PATCH 321/2232] Split Receiver's ToTokens into a wrapper type


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 350ee97..36f25c5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -126,7 +126,10 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
-    let receiver = efn.receiver.iter().map(|receiver| quote!(_: #receiver));
+    let receiver = efn.receiver.iter().map(|receiver| {
+        let receiver_type = receiver.ty();
+        quote!(_: #receiver_type)
+    });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
@@ -383,10 +386,10 @@ fn expand_rust_function_shim_impl(
         .receiver
         .as_ref()
         .map(|receiver| quote_spanned!(receiver.var.span=> __self));
-    let receiver = sig
-        .receiver
-        .as_ref()
-        .map(|receiver| quote!(#receiver_var: #receiver));
+    let receiver = sig.receiver.as_ref().map(|receiver| {
+        let receiver_type = receiver.ty();
+        quote!(#receiver_var: #receiver_type)
+    });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         let ty = expand_extern_type(&arg.ty);
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 6e3db9b..08c966a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -98,10 +98,19 @@ impl ToTokens for Signature {
     }
 }
 
-impl ToTokens for Receiver {
+pub struct ReceiverType<'a>(&'a Receiver);
+
+impl Receiver {
+    // &TheType
+    pub fn ty(&self) -> ReceiverType {
+        ReceiverType(self)
+    }
+}
+
+impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.ampersand.to_tokens(tokens);
-        self.mutability.to_tokens(tokens);
-        self.ty.to_tokens(tokens);
+        self.0.ampersand.to_tokens(tokens);
+        self.0.mutability.to_tokens(tokens);
+        self.0.ty.to_tokens(tokens);
     }
 }

From 0bd50fa93139da55d2c0b13aaa604805e0da2e76 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:23:39 +0000
Subject: [PATCH 322/2232] Preserve lifetimes on parsed references


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 7b2d746..657fdb3 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -86,15 +86,17 @@ impl PartialEq for Ref {
     fn eq(&self, other: &Ref) -> bool {
         let Ref {
             ampersand: _,
+            lifetime,
             mutability,
             inner,
         } = self;
         let Ref {
             ampersand: _,
+            lifetime: lifetime2,
             mutability: mutability2,
             inner: inner2,
         } = other;
-        mutability.is_some() == mutability2.is_some() && inner == inner2
+        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && inner == inner2
     }
 }
 
@@ -102,9 +104,11 @@ impl Hash for Ref {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ref {
             ampersand: _,
+            lifetime,
             mutability,
             inner,
         } = self;
+        lifetime.hash(state);
         mutability.is_some().hash(state);
         inner.hash(state);
     }
@@ -186,17 +190,19 @@ impl PartialEq for Receiver {
     fn eq(&self, other: &Receiver) -> bool {
         let Receiver {
             ampersand: _,
+            lifetime,
             mutability,
             var: _,
             ty,
         } = self;
         let Receiver {
             ampersand: _,
+            lifetime: lifetime2,
             mutability: mutability2,
             var: _,
             ty: ty2,
         } = other;
-        mutability.is_some() == mutability2.is_some() && ty == ty2
+        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
     }
 }
 
@@ -204,10 +210,12 @@ impl Hash for Receiver {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Receiver {
             ampersand: _,
+            lifetime,
             mutability,
             var: _,
             ty,
         } = self;
+        lifetime.hash(state);
         mutability.is_some().hash(state);
         ty.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3a2bb93..cf811cf 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -19,7 +19,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{LitStr, Token};
+use syn::{Lifetime, LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -76,6 +76,7 @@ pub struct Var {
 
 pub struct Receiver {
     pub ampersand: Token![&],
+    pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
     pub ty: Ident,
@@ -102,6 +103,7 @@ pub struct Ty1 {
 
 pub struct Ref {
     pub ampersand: Token![&],
+    pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub inner: Type,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8cc4e2a..aed77d8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -177,9 +177,10 @@ fn parse_extern_fn(
         match arg {
             FnArg::Receiver(arg) => {
                 if let Some(ety) = single_type {
-                    if let Some((ampersand, _)) = arg.reference {
+                    if let Some((ampersand, lifetime)) = &arg.reference {
                         receiver = Some(Receiver {
-                            ampersand,
+                            ampersand: *ampersand,
+                            lifetime: lifetime.clone(),
                             mutability: arg.mutability,
                             var: Token![self](ety.ident.span()),
                             ty: ety.ident.clone(),
@@ -206,6 +207,7 @@ fn parse_extern_fn(
                     if let Type::Ident(ident) = reference.inner {
                         receiver = Some(Receiver {
                             ampersand: reference.ampersand,
+                            lifetime: reference.lifetime,
                             mutability: reference.mutability,
                             var: Token![self](ident.span()),
                             ty: ident,
@@ -273,6 +275,7 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     };
     Ok(which(Box::new(Ref {
         ampersand: ty.and_token,
+        lifetime: ty.lifetime.clone(),
         mutability: ty.mutability,
         inner,
     })))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 08c966a..26bb3d1 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -47,6 +47,7 @@ impl ToTokens for Ty1 {
 impl ToTokens for Ref {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.ampersand.to_tokens(tokens);
+        self.lifetime.to_tokens(tokens);
         self.mutability.to_tokens(tokens);
         self.inner.to_tokens(tokens);
     }
@@ -110,6 +111,7 @@ impl Receiver {
 impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.0.ampersand.to_tokens(tokens);
+        self.0.lifetime.to_tokens(tokens);
         self.0.mutability.to_tokens(tokens);
         self.0.ty.to_tokens(tokens);
     }

From 62d360ccaf3b73ec145adebee53a5d7b227560cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:26:21 +0000
Subject: [PATCH 323/2232] Preserve whether Receiver was shorthand for error reporting


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 657fdb3..acc99ab 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -194,6 +194,7 @@ impl PartialEq for Receiver {
             mutability,
             var: _,
             ty,
+            shorthand: _,
         } = self;
         let Receiver {
             ampersand: _,
@@ -201,6 +202,7 @@ impl PartialEq for Receiver {
             mutability: mutability2,
             var: _,
             ty: ty2,
+            shorthand: _,
         } = other;
         lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
     }
@@ -214,6 +216,7 @@ impl Hash for Receiver {
             mutability,
             var: _,
             ty,
+            shorthand: _,
         } = self;
         lifetime.hash(state);
         mutability.is_some().hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index cf811cf..ab5cecc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -80,6 +80,7 @@ pub struct Receiver {
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
     pub ty: Ident,
+    pub shorthand: bool,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index aed77d8..71e0c76 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -184,6 +184,7 @@ fn parse_extern_fn(
                             mutability: arg.mutability,
                             var: Token![self](ety.ident.span()),
                             ty: ety.ident.clone(),
+                            shorthand: true,
                         });
                         continue;
                     }
@@ -211,6 +212,7 @@ fn parse_extern_fn(
                             mutability: reference.mutability,
                             var: Token![self](ident.span()),
                             ty: ident,
+                            shorthand: false,
                         });
                         continue;
                     }

From bfad5f759fbdcbce1c28b66716e9e44cd1101c3a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:36:55 +0000
Subject: [PATCH 324/2232] Preserve span on Receiver shorthand `self` token


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 71e0c76..bdccbda 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -182,7 +182,7 @@ fn parse_extern_fn(
                             ampersand: *ampersand,
                             lifetime: lifetime.clone(),
                             mutability: arg.mutability,
-                            var: Token![self](ety.ident.span()),
+                            var: arg.self_token,
                             ty: ety.ident.clone(),
                             shorthand: true,
                         });

From d763f4cd6457a3b0ec061b56b2af6b6def2f0907 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:39:44 +0000
Subject: [PATCH 325/2232] Reject explicit lifetimes in a reference type


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 3b6937a..fa51ed3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Slice, Struct, Ty1, Type, Types};
+use crate::syntax::{
+    error, ident, Api, ExternFn, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
@@ -100,6 +102,10 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
+    if ty.lifetime.is_some() {
+        cx.error(ty, "references with explicit lifetimes are not supported");
+    }
+
     match ty.inner {
         Type::Fn(_) | Type::Void(_) => {}
         _ => return,
@@ -134,6 +140,13 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 }
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
+    if let Some(receiver) = &efn.receiver {
+        if receiver.lifetime.is_some() {
+            let span = span_for_receiver_error(receiver);
+            cx.error(span, "references with explicit lifetimes are not supported");
+        }
+    }
+
     for arg in &efn.args {
         if is_unsized(cx, &arg.ty) {
             let desc = describe(cx, &arg.ty);
@@ -223,6 +236,19 @@ fn span_for_struct_error(strct: &Struct) -> TokenStream {
     quote!(#struct_token #brace_token)
 }
 
+fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
+    let ampersand = receiver.ampersand;
+    let lifetime = &receiver.lifetime;
+    let mutability = receiver.mutability;
+    if receiver.shorthand {
+        let var = receiver.var;
+        quote!(#ampersand #lifetime #mutability #var)
+    } else {
+        let ty = &receiver.ty;
+        quote!(#ampersand #lifetime #mutability #ty)
+    }
+}
+
 fn combine_errors(errors: Vec<Error>) -> Result<()> {
     let mut iter = errors.into_iter();
     let mut all_errors = match iter.next() {

From 6d9f4aab20245ac30ea1e222f268833ddd5d2284 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:39:44 +0000
Subject: [PATCH 326/2232] Add ui test for disallowed lifetimes


---

diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
new file mode 100644
index 0000000..ee39fef
--- /dev/null
+++ b/tests/ui/disallow_lifetime.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type C;
+        fn f(&'static self);
+    }
+
+    extern "Rust" {
+        fn f(string: &'a String);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/disallow_lifetime.stderr b/tests/ui/disallow_lifetime.stderr
new file mode 100644
index 0000000..d7c42e4
--- /dev/null
+++ b/tests/ui/disallow_lifetime.stderr
@@ -0,0 +1,11 @@
+error: references with explicit lifetimes are not supported
+ --> $DIR/disallow_lifetime.rs:9:22
+  |
+9 |         fn f(string: &'a String);
+  |                      ^^^^^^^^^^
+
+error: references with explicit lifetimes are not supported
+ --> $DIR/disallow_lifetime.rs:5:14
+  |
+5 |         fn f(&'static self);
+  |              ^^^^^^^^^^^^^

From 3273a5fb9b966d164055cdf757addb1dfc8c97ac Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:51:43 +0000
Subject: [PATCH 327/2232] Merge pull request #133 from dtolnay/lifetimes


Trigger error on explicitly specified lifetimes in a reference type
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 3b6937a..fa51ed3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::{error, ident, Api, ExternFn, Lang, Ref, Slice, Struct, Ty1, Type, Types};
+use crate::syntax::{
+    error, ident, Api, ExternFn, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+};
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
@@ -100,6 +102,10 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
+    if ty.lifetime.is_some() {
+        cx.error(ty, "references with explicit lifetimes are not supported");
+    }
+
     match ty.inner {
         Type::Fn(_) | Type::Void(_) => {}
         _ => return,
@@ -134,6 +140,13 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 }
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
+    if let Some(receiver) = &efn.receiver {
+        if receiver.lifetime.is_some() {
+            let span = span_for_receiver_error(receiver);
+            cx.error(span, "references with explicit lifetimes are not supported");
+        }
+    }
+
     for arg in &efn.args {
         if is_unsized(cx, &arg.ty) {
             let desc = describe(cx, &arg.ty);
@@ -223,6 +236,19 @@ fn span_for_struct_error(strct: &Struct) -> TokenStream {
     quote!(#struct_token #brace_token)
 }
 
+fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
+    let ampersand = receiver.ampersand;
+    let lifetime = &receiver.lifetime;
+    let mutability = receiver.mutability;
+    if receiver.shorthand {
+        let var = receiver.var;
+        quote!(#ampersand #lifetime #mutability #var)
+    } else {
+        let ty = &receiver.ty;
+        quote!(#ampersand #lifetime #mutability #ty)
+    }
+}
+
 fn combine_errors(errors: Vec<Error>) -> Result<()> {
     let mut iter = errors.into_iter();
     let mut all_errors = match iter.next() {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 7b2d746..acc99ab 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -86,15 +86,17 @@ impl PartialEq for Ref {
     fn eq(&self, other: &Ref) -> bool {
         let Ref {
             ampersand: _,
+            lifetime,
             mutability,
             inner,
         } = self;
         let Ref {
             ampersand: _,
+            lifetime: lifetime2,
             mutability: mutability2,
             inner: inner2,
         } = other;
-        mutability.is_some() == mutability2.is_some() && inner == inner2
+        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && inner == inner2
     }
 }
 
@@ -102,9 +104,11 @@ impl Hash for Ref {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ref {
             ampersand: _,
+            lifetime,
             mutability,
             inner,
         } = self;
+        lifetime.hash(state);
         mutability.is_some().hash(state);
         inner.hash(state);
     }
@@ -186,17 +190,21 @@ impl PartialEq for Receiver {
     fn eq(&self, other: &Receiver) -> bool {
         let Receiver {
             ampersand: _,
+            lifetime,
             mutability,
             var: _,
             ty,
+            shorthand: _,
         } = self;
         let Receiver {
             ampersand: _,
+            lifetime: lifetime2,
             mutability: mutability2,
             var: _,
             ty: ty2,
+            shorthand: _,
         } = other;
-        mutability.is_some() == mutability2.is_some() && ty == ty2
+        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
     }
 }
 
@@ -204,10 +212,13 @@ impl Hash for Receiver {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Receiver {
             ampersand: _,
+            lifetime,
             mutability,
             var: _,
             ty,
+            shorthand: _,
         } = self;
+        lifetime.hash(state);
         mutability.is_some().hash(state);
         ty.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3a2bb93..ab5cecc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -19,7 +19,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{LitStr, Token};
+use syn::{Lifetime, LitStr, Token};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -76,9 +76,11 @@ pub struct Var {
 
 pub struct Receiver {
     pub ampersand: Token![&],
+    pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
     pub ty: Ident,
+    pub shorthand: bool,
 }
 
 pub enum Type {
@@ -102,6 +104,7 @@ pub struct Ty1 {
 
 pub struct Ref {
     pub ampersand: Token![&],
+    pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub inner: Type,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8cc4e2a..bdccbda 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -177,12 +177,14 @@ fn parse_extern_fn(
         match arg {
             FnArg::Receiver(arg) => {
                 if let Some(ety) = single_type {
-                    if let Some((ampersand, _)) = arg.reference {
+                    if let Some((ampersand, lifetime)) = &arg.reference {
                         receiver = Some(Receiver {
-                            ampersand,
+                            ampersand: *ampersand,
+                            lifetime: lifetime.clone(),
                             mutability: arg.mutability,
-                            var: Token![self](ety.ident.span()),
+                            var: arg.self_token,
                             ty: ety.ident.clone(),
+                            shorthand: true,
                         });
                         continue;
                     }
@@ -206,9 +208,11 @@ fn parse_extern_fn(
                     if let Type::Ident(ident) = reference.inner {
                         receiver = Some(Receiver {
                             ampersand: reference.ampersand,
+                            lifetime: reference.lifetime,
                             mutability: reference.mutability,
                             var: Token![self](ident.span()),
                             ty: ident,
+                            shorthand: false,
                         });
                         continue;
                     }
@@ -273,6 +277,7 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     };
     Ok(which(Box::new(Ref {
         ampersand: ty.and_token,
+        lifetime: ty.lifetime.clone(),
         mutability: ty.mutability,
         inner,
     })))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 08c966a..26bb3d1 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -47,6 +47,7 @@ impl ToTokens for Ty1 {
 impl ToTokens for Ref {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.ampersand.to_tokens(tokens);
+        self.lifetime.to_tokens(tokens);
         self.mutability.to_tokens(tokens);
         self.inner.to_tokens(tokens);
     }
@@ -110,6 +111,7 @@ impl Receiver {
 impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.0.ampersand.to_tokens(tokens);
+        self.0.lifetime.to_tokens(tokens);
         self.0.mutability.to_tokens(tokens);
         self.0.ty.to_tokens(tokens);
     }
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
new file mode 100644
index 0000000..ee39fef
--- /dev/null
+++ b/tests/ui/disallow_lifetime.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type C;
+        fn f(&'static self);
+    }
+
+    extern "Rust" {
+        fn f(string: &'a String);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/disallow_lifetime.stderr b/tests/ui/disallow_lifetime.stderr
new file mode 100644
index 0000000..d7c42e4
--- /dev/null
+++ b/tests/ui/disallow_lifetime.stderr
@@ -0,0 +1,11 @@
+error: references with explicit lifetimes are not supported
+ --> $DIR/disallow_lifetime.rs:9:22
+  |
+9 |         fn f(string: &'a String);
+  |                      ^^^^^^^^^^
+
+error: references with explicit lifetimes are not supported
+ --> $DIR/disallow_lifetime.rs:5:14
+  |
+5 |         fn f(&'static self);
+  |              ^^^^^^^^^^^^^

From 8b60bf170bc4a96804d3c7817c3903191dc3ccdd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:54:15 +0000
Subject: [PATCH 328/2232] Reject unrecognized idents in receiver's type


---

diff --git a/syntax/check.rs b/syntax/check.rs
index fa51ed3..f6e46fd 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -141,6 +141,14 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
+        if !cx.types.structs.contains_key(&receiver.ty)
+            && !cx.types.cxx.contains(&receiver.ty)
+            && !cx.types.rust.contains(&receiver.ty)
+        {
+            let span = span_for_receiver_error(receiver);
+            cx.error(span, "unrecognized receiver type");
+        }
+
         if receiver.lifetime.is_some() {
             let span = span_for_receiver_error(receiver);
             cx.error(span, "references with explicit lifetimes are not supported");

From 7a03847db2760b59104b02e798739b224a44f019 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 22 2020 23:54:34 +0000
Subject: [PATCH 329/2232] Add ui test for unrecognized receiver type


---

diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
new file mode 100644
index 0000000..823bfcf
--- /dev/null
+++ b/tests/ui/unrecognized_receiver.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        fn f(self: &Unrecognized);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unrecognized_receiver.stderr b/tests/ui/unrecognized_receiver.stderr
new file mode 100644
index 0000000..a44bec1
--- /dev/null
+++ b/tests/ui/unrecognized_receiver.stderr
@@ -0,0 +1,5 @@
+error: unrecognized receiver type
+ --> $DIR/unrecognized_receiver.rs:4:20
+  |
+4 |         fn f(self: &Unrecognized);
+  |                    ^^^^^^^^^^^^^

From c5e570bedb77399d97f2c8c44a71fd84e7ef6b47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 00:10:12 +0000
Subject: [PATCH 330/2232] Merge pull request #134 from dtolnay/receiver


Trigger error on unrecognized ident in receiver's type
---

diff --git a/syntax/check.rs b/syntax/check.rs
index fa51ed3..f6e46fd 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -141,6 +141,14 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
+        if !cx.types.structs.contains_key(&receiver.ty)
+            && !cx.types.cxx.contains(&receiver.ty)
+            && !cx.types.rust.contains(&receiver.ty)
+        {
+            let span = span_for_receiver_error(receiver);
+            cx.error(span, "unrecognized receiver type");
+        }
+
         if receiver.lifetime.is_some() {
             let span = span_for_receiver_error(receiver);
             cx.error(span, "references with explicit lifetimes are not supported");
diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
new file mode 100644
index 0000000..823bfcf
--- /dev/null
+++ b/tests/ui/unrecognized_receiver.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        fn f(self: &Unrecognized);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unrecognized_receiver.stderr b/tests/ui/unrecognized_receiver.stderr
new file mode 100644
index 0000000..a44bec1
--- /dev/null
+++ b/tests/ui/unrecognized_receiver.stderr
@@ -0,0 +1,5 @@
+error: unrecognized receiver type
+ --> $DIR/unrecognized_receiver.rs:4:20
+  |
+4 |         fn f(self: &Unrecognized);
+  |                    ^^^^^^^^^^^^^

From 0b368ae3412aceddb970da978cd4771f6b818a54 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 00:55:09 +0000
Subject: [PATCH 331/2232] Defer error on restricted type names


---

diff --git a/syntax/check.rs b/syntax/check.rs
index f6e46fd..0d25e77 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{
-    error, ident, Api, ExternFn, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+    error, ident, Api, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -39,6 +39,7 @@ fn do_typecheck(cx: &mut Check) {
     for api in cx.apis {
         match api {
             Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
         }
@@ -119,6 +120,8 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
+    check_reserved_name(cx, &strct.ident);
+
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
@@ -139,6 +142,10 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
     }
 }
 
+fn check_api_type(cx: &mut Check, ty: &ExternType) {
+    check_reserved_name(cx, &ty.ident);
+}
+
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
         if !cx.types.structs.contains_key(&receiver.ty)
@@ -228,6 +235,12 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
     }
 }
 
+fn check_reserved_name(cx: &mut Check, ident: &Ident) {
+    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
+        cx.error(ident, "reserved name");
+    }
+}
+
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index bdccbda..060f133 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,9 +1,8 @@
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Var,
+    attrs, error, Api, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, Struct,
+    Ty1, Type, Var,
 };
-use proc_macro2::Ident;
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
@@ -51,7 +50,6 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     attrs::parse(&item.attrs, &mut doc, Some(&mut derives))?;
-    check_reserved_name(&item.ident)?;
 
     let fields = match item.fields {
         Fields::Named(fields) => fields,
@@ -94,7 +92,6 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let mut types = Vec::new();
     for foreign in &foreign_mod.items {
         if let ForeignItem::Type(foreign) = foreign {
-            check_reserved_name(&foreign.ident)?;
             let ety = parse_extern_type(foreign)?;
             types.push(ety);
         }
@@ -396,11 +393,3 @@ fn parse_return_type(
         ty => Ok(Some(ty)),
     }
 }
-
-fn check_reserved_name(ident: &Ident) -> Result<()> {
-    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
-        Err(Error::new(ident.span(), "reserved name"))
-    } else {
-        Ok(())
-    }
-}

From 2dd73eaf03e14894b3dc003ee90e36eb13e24c50 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 00:56:27 +0000
Subject: [PATCH 332/2232] Add ui test for reserved type names


---

diff --git a/tests/ui/reserved_name.rs b/tests/ui/reserved_name.rs
new file mode 100644
index 0000000..27acca5
--- /dev/null
+++ b/tests/ui/reserved_name.rs
@@ -0,0 +1,16 @@
+#[cxx::bridge]
+mod ffi {
+    struct UniquePtr {
+        val: usize,
+    }
+
+    extern "C" {
+        type Box;
+    }
+
+    extern "Rust" {
+        type String;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/reserved_name.stderr b/tests/ui/reserved_name.stderr
new file mode 100644
index 0000000..6684771
--- /dev/null
+++ b/tests/ui/reserved_name.stderr
@@ -0,0 +1,17 @@
+error: reserved name
+ --> $DIR/reserved_name.rs:3:12
+  |
+3 |     struct UniquePtr {
+  |            ^^^^^^^^^
+
+error: reserved name
+ --> $DIR/reserved_name.rs:8:14
+  |
+8 |         type Box;
+  |              ^^^
+
+error: reserved name
+  --> $DIR/reserved_name.rs:12:14
+   |
+12 |         type String;
+   |              ^^^^^^

From 0b956da64a33c19eaa778194b49c61e062722010 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:05:11 +0000
Subject: [PATCH 333/2232] Merge pull request #135 from dtolnay/reserved


Defer error on restricted type names
---

diff --git a/syntax/check.rs b/syntax/check.rs
index f6e46fd..0d25e77 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{
-    error, ident, Api, ExternFn, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+    error, ident, Api, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -39,6 +39,7 @@ fn do_typecheck(cx: &mut Check) {
     for api in cx.apis {
         match api {
             Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
         }
@@ -119,6 +120,8 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
+    check_reserved_name(cx, &strct.ident);
+
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
@@ -139,6 +142,10 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
     }
 }
 
+fn check_api_type(cx: &mut Check, ty: &ExternType) {
+    check_reserved_name(cx, &ty.ident);
+}
+
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
         if !cx.types.structs.contains_key(&receiver.ty)
@@ -228,6 +235,12 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
     }
 }
 
+fn check_reserved_name(cx: &mut Check, ident: &Ident) {
+    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
+        cx.error(ident, "reserved name");
+    }
+}
+
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index bdccbda..060f133 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,9 +1,8 @@
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Var,
+    attrs, error, Api, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, Struct,
+    Ty1, Type, Var,
 };
-use proc_macro2::Ident;
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
@@ -51,7 +50,6 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     attrs::parse(&item.attrs, &mut doc, Some(&mut derives))?;
-    check_reserved_name(&item.ident)?;
 
     let fields = match item.fields {
         Fields::Named(fields) => fields,
@@ -94,7 +92,6 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let mut types = Vec::new();
     for foreign in &foreign_mod.items {
         if let ForeignItem::Type(foreign) = foreign {
-            check_reserved_name(&foreign.ident)?;
             let ety = parse_extern_type(foreign)?;
             types.push(ety);
         }
@@ -396,11 +393,3 @@ fn parse_return_type(
         ty => Ok(Some(ty)),
     }
 }
-
-fn check_reserved_name(ident: &Ident) -> Result<()> {
-    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
-        Err(Error::new(ident.span(), "reserved name"))
-    } else {
-        Ok(())
-    }
-}
diff --git a/tests/ui/reserved_name.rs b/tests/ui/reserved_name.rs
new file mode 100644
index 0000000..27acca5
--- /dev/null
+++ b/tests/ui/reserved_name.rs
@@ -0,0 +1,16 @@
+#[cxx::bridge]
+mod ffi {
+    struct UniquePtr {
+        val: usize,
+    }
+
+    extern "C" {
+        type Box;
+    }
+
+    extern "Rust" {
+        type String;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/reserved_name.stderr b/tests/ui/reserved_name.stderr
new file mode 100644
index 0000000..6684771
--- /dev/null
+++ b/tests/ui/reserved_name.stderr
@@ -0,0 +1,17 @@
+error: reserved name
+ --> $DIR/reserved_name.rs:3:12
+  |
+3 |     struct UniquePtr {
+  |            ^^^^^^^^^
+
+error: reserved name
+ --> $DIR/reserved_name.rs:8:14
+  |
+8 |         type Box;
+  |              ^^^
+
+error: reserved name
+  --> $DIR/reserved_name.rs:12:14
+   |
+12 |         type String;
+   |              ^^^^^^

From 9bfbea37c742dead8901f955c24ccc9c14ac7954 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:12:49 +0000
Subject: [PATCH 334/2232] Allow mutating signature through ExternFn


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index acc99ab..a2ce05b 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,7 +1,7 @@
 use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::hash::{Hash, Hasher};
 use std::mem;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut};
 
 impl Deref for ExternFn {
     type Target = Signature;
@@ -11,6 +11,12 @@ impl Deref for ExternFn {
     }
 }
 
+impl DerefMut for ExternFn {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.sig
+    }
+}
+
 impl Hash for Type {
     fn hash<H: Hasher>(&self, state: &mut H) {
         mem::discriminant(self).hash(state);

From a1f29c4e430c9bae1e316ef41b78f010b2b1141a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:20:58 +0000
Subject: [PATCH 335/2232] Defer computing the Self type of methods


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0d25e77..5e8cc09 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -148,16 +148,28 @@ fn check_api_type(cx: &mut Check, ty: &ExternType) {
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
-        if !cx.types.structs.contains_key(&receiver.ty)
+        let ref span = span_for_receiver_error(receiver);
+
+        if receiver.ty == "Self" {
+            let mutability = match receiver.mutability {
+                Some(_) => "mut ",
+                None => "",
+            };
+            let msg = format!(
+                "unnamed receiver type is only allowed if the surrounding \
+                 extern block contains exactly one extern type; \
+                 use `self: &{mutability}TheType`",
+                mutability = mutability,
+            );
+            cx.error(span, msg);
+        } else if !cx.types.structs.contains_key(&receiver.ty)
             && !cx.types.cxx.contains(&receiver.ty)
             && !cx.types.rust.contains(&receiver.ty)
         {
-            let span = span_for_receiver_error(receiver);
             cx.error(span, "unrecognized receiver type");
         }
 
         if receiver.lifetime.is_some() {
-            let span = span_for_receiver_error(receiver);
             cx.error(span, "references with explicit lifetimes are not supported");
         }
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 060f133..7d92b1b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -89,24 +89,15 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         Lang::Rust => Api::RustFunction,
     };
 
-    let mut types = Vec::new();
-    for foreign in &foreign_mod.items {
-        if let ForeignItem::Type(foreign) = foreign {
-            let ety = parse_extern_type(foreign)?;
-            types.push(ety);
-        }
-    }
-    let single_type = if types.len() == 1 {
-        Some(&types[0])
-    } else {
-        None
-    };
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(_) => {}
+            ForeignItem::Type(foreign) => {
+                let ety = parse_extern_type(foreign)?;
+                items.push(api_type(ety));
+            }
             ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang, &single_type)?;
+                let efn = parse_extern_fn(foreign, lang)?;
                 items.push(api_function(efn));
             }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -116,7 +107,24 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
             _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
         }
     }
-    items.extend(types.into_iter().map(|ety| api_type(ety)));
+
+    let mut types = items.iter().filter_map(|item| match item {
+        Api::CxxType(ty) | Api::RustType(ty) => Some(ty),
+        _ => None,
+    });
+    if let (Some(single_type), None) = (types.next(), types.next()) {
+        let single_type = single_type.ident.clone();
+        for item in &mut items {
+            if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
+                if let Some(receiver) = &mut efn.receiver {
+                    if receiver.ty == "Self" {
+                        receiver.ty = single_type.clone();
+                    }
+                }
+            }
+        }
+    }
+
     Ok(items)
 }
 
@@ -148,11 +156,7 @@ fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
     })
 }
 
-fn parse_extern_fn(
-    foreign_fn: &ForeignItemFn,
-    lang: Lang,
-    single_type: &Option<&ExternType>,
-) -> Result<ExternFn> {
+fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -173,18 +177,16 @@ fn parse_extern_fn(
         let (arg, comma) = arg.into_tuple();
         match arg {
             FnArg::Receiver(arg) => {
-                if let Some(ety) = single_type {
-                    if let Some((ampersand, lifetime)) = &arg.reference {
-                        receiver = Some(Receiver {
-                            ampersand: *ampersand,
-                            lifetime: lifetime.clone(),
-                            mutability: arg.mutability,
-                            var: arg.self_token,
-                            ty: ety.ident.clone(),
-                            shorthand: true,
-                        });
-                        continue;
-                    }
+                if let Some((ampersand, lifetime)) = &arg.reference {
+                    receiver = Some(Receiver {
+                        ampersand: *ampersand,
+                        lifetime: lifetime.clone(),
+                        mutability: arg.mutability,
+                        var: arg.self_token,
+                        ty: Token![Self](arg.self_token.span).into(),
+                        shorthand: true,
+                    });
+                    continue;
                 }
                 return Err(Error::new_spanned(arg, "unsupported signature"));
             }

From ab73957a4e7416f744da1355af274d81a8989602 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:25:43 +0000
Subject: [PATCH 336/2232] Add ui test for unnamed receiver type error message


---

diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
new file mode 100644
index 0000000..917e991
--- /dev/null
+++ b/tests/ui/unnamed_receiver.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type One;
+        type Two;
+        fn f(&mut self);
+    }
+
+    extern "Rust" {
+        fn f(self: &Self);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unnamed_receiver.stderr b/tests/ui/unnamed_receiver.stderr
new file mode 100644
index 0000000..e66d9e3
--- /dev/null
+++ b/tests/ui/unnamed_receiver.stderr
@@ -0,0 +1,11 @@
+error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &mut TheType`
+ --> $DIR/unnamed_receiver.rs:6:14
+  |
+6 |         fn f(&mut self);
+  |              ^^^^^^^^^
+
+error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &TheType`
+  --> $DIR/unnamed_receiver.rs:10:20
+   |
+10 |         fn f(self: &Self);
+   |                    ^^^^^

From 50f8896bedecc5d9ff1d560dc7833a71b62b4dbe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:35:22 +0000
Subject: [PATCH 337/2232] Merge pull request #136 from dtolnay/receiver


Defer computing the Self type of methods
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0d25e77..5e8cc09 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -148,16 +148,28 @@ fn check_api_type(cx: &mut Check, ty: &ExternType) {
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
-        if !cx.types.structs.contains_key(&receiver.ty)
+        let ref span = span_for_receiver_error(receiver);
+
+        if receiver.ty == "Self" {
+            let mutability = match receiver.mutability {
+                Some(_) => "mut ",
+                None => "",
+            };
+            let msg = format!(
+                "unnamed receiver type is only allowed if the surrounding \
+                 extern block contains exactly one extern type; \
+                 use `self: &{mutability}TheType`",
+                mutability = mutability,
+            );
+            cx.error(span, msg);
+        } else if !cx.types.structs.contains_key(&receiver.ty)
             && !cx.types.cxx.contains(&receiver.ty)
             && !cx.types.rust.contains(&receiver.ty)
         {
-            let span = span_for_receiver_error(receiver);
             cx.error(span, "unrecognized receiver type");
         }
 
         if receiver.lifetime.is_some() {
-            let span = span_for_receiver_error(receiver);
             cx.error(span, "references with explicit lifetimes are not supported");
         }
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 060f133..7d92b1b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -89,24 +89,15 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         Lang::Rust => Api::RustFunction,
     };
 
-    let mut types = Vec::new();
-    for foreign in &foreign_mod.items {
-        if let ForeignItem::Type(foreign) = foreign {
-            let ety = parse_extern_type(foreign)?;
-            types.push(ety);
-        }
-    }
-    let single_type = if types.len() == 1 {
-        Some(&types[0])
-    } else {
-        None
-    };
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(_) => {}
+            ForeignItem::Type(foreign) => {
+                let ety = parse_extern_type(foreign)?;
+                items.push(api_type(ety));
+            }
             ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang, &single_type)?;
+                let efn = parse_extern_fn(foreign, lang)?;
                 items.push(api_function(efn));
             }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -116,7 +107,24 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
             _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
         }
     }
-    items.extend(types.into_iter().map(|ety| api_type(ety)));
+
+    let mut types = items.iter().filter_map(|item| match item {
+        Api::CxxType(ty) | Api::RustType(ty) => Some(ty),
+        _ => None,
+    });
+    if let (Some(single_type), None) = (types.next(), types.next()) {
+        let single_type = single_type.ident.clone();
+        for item in &mut items {
+            if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
+                if let Some(receiver) = &mut efn.receiver {
+                    if receiver.ty == "Self" {
+                        receiver.ty = single_type.clone();
+                    }
+                }
+            }
+        }
+    }
+
     Ok(items)
 }
 
@@ -148,11 +156,7 @@ fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
     })
 }
 
-fn parse_extern_fn(
-    foreign_fn: &ForeignItemFn,
-    lang: Lang,
-    single_type: &Option<&ExternType>,
-) -> Result<ExternFn> {
+fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -173,18 +177,16 @@ fn parse_extern_fn(
         let (arg, comma) = arg.into_tuple();
         match arg {
             FnArg::Receiver(arg) => {
-                if let Some(ety) = single_type {
-                    if let Some((ampersand, lifetime)) = &arg.reference {
-                        receiver = Some(Receiver {
-                            ampersand: *ampersand,
-                            lifetime: lifetime.clone(),
-                            mutability: arg.mutability,
-                            var: arg.self_token,
-                            ty: ety.ident.clone(),
-                            shorthand: true,
-                        });
-                        continue;
-                    }
+                if let Some((ampersand, lifetime)) = &arg.reference {
+                    receiver = Some(Receiver {
+                        ampersand: *ampersand,
+                        lifetime: lifetime.clone(),
+                        mutability: arg.mutability,
+                        var: arg.self_token,
+                        ty: Token![Self](arg.self_token.span).into(),
+                        shorthand: true,
+                    });
+                    continue;
                 }
                 return Err(Error::new_spanned(arg, "unsupported signature"));
             }
diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
new file mode 100644
index 0000000..917e991
--- /dev/null
+++ b/tests/ui/unnamed_receiver.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type One;
+        type Two;
+        fn f(&mut self);
+    }
+
+    extern "Rust" {
+        fn f(self: &Self);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unnamed_receiver.stderr b/tests/ui/unnamed_receiver.stderr
new file mode 100644
index 0000000..e66d9e3
--- /dev/null
+++ b/tests/ui/unnamed_receiver.stderr
@@ -0,0 +1,11 @@
+error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &mut TheType`
+ --> $DIR/unnamed_receiver.rs:6:14
+  |
+6 |         fn f(&mut self);
+  |              ^^^^^^^^^
+
+error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &TheType`
+  --> $DIR/unnamed_receiver.rs:10:20
+   |
+10 |         fn f(self: &Self);
+   |                    ^^^^^

From 274da11cc3ccc540b193ceda7b45ca18f0f93c25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:38:00 +0000
Subject: [PATCH 338/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index af14713..9696c97 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -14,7 +14,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    srcs = glob(["vendor/cc-1.0.52/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -107,7 +107,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.13/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.14/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":clap",
@@ -118,7 +118,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.6/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.7/src/**"]),
     proc_macro = True,
     deps = [
         ":heck",
diff --git a/third-party/BUILD b/third-party/BUILD
index 25a3dd6..a3db8b1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -19,7 +19,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.50/src/**"]),
+    srcs = glob(["vendor/cc-1.0.52/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -112,7 +112,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.13/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.14/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
@@ -123,7 +123,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.6/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.7/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 71ad826..1aba3c9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -34,9 +34,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.50"
+version = "1.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
+checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
 
 [[package]]
 name = "clap"
@@ -135,9 +135,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.10"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
+checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
 dependencies = [
  "libc",
 ]
@@ -226,9 +226,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
+checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
 
 [[package]]
 name = "serde"
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.13"
+version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff6da2e8d107dfd7b74df5ef4d205c6aebee0706c647f6bc6a2d5789905c00fb"
+checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
 dependencies = [
  "clap",
  "lazy_static",
@@ -280,9 +280,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a489c87c08fbaf12e386665109dd13470dcc9c4583ea3e10dd2b4523e5ebd9ac"
+checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -422,9 +422,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
 dependencies = [
  "winapi",
 ]

From 0d645c7d4020229a04442bb9b389318386470c10 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 01:38:34 +0000
Subject: [PATCH 339/2232] Release 0.2.10


---

diff --git a/Cargo.toml b/Cargo.toml
index f9d9b52..e61fd2f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.9" # remember to update html_root_url
+version = "0.2.10" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.9", path = "macro" }
+cxxbridge-macro = { version = "=0.2.10", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 7c0739b..6ec328e 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.9"
+version = "0.2.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 386c9dd..ca0e326 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.9"
+version = "0.2.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 609db59..74e103a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.9")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.10")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1aba3c9..7158ff0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.9"
+version = "0.2.10"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.9"
+version = "0.2.10"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.9"
+version = "0.2.10"
 dependencies = [
  "cxx",
  "proc-macro2",

From 3deb2f9d2a4b23681d76d2a254903cc54aea5d7a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 02:16:38 +0000
Subject: [PATCH 340/2232] Remove checkboxes from readme in favor of filed issues


---

diff --git a/README.md b/README.md
index 508d43d..a8f4093 100644
--- a/README.md
+++ b/README.md
@@ -332,11 +332,8 @@ matter of designing a nice API for each in its non-native language.
 ## Remaining work
 
 This is still early days for CXX; I am releasing it as a minimum viable product
-to collect feedback on the direction and invite collaborators. Here are some of
-the facets that I still intend for this project to tackle:
-
-- [ ] Support structs with type parameters
-- [ ] Support async functions
+to collect feedback on the direction and invite collaborators. Please check the
+open issues.
 
 On the build side, I don't have much experience with the `cc` crate so I expect
 there may be someone who can suggest ways to make that aspect of this crate

From a3a0a6dfc57e8019c502b21dbd7aa4d2c94ed343 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 02:49:22 +0000
Subject: [PATCH 341/2232] Enable trybuild diffs


---

diff --git a/Cargo.toml b/Cargo.toml
index e61fd2f..f497482 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,7 @@ cc = "1.0.49"
 [dev-dependencies]
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = "1.0.21"
+trybuild = { version = "1.0.21", features = ["diff"] }
 
 [workspace]
 members = ["cmd", "demo-rs", "macro", "tests/ffi"]

From 4b07ab92e3fc900a4d712691533e6b77188e9785 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 02:50:21 +0000
Subject: [PATCH 342/2232] Improve span of unsized opaque type error


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 36f25c5..8b3602a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -32,7 +32,8 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                 has_rust_type = true;
             }
             let ident = &ety.ident;
-            hidden.extend(quote!(__assert_sized::<#ident>();));
+            let span = ident.span();
+            hidden.extend(quote_spanned!(span=> __assert_sized::<#ident>();));
         }
     }
 
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 1146b80..e93a546 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -1,13 +1,12 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/opaque_not_sized.rs:1:1
+ --> $DIR/opaque_not_sized.rs:4:14
   |
 1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  | |
-  | doesn't have a size known at compile-time
-  | required by this bound in `ffi::_::__assert_sized`
+  | -------------- required by this bound in `ffi::_::__assert_sized`
+...
+4 |         type TypeR;
+  |              ^^^^^ doesn't have a size known at compile-time
   |
   = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required because it appears within the type `TypeR`
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From b17b9f3bf4b34a81e2a0f9226ef89bc0d3c4167a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 03:01:08 +0000
Subject: [PATCH 343/2232] Regenerate lockfile to include trybuild/diff feature


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 7158ff0..2e70499 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -119,6 +119,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "dissimilar"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39de161cd2ebbd6e5783db53a82a47b6a47dcfef754130839603561745528b94"
+
+[[package]]
 name = "glob"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -366,6 +372,7 @@ version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "459186ab1afd6d93bd23c2269125f4f7694f8771fe0e64434b4bdc212b94034d"
 dependencies = [
+ "dissimilar",
  "glob",
  "lazy_static",
  "serde",

From 1044d44f308e97ab017ff05c3384e10b41e7913a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 03:01:21 +0000
Subject: [PATCH 344/2232] Suppress irrelevant "required by this bound" from error message


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8b3602a..3189bff 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -20,20 +20,15 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
 
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
-    let mut has_rust_type = false;
 
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
-            if !has_rust_type {
-                hidden.extend(quote!(
-                    const fn __assert_sized<T>() {}
-                ));
-                has_rust_type = true;
-            }
             let ident = &ety.ident;
             let span = ident.span();
-            hidden.extend(quote_spanned!(span=> __assert_sized::<#ident>();));
+            hidden.extend(quote_spanned! {span=>
+                let _ = ::std::ptr::read::<#ident>;
+            });
         }
     }
 
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index e93a546..0baa70a 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -1,12 +1,9 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/opaque_not_sized.rs:4:14
-  |
-1 | #[cxx::bridge]
-  | -------------- required by this bound in `ffi::_::__assert_sized`
-...
-4 |         type TypeR;
-  |              ^^^^^ doesn't have a size known at compile-time
-  |
-  = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
-  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-  = note: required because it appears within the type `TypeR`
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
+    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+    = note: required because it appears within the type `TypeR`

From 97408eed57cd17f92d5498587f2b65c63c3eebed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 03:27:29 +0000
Subject: [PATCH 345/2232] Merge pull request #141 from dtolnay/sized


Improve span of unsized opaque type error
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8b3602a..3189bff 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -20,20 +20,15 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
 
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
-    let mut has_rust_type = false;
 
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
-            if !has_rust_type {
-                hidden.extend(quote!(
-                    const fn __assert_sized<T>() {}
-                ));
-                has_rust_type = true;
-            }
             let ident = &ety.ident;
             let span = ident.span();
-            hidden.extend(quote_spanned!(span=> __assert_sized::<#ident>();));
+            hidden.extend(quote_spanned! {span=>
+                let _ = ::std::ptr::read::<#ident>;
+            });
         }
     }
 
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index e93a546..0baa70a 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -1,12 +1,9 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
- --> $DIR/opaque_not_sized.rs:4:14
-  |
-1 | #[cxx::bridge]
-  | -------------- required by this bound in `ffi::_::__assert_sized`
-...
-4 |         type TypeR;
-  |              ^^^^^ doesn't have a size known at compile-time
-  |
-  = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
-  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-  = note: required because it appears within the type `TypeR`
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
+    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+    = note: required because it appears within the type `TypeR`

From 00377239222ead743ccb4a7b7ce75a840e89a964 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 23 2020 16:42:46 +0000
Subject: [PATCH 346/2232] Add CI of test suite including method syntax on 1.43


---

diff --git a/.travis.yml b/.travis.yml
index 49bacbd..124fc57 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@ language: rust
 rust:
   - nightly
   - beta
+  - stable
 
 script:
   - cargo run --manifest-path demo-rs/Cargo.toml

From cb4ee4bb71beb8a1f102dad701f719df2b87c4fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 18:28:34 +0000
Subject: [PATCH 347/2232] Fix missing absolute path to MaybeUninit


It's possible for `std` to mean something different from `::std` if the
user's ffi mod contains a type named `std`.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3189bff..8223572 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -228,7 +228,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             // These are arguments for which C++ has taken ownership of the data
             // behind the mut reference it received.
             quote! {
-                let mut #var = std::mem::MaybeUninit::new(#var);
+                let mut #var = ::std::mem::MaybeUninit::new(#var);
             }
         })
         .collect::<TokenStream>();

From ad7186a89fa4f6057167a650e0e284f5d5703164 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 22:37:49 +0000
Subject: [PATCH 348/2232] Produce better error on const_assert failures


The new message includes the value of the left and right side. The
previous message did not include the values, just said it failed.

---

diff --git a/src/assert.rs b/src/assert.rs
index 6159ce6..cc736dc 100644
--- a/src/assert.rs
+++ b/src/assert.rs
@@ -1,30 +1,5 @@
-pub struct True;
-pub struct False;
-
-pub trait ToBool {
-    type Bool: Sized;
-    const BOOL: Self::Bool;
-}
-
-impl ToBool for [(); 0] {
-    type Bool = False;
-    const BOOL: Self::Bool = False;
-}
-
-impl ToBool for [(); 1] {
-    type Bool = True;
-    const BOOL: Self::Bool = True;
-}
-
-macro_rules! bool {
-    ($e:expr) => {{
-        const EXPR: bool = $e;
-        <[(); EXPR as usize] as $crate::assert::ToBool>::BOOL
-    }};
-}
-
-macro_rules! const_assert {
-    ($e:expr) => {
-        const _: $crate::assert::True = bool!($e);
+macro_rules! const_assert_eq {
+    ($left:expr, $right:expr) => {
+        const _: [(); $left] = [(); $right];
     };
 }
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index a0c348b..6e987a8 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -23,4 +23,4 @@ impl RustSliceU8 {
     }
 }
 
-const_assert!(mem::size_of::<Option<RustSliceU8>>() == mem::size_of::<RustSliceU8>());
+const_assert_eq!(mem::size_of::<Option<RustSliceU8>>(), mem::size_of::<RustSliceU8>());
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 51e4835..184e2c1 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -31,4 +31,4 @@ unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     str::from_utf8(slice).is_ok()
 }
 
-const_assert!(mem::size_of::<Option<RustStr>>() == mem::size_of::<RustStr>());
+const_assert_eq!(mem::size_of::<Option<RustStr>>(), mem::size_of::<RustStr>());

From aa77e82ec8b45ee86a410555cfb91864c210882b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 22:43:05 +0000
Subject: [PATCH 349/2232] Use const_assert_eq for all const assertions


---

diff --git a/src/opaque.rs b/src/opaque.rs
index ded64e9..0ff6bb9 100644
--- a/src/opaque.rs
+++ b/src/opaque.rs
@@ -10,7 +10,5 @@ pub struct Opaque {
     _private: [*const u8; 0],
 }
 
-fn _assert() {
-    let _: [(); 0] = [(); mem::size_of::<Opaque>()];
-    let _: [(); 1] = [(); mem::align_of::<Opaque>()];
-}
+const_assert_eq!(0, mem::size_of::<Opaque>());
+const_assert_eq!(1, mem::align_of::<Opaque>());
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 113adfd..3fba2f5 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -71,7 +71,5 @@ unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
 
-fn _assert() {
-    let _: [(); mem::size_of::<[usize; 3]>()] = [(); mem::size_of::<String>()];
-    let _: [(); mem::align_of::<usize>()] = [(); mem::align_of::<String>()];
-}
+const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<String>());
+const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<String>());

From 7a9b1301acfaaa556051230600f5ef86dd77e592 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 23:15:36 +0000
Subject: [PATCH 350/2232] Relative link to local types in builtin types doc


These links work for locally rendered offline documentation.

---

diff --git a/src/lib.rs b/src/lib.rs
index 74e103a..304a87a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -308,9 +308,9 @@
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+//! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-//! <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>

From d7b8a6e34c91f8c2c09015f389ac8f7e20909e75 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 23:22:55 +0000
Subject: [PATCH 351/2232] Link to std::string::empty


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index d3d128c..baad468 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -36,6 +36,10 @@ impl CxxString {
     }
 
     /// Returns true if `self` has a length of zero bytes.
+    ///
+    /// Matches the behavior of C++ [std::string::empty][empty].
+    ///
+    /// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty
     pub fn is_empty(&self) -> bool {
         self.len() == 0
     }

From 3cd990fe644ba16c4e6212a4749aa770491b4c0c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 24 2020 23:24:26 +0000
Subject: [PATCH 352/2232] Fix link from CxxString::as_ptr to len method


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index baad468..54fad27 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -58,9 +58,10 @@ impl CxxString {
     /// Note that the return type may look like `const char *` but is not a
     /// `const char *` in the typical C sense, as C++ strings may contain
     /// internal null bytes. As such, the returned pointer only makes sense as a
-    /// string in combination with the length returned by [`len()`](#len).
+    /// string in combination with the length returned by [`len()`][len].
     ///
     /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data
+    /// [len]: #method.len
     pub fn as_ptr(&self) -> *const u8 {
         unsafe { string_data(self) }
     }

From 9706a5104c8d01589813adbc6267c60d5217e3ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 25 2020 00:09:01 +0000
Subject: [PATCH 353/2232] Express Box const_pointer and pointer more concisely


---

diff --git a/include/cxx.h b/include/cxx.h
index 637372a..7c2594c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -125,9 +125,9 @@ template <typename T>
 class Box final {
 public:
   using value_type = T;
-  using const_pointer = typename std::add_pointer<
-      typename std::add_const<value_type>::type>::type;
-  using pointer = typename std::add_pointer<value_type>::type;
+  using const_pointer =
+      typename std::add_pointer<typename std::add_const<T>::type>::type;
+  using pointer = typename std::add_pointer<T>::type;
 
   Box(const Box &other) : Box(*other) {}
   Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }

From e9f58d5cf3e3b8f4bd507c9a0b1b07db2c6fffd0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 25 2020 00:44:58 +0000
Subject: [PATCH 354/2232] Wrap long const assert


---

diff --git a/src/assert.rs b/src/assert.rs
index cc736dc..738e5bb 100644
--- a/src/assert.rs
+++ b/src/assert.rs
@@ -1,5 +1,5 @@
 macro_rules! const_assert_eq {
-    ($left:expr, $right:expr) => {
+    ($left:expr, $right:expr $(,)?) => {
         const _: [(); $left] = [(); $right];
     };
 }
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index 6e987a8..f509c7f 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -23,4 +23,7 @@ impl RustSliceU8 {
     }
 }
 
-const_assert_eq!(mem::size_of::<Option<RustSliceU8>>(), mem::size_of::<RustSliceU8>());
+const_assert_eq!(
+    mem::size_of::<Option<RustSliceU8>>(),
+    mem::size_of::<RustSliceU8>(),
+);

From eba35cfce75094c0e4b459f63cc1e8ab915c10af Mon Sep 17 00:00:00 2001
From: Myron Ahn <myronahn@gmail.com>
Date: Apr 25 2020 19:47:04 +0000
Subject: [PATCH 355/2232] C++ std::vector<T> and Rust std::vec::Vec<T> support


Add basic std::vector and std::vec::Vec support across FFI boundary.

---

diff --git a/Cargo.toml b/Cargo.toml
index f497482..95cd87d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 cc = "1.0.49"
+codespan = "0.7"
 codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.10", path = "macro" }
 link-cplusplus = "1.0"
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..387c56a 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,13 +9,41 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
+std::unique_ptr<ThingC> make_demo(::rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
-void do_thing(SharedThing state) { print_r(*state.y); }
+std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
+  print_r(*state.y);
+  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  for (uint8_t i = 0; i < 10; i++) {
+    vec->push_back(i * i);
+  }
+  return vec;
+}
+
+JsonBlob get_jb(const ::rust::Vec<uint8_t>& vec) {
+  JsonBlob retval;
+
+  std::cout << "incoming vec length is " << vec.size() << "\n";
+  auto vec_copy = static_cast<std::vector<uint8_t>>(vec);
+  std::cout << "vec_copy length is " << vec_copy.size() << "\n";
+  std::cout << "vec_copy[0] is " << (int)vec_copy[0] << "\n";
+
+  auto blob = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  for (uint8_t i = 0; i < 10; i++) {
+    blob->push_back(i * 2);
+  }
+
+  auto json = std::unique_ptr<std::string>(new std::string("{\"demo\": 23}"));
+
+  retval.json = std::move(json);
+  retval.blob = std::move(blob);
+
+  return retval;
+}
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index fafc474..eea0af7 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -15,10 +15,12 @@ public:
 };
 
 struct SharedThing;
+struct JsonBlob;
 
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
+std::unique_ptr<ThingC> make_demo(::rust::Str appname);
 const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
+std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
+JsonBlob get_jb(const ::rust::Vec<uint8_t>& vec);
 
 } // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 66dfc79..8bf9926 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -6,13 +6,19 @@ mod ffi {
         x: UniquePtr<ThingC>,
     }
 
+    struct JsonBlob {
+        json: UniquePtr<CxxString>,
+        blob: UniquePtr<Vector<u8>>,
+    }
+
     extern "C" {
         include!("demo-cxx/demo.h");
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
         fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
+        fn do_thing(state: SharedThing) -> UniquePtr<Vector<u8>>;
+        fn get_jb(v: &Vec<u8>) -> JsonBlob;
     }
 
     extern "Rust" {
@@ -31,9 +37,24 @@ fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
     println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
 
-    ffi::do_thing(ffi::SharedThing {
+    let vec = ffi::do_thing(ffi::SharedThing {
         z: 222,
         y: Box::new(ThingR(333)),
         x,
     });
+
+    println!("vec length = {}", vec.as_ref().unwrap().size());
+    for (i, v) in vec.as_ref().unwrap().into_iter().enumerate() {
+        println!("vec[{}] = {}", i, v);
+    }
+
+    let mut rv: Vec<u8> = Vec::new();
+    for _ in 0..1000 {
+        rv.push(33);
+    }
+    let jb = ffi::get_jb(&rv);
+    println!("json: {}", jb.json.as_ref().unwrap());
+    for (i, v) in jb.blob.as_ref().unwrap().into_iter().enumerate() {
+        println!("jb.blob[{}] = {}", i, v);
+    }
 }
diff --git a/gen/include.rs b/gen/include.rs
index 8f38fe3..077d03e 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -36,6 +36,7 @@ pub struct Includes {
     pub exception: bool,
     pub memory: bool,
     pub string: bool,
+    pub vector: bool,
     pub type_traits: bool,
     pub utility: bool,
     pub base_tsd: bool,
diff --git a/gen/write.rs b/gen/write.rs
index a8e3fd4..a74833f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,8 +1,10 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
+use crate::syntax::typename::ToTypename;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -42,7 +44,7 @@ pub(super) fn gen(
             Api::Struct(strct) => write_struct_decl(out, &strct.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident),
             Api::RustType(ety) => write_struct_decl(out, &ety.ident),
-            _ => {}
+            _ => (),
         }
     }
 
@@ -123,8 +125,9 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
+            Type::Vector(_) => out.include.vector = true,
             Type::SliceRefU8(_) => out.include.cstdint = true,
-            _ => {}
+            _ => (),
         }
     }
 }
@@ -134,14 +137,18 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_str = false;
     let mut needs_rust_slice = false;
     let mut needs_rust_box = false;
+    let mut needs_rust_vec = false;
     let mut needs_rust_fn = false;
-    let mut needs_rust_isize = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
                 out.include.type_traits = true;
                 needs_rust_box = true;
             }
+            Type::RustVec(_) => {
+                out.include.type_traits = true;
+                needs_rust_vec = true;
+            }
             Type::Str(_) => {
                 out.include.cstdint = true;
                 out.include.string = true;
@@ -153,10 +160,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Type::Slice(_) | Type::SliceRefU8(_) => {
                 needs_rust_slice = true;
             }
-            ty if ty == Isize => {
-                out.include.base_tsd = true;
-                needs_rust_isize = true;
-            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -213,9 +216,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_rust_str
         || needs_rust_slice
         || needs_rust_box
+        || needs_rust_vec
         || needs_rust_fn
         || needs_rust_error
-        || needs_rust_isize
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
@@ -233,9 +236,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
     write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
     if needs_manually_drop {
@@ -469,6 +472,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::Vector(_)) => write!(
+            out,
+            " /* Use RVO to convert to r-value and move construct */"
+        ),
         Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
@@ -779,7 +786,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) => {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) => {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
@@ -796,21 +803,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
+            Some(a) => write!(out, "{}", a.to_cxx()),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
@@ -818,11 +811,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ty.inner);
             write!(out, ">");
         }
+        Type::RustVec(ty) => {
+            write!(out, "::rust::Vec<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
         Type::UniquePtr(ptr) => {
             write!(out, "::std::unique_ptr<");
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::Vector(ty) => {
+            write!(out, "::std::vector<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
         Type::Ref(r) => {
             if r.mutability.is_none() {
                 write!(out, "const ");
@@ -870,6 +873,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::Str(_)
+        | Type::Vector(_)
+        | Type::RustVec(_)
         | Type::SliceRefU8(_)
         | Type::Fn(_) => write!(out, " "),
         Type::Ref(_) => {}
@@ -882,6 +887,11 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         Atom::from(ident).is_none()
     }
 
+    fn allow_vector(ident: &Ident) -> bool {
+        // Note: built-in types such as u8 are already defined in cxx.cc
+        Atom::from(ident).is_none()
+    }
+
     out.begin_block("extern \"C\"");
     for ty in types {
         if let Type::RustBox(ty) = ty {
@@ -889,11 +899,30 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 out.next_section();
                 write_rust_box_extern(out, inner);
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(_) = &ty.inner {
+                out.next_section();
+                write_rust_vec_extern(out, &ty.inner);
+            }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, inner, types);
+                    write_unique_ptr(out, &ptr.inner, types);
+                }
+            } else if let Type::Vector(ptr1) = &ptr.inner {
+                if let Type::Ident(inner) = &ptr1.inner {
+                    if allow_vector(inner) {
+                        out.next_section();
+                        write_unique_ptr(out, &ptr.inner, types);
+                    }
+                }
+            }
+        } else if let Type::Vector(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if allow_vector(inner) {
+                    out.next_section();
+                    write_vector(out, inner);
                 }
             }
         }
@@ -907,6 +936,10 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ty.inner {
                 write_rust_box_impl(out, inner);
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(_) = &ty.inner {
+                write_rust_vec_impl(out, &ty.inner);
+            }
         }
     }
     out.end_block("namespace cxxbridge02");
@@ -937,6 +970,31 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
 }
 
+fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const std::vector<{}> &vector) noexcept;",
+        instance, inner, inner
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
+}
+
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let mut inner = String::new();
     for name in &out.namespace {
@@ -957,16 +1015,44 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
-    out.include.utility = true;
+fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
 
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$drop(this);",
+        instance
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(
+        out,
+        "Vec<{}>::operator std::vector<{}>() const noexcept {{",
+        inner, inner
+    );
+    writeln!(
+        out,
+        "  std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
+        inner, instance,
+    );
+    writeln!(out, "}}");
+}
+
+fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.utility = true;
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
@@ -987,18 +1073,21 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    if types.structs.contains_key(ident) {
-        writeln!(
+    match ty {
+        Type::Ident(ident) if types.structs.contains_key(ident) => {
+            writeln!(
             out,
             "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
-        writeln!(
-            out,
-            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
-        );
-        writeln!(out, "}}");
+            writeln!(
+                out,
+                "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+                inner, inner,
+            );
+            writeln!(out, "}}");
+        }
+        _ => (),
     }
     writeln!(
         out,
@@ -1030,3 +1119,50 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     writeln!(out, "}}");
     writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
 }
+
+fn write_vector(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    // Do not apply namespace to built-in type
+    let is_user_type = Atom::from(ident).is_none();
+    if is_user_type {
+        for name in &out.namespace {
+            inner += name;
+            inner += "::";
+        }
+    }
+    let mut instance = inner.clone();
+    if let Some(ti) = Atom::from(ident) {
+        inner += ti.to_cxx();
+    } else {
+        inner += &ident.to_string();
+    };
+    instance += &ident.to_string();
+    let instance = instance.replace("::", "$");
+
+    writeln!(out, "#ifndef CXXBRIDGE02_vector_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
+    writeln!(
+        out,
+        "size_t cxxbridge02$std$vector${}$length(const std::vector<{}> &s) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  return s.size();");
+    writeln!(out, "}}");
+
+    writeln!(
+        out,
+        "void cxxbridge02$std$vector${}$push_back(std::vector<{}> &s, const {} &item) noexcept {{",
+        instance, inner, inner
+    );
+    writeln!(out, "  s.push_back(item);");
+    writeln!(out, "}}");
+
+    writeln!(
+        out,
+        "const {} *cxxbridge02$std$vector${}$get_unchecked(const std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return &s[pos];");
+    writeln!(out, "}}");
+    writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
+}
diff --git a/include/cxx.h b/include/cxx.h
index 637372a..35e9059 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -5,6 +5,7 @@
 #include <exception>
 #include <iosfwd>
 #include <string>
+#include <vector>
 #include <type_traits>
 #include <utility>
 #if defined(_WIN32)
@@ -83,6 +84,27 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_STR
 
+#ifndef CXXBRIDGE02_RUST_VEC
+#define CXXBRIDGE02_RUST_VEC
+template <typename T>
+class Vec final {
+public:
+  size_t size() const noexcept;
+  explicit operator std::vector<T>() const noexcept;
+
+private:
+  Vec() noexcept;
+  Vec(const Vec &other) noexcept;
+  Vec &operator=(Vec other) noexcept;
+  void drop() noexcept;
+  
+  // Repr
+  const T *ptr;
+  size_t len;
+  size_t capacity;
+};
+#endif // CXXBRIDGE02_RUST_VEC
+
 #ifndef CXXBRIDGE02_RUST_SLICE
 #define CXXBRIDGE02_RUST_SLICE
 template <typename T>
@@ -234,14 +256,11 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_ERROR
 
-#ifndef CXXBRIDGE02_RUST_ISIZE
-#define CXXBRIDGE02_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
-#endif // CXXBRIDGE02_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index ca0e326..99ae923 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -19,7 +19,7 @@ quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.2", path = ".." }
+cxx = { version = "0.2.7-alpha-1", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8b3602a..b329276 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,14 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
+use crate::syntax::typename::ToTypename;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, Error, ItemMod, Result, Token};
+use syn::{parse_quote, spanned::Spanned, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -22,6 +24,38 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let mut hidden = TokenStream::new();
     let mut has_rust_type = false;
 
+    // "Header" to define newtypes locally so we can implement
+    // traits on them.
+    expanded.extend(quote! {
+        pub struct Vector<T>(pub ::cxx::RealVector<T>);
+        impl<T: cxx::private::VectorTarget<T>> Vector<T> {
+            pub fn size(&self) -> usize {
+                self.0.size()
+            }
+            pub fn get(&self, pos: usize) -> Option<&T> {
+                self.0.get(pos)
+            }
+            pub fn get_unchecked(&self, pos: usize) -> &T {
+                self.0.get_unchecked(pos)
+            }
+            pub fn is_empty(&self) -> bool {
+                self.0.is_empty()
+            }
+            pub fn push_back(&mut self, item: &T) {
+                self.0.push_back(item)
+            }
+        }
+        impl<'a, T: cxx::private::VectorTarget<T>> IntoIterator for &'a Vector<T> {
+            type Item = &'a T;
+            type IntoIter = <&'a ::cxx::RealVector<T> as IntoIterator>::IntoIter;
+
+            fn into_iter(self) -> Self::IntoIter {
+                self.0.into_iter()
+            }
+        }
+        unsafe impl<T> Send for Vector<T> where T: Send + cxx::private::VectorTarget<T> {}
+    });
+
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
@@ -58,10 +92,34 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                     hidden.extend(expand_rust_box(namespace, ident));
                 }
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(ident) = &ty.inner {
+                hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+            }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types));
+                    expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
+                }
+            } else if let Type::Vector(_) = &ptr.inner {
+                // Generate code for unique_ptr<vector<T>> if T is not an atom
+                // or if T is a primitive.
+                // Code for primitives is already generated
+                match Atom::from(ident) {
+                    None => expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types)),
+                    Some(atom) => {
+                        if atom.is_valid_vector_target() {
+                            expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
+                        }
+                    }
+                }
+            }
+        } else if let Type::Vector(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(ident).is_none() {
+                    // Generate code for Vector<T> if T is not an atom
+                    // Code for atoms is already generated
+                    expanded.extend(expand_vector(namespace, &ptr.inner));
                 }
             }
         }
@@ -197,10 +255,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
+            Type::RustVec(_) => quote!(::cxx::RustVec::from(#var)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
                 }
+                Type::RustVec(_) => quote!(::cxx::RustVec::from_ref(#var)),
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -523,9 +583,42 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
-    let name = ident.to_string();
-    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
+fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
+    let link_drop = format!("{}drop", link_prefix);
+    let link_vector_from = format!("{}vector_from", link_prefix);
+    let link_len = format!("{}len", link_prefix);
+
+    let local_prefix = format_ident!("{}__vec_", ident);
+    let local_drop = format_ident!("{}drop", local_prefix);
+    let local_vector_from = format_ident!("{}vector_from", local_prefix);
+    let local_len = format_ident!("{}len", local_prefix);
+
+    let span = ty.span();
+    quote_spanned! {span=>
+        #[doc(hidden)]
+        #[export_name = #link_drop]
+        unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
+            std::ptr::drop_in_place(this);
+        }
+        #[export_name = #link_vector_from]
+        unsafe extern "C" fn #local_vector_from(this: *mut ::cxx::RustVec<#inner>, vector: *mut ::cxx::RealVector<#inner>) {
+            this.as_ref().unwrap().into_vector(vector.as_mut().unwrap());
+        }
+        #[export_name = #link_len]
+        unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
+            this.as_ref().unwrap().len()
+        }
+    }
+}
+
+fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
+    let name = ty.to_typename(&namespace.segments);
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -533,8 +626,8 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) {
-        Some(quote! {
+    let new_method = match ty {
+        Type::Ident(ident) if types.structs.contains_key(ident) => Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
@@ -544,13 +637,12 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
                 unsafe { __new(&mut repr, &mut value) }
                 repr
             }
-        })
-    } else {
-        None
+        }),
+        _ => None,
     };
 
     quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+        unsafe impl ::cxx::private::UniquePtrTarget for #inner {
             const __NAME: &'static str = #name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -565,7 +657,7 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
-                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #ident);
+                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #inner);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __raw(&mut repr, raw);
@@ -574,14 +666,14 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #ident;
+                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #inner;
                 }
                 __get(&repr)
             }
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
-                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #ident;
+                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #inner;
                 }
                 __release(&mut repr)
             }
@@ -596,6 +688,90 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     }
 }
 
+fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$std$vector${}", mangled);
+    let link_length = format!("{}length", prefix);
+    let link_get_unchecked = format!("{}get_unchecked", prefix);
+    let link_push_back = format!("{}push_back", prefix);
+
+    quote! {
+        impl ::cxx::private::VectorTarget<#inner> for #inner {
+            fn get_unchecked(v: &::cxx::RealVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &::cxx::RealVector<#inner>, _: usize) -> &#inner;
+                }
+                unsafe {
+                    __get_unchecked(v, pos)
+                }
+            }
+            fn vector_length(v: &::cxx::RealVector<#inner>) -> usize {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_length]
+                        fn __vector_length(_: &::cxx::RealVector<#inner>) -> usize;
+                    }
+                    __vector_length(v)
+                }
+            }
+            fn push_back(v: &::cxx::RealVector<#inner>, item: &#inner) {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_push_back]
+                        fn __push_back(_: &::cxx::RealVector<#inner>, _: &#inner) -> usize;
+                    }
+                    __push_back(v, item);
+                }
+            }
+        }
+    }
+}
+
+pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
+    let ty = Type::Ident(ident);
+    let inner = &ty;
+    let namespace = Namespace { segments: vec![] };
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$std$vector${}", mangled);
+    let link_length = format!("{}length", prefix);
+    let link_get_unchecked = format!("{}get_unchecked", prefix);
+    let link_push_back = format!("{}push_back", prefix);
+
+    quote! {
+        impl VectorTarget<#inner> for #inner {
+            fn get_unchecked(v: &RealVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &RealVector<#inner>, _: usize) -> &#inner;
+                }
+                unsafe {
+                    __get_unchecked(v, pos)
+                }
+            }
+            fn vector_length(v: &RealVector<#inner>) -> usize {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_length]
+                        fn __vector_length(_: &RealVector<#inner>) -> usize;
+                    }
+                    __vector_length(v)
+                }
+            }
+            fn push_back(v: &RealVector<#inner>, item: &#inner) {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_push_back]
+                        fn __push_back(_: &RealVector<#inner>, _: &#inner) -> usize;
+                    }
+                    __push_back(v, item);
+                }
+            }
+        }
+    }
+}
+
 fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     match ret {
         Some(ret) => quote!(-> #ret),
@@ -613,11 +789,16 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
     match ty {
         Type::Ident(ident) if ident == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            let inner = &ty.inner;
+            let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
         }
+        Type::RustVec(ty) => quote!(::cxx::RustVec<#ty>),
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
+            Type::RustVec(ty) => {
+                let inner = expand_extern_type(&ty.inner);
+                quote!(&::cxx::RustVec<#inner>)
+            }
             _ => quote!(#ty),
         },
         Type::Str(_) => quote!(::cxx::private::RustStr),
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b56f58e..87fe405 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -14,7 +14,7 @@ mod syntax;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod};
+use syn::{parse_macro_input, Ident, ItemMod};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,3 +44,9 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
+
+#[proc_macro]
+pub fn vector_builtin(input: TokenStream) -> TokenStream {
+    let ident = parse_macro_input!(input as Ident);
+    expand::expand_vector_builtin(ident).into()
+}
diff --git a/src/cxx.cc b/src/cxx.cc
index b64333c..916f525 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -3,6 +3,7 @@
 #include <exception>
 #include <iostream>
 #include <memory>
+#include <vector>
 #include <stdexcept>
 
 template <typename Exception>
@@ -197,3 +198,50 @@ void cxxbridge02$unique_ptr$std$string$drop(
   ptr->~unique_ptr();
 }
 } // extern "C"
+
+#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
+extern "C" { \
+size_t cxxbridge02$std$vector$##RUST_TYPE##$length(const std::vector<CXX_TYPE> &s) noexcept { \
+  return s.size(); \
+} \
+void cxxbridge02$std$vector$##RUST_TYPE##$push_back(std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept { \
+  s.push_back(item); \
+} \
+const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
+  return &s[pos]; \
+} \
+static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) == sizeof(void *), ""); \
+static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) == alignof(void *), ""); \
+void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
+  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(); \
+} \
+void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr, std::vector<CXX_TYPE> *value) noexcept { \
+  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(new std::vector<CXX_TYPE>(::std::move(*value))); \
+} \
+void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr, std::vector<CXX_TYPE> *raw) noexcept { \
+  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
+} \
+const std::vector<CXX_TYPE> *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(const ::std::unique_ptr<std::vector<CXX_TYPE>>& ptr) noexcept { \
+  return ptr.get(); \
+} \
+std::vector<CXX_TYPE> *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(::std::unique_ptr<std::vector<CXX_TYPE>>& ptr) noexcept { \
+  return ptr.release(); \
+} \
+void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
+  ptr->~unique_ptr(); \
+} \
+} // extern "C"
+
+STD_VECTOR_OPS(u8, uint8_t);
+STD_VECTOR_OPS(u16, uint16_t);
+STD_VECTOR_OPS(u32, uint32_t);
+STD_VECTOR_OPS(u64, uint64_t);
+STD_VECTOR_OPS(usize, size_t);
+STD_VECTOR_OPS(i8, int8_t);
+STD_VECTOR_OPS(i16, int16_t);
+STD_VECTOR_OPS(i32, int32_t);
+STD_VECTOR_OPS(i64, int64_t);
+STD_VECTOR_OPS(isize, rust::isize);
+STD_VECTOR_OPS(f32, float);
+STD_VECTOR_OPS(f64, double);
+
diff --git a/src/lib.rs b/src/lib.rs
index 74e103a..994c430 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -370,13 +370,18 @@ mod result;
 mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
+mod rust_vec;
 mod syntax;
 mod unique_ptr;
 mod unwind;
+mod vector;
 
 pub use crate::cxx_string::CxxString;
 pub use crate::exception::Exception;
+pub use crate::rust_vec::RustVec;
 pub use crate::unique_ptr::UniquePtr;
+pub use crate::vector::RealVector;
+pub use crate::vector::VectorIntoIterator;
 pub use cxxbridge_macro::bridge;
 
 // Not public API.
@@ -390,6 +395,7 @@ pub mod private {
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
+    pub use crate::vector::VectorTarget;
 }
 
 use crate::error::Result;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
new file mode 100644
index 0000000..a28570d
--- /dev/null
+++ b/src/rust_vec.rs
@@ -0,0 +1,39 @@
+use crate::vector::RealVector;
+use crate::vector::VectorTarget;
+
+#[repr(C)]
+pub struct RustVec<T: VectorTarget<T>> {
+    repr: Vec<T>,
+}
+
+impl<T: VectorTarget<T>> RustVec<T> {
+    pub fn from(v: Vec<T>) -> Self {
+        RustVec { repr: v }
+    }
+
+    pub fn from_ref(v: &Vec<T>) -> &Self {
+        unsafe { std::mem::transmute::<&Vec<T>, &RustVec<T>>(v) }
+    }
+
+    pub fn into_vec(self) -> Vec<T> {
+        self.repr
+    }
+
+    pub fn as_vec(&self) -> &Vec<T> {
+        &self.repr
+    }
+
+    pub fn as_mut_vec(&mut self) -> &mut Vec<T> {
+        &mut self.repr
+    }
+
+    pub fn len(&self) -> usize {
+        self.repr.len()
+    }
+
+    pub fn into_vector(&self, vec: &mut RealVector<T>) {
+        for item in &self.repr {
+            vec.push_back(item);
+        }
+    }
+}
diff --git a/src/vector.rs b/src/vector.rs
new file mode 100644
index 0000000..805bdbb
--- /dev/null
+++ b/src/vector.rs
@@ -0,0 +1,91 @@
+pub trait VectorTarget<T> {
+    fn get_unchecked(v: &RealVector<T>, pos: usize) -> &T
+    where
+        Self: Sized;
+    fn vector_length(v: &RealVector<T>) -> usize
+    where
+        Self: Sized;
+    fn push_back(v: &RealVector<T>, item: &T)
+    where
+        Self: Sized;
+}
+
+/// Binding to C++ `std::vector`.
+///
+/// # Invariants
+///
+/// As an invariant of this API and the static analysis of the cxx::bridge
+/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
+/// requires a move constructor and may hold internal pointers, which is not
+/// compatible with Rust's move behavior. Instead in Rust code we will only ever
+/// look at a Vector through a reference or smart pointer, as in `&Vector`
+/// or `UniquePtr<Vector>`.
+#[repr(C)]
+pub struct RealVector<T> {
+    _private: [T; 0],
+}
+
+impl<T: VectorTarget<T>> RealVector<T> {
+    /// Returns the length of the vector in bytes.
+    pub fn size(&self) -> usize {
+        T::vector_length(self)
+    }
+
+    pub fn get_unchecked(&self, pos: usize) -> &T {
+        T::get_unchecked(self, pos)
+    }
+
+    /// Returns true if `self` has a length of zero bytes.
+    pub fn is_empty(&self) -> bool {
+        self.size() == 0
+    }
+
+    pub fn get(&self, pos: usize) -> Option<&T> {
+        if pos < self.size() {
+            Some(self.get_unchecked(pos))
+        } else {
+            None
+        }
+    }
+
+    pub fn push_back(&mut self, item: &T) {
+        T::push_back(self, item);
+    }
+}
+
+unsafe impl<T> Send for RealVector<T> where T: Send + VectorTarget<T> {}
+
+pub struct VectorIntoIterator<'a, T> {
+    v: &'a RealVector<T>,
+    index: usize,
+}
+
+impl<'a, T: VectorTarget<T>> IntoIterator for &'a RealVector<T> {
+    type Item = &'a T;
+    type IntoIter = VectorIntoIterator<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        VectorIntoIterator { v: self, index: 0 }
+    }
+}
+
+impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
+    type Item = &'a T;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.index = self.index + 1;
+        self.v.get(self.index - 1)
+    }
+}
+
+cxxbridge_macro::vector_builtin!(u8);
+cxxbridge_macro::vector_builtin!(u16);
+cxxbridge_macro::vector_builtin!(u32);
+cxxbridge_macro::vector_builtin!(u64);
+cxxbridge_macro::vector_builtin!(usize);
+cxxbridge_macro::vector_builtin!(i8);
+cxxbridge_macro::vector_builtin!(i16);
+cxxbridge_macro::vector_builtin!(i32);
+cxxbridge_macro::vector_builtin!(i64);
+cxxbridge_macro::vector_builtin!(isize);
+cxxbridge_macro::vector_builtin!(f32);
+cxxbridge_macro::vector_builtin!(f64);
diff --git a/syntax/atom.rs b/syntax/atom.rs
index eeea831..c68b3fe 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -42,6 +42,43 @@ impl Atom {
             _ => None,
         }
     }
+
+    pub fn to_cxx(&self) -> &'static str {
+        use self::Atom::*;
+        match self {
+            Bool => "bool",
+            U8 => "uint8_t",
+            U16 => "uint16_t",
+            U32 => "uint32_t",
+            U64 => "uint64_t",
+            Usize => "size_t",
+            I8 => "int8_t",
+            I16 => "int16_t",
+            I32 => "int32_t",
+            I64 => "int64_t",
+            Isize => "::rust::isize",
+            F32 => "float",
+            F64 => "double",
+            CxxString => "::std::string",
+            RustString => "::rust::String",
+        }
+    }
+
+    pub fn is_valid_vector_target(&self) -> bool {
+        use self::Atom::*;
+        *self == U8
+            || *self == U16
+            || *self == U32
+            || *self == U64
+            || *self == Usize
+            || *self == I8
+            || *self == I16
+            || *self == I32
+            || *self == I64
+            || *self == Isize
+            || *self == F32
+            || *self == F64
+    }
 }
 
 impl PartialEq<Atom> for Ident {
diff --git a/syntax/check.rs b/syntax/check.rs
index 5e8cc09..387f9a6 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,7 +29,9 @@ fn do_typecheck(cx: &mut Check) {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
+            Type::RustVec(ptr) => check_type_vec(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::Vector(ptr) => check_type_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
@@ -87,6 +89,21 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported target type of Box");
 }
 
+fn check_type_vec(cx: &mut Check, ptr: &Ty1) {
+    // Vec can contain either user-defined type or u8
+    if let Type::Ident(ident) = &ptr.inner {
+        if Atom::from(ident).map(|a| a.is_valid_vector_target()) == Some(true) {
+            return;
+        } else if cx.types.cxx.contains(ident) {
+            cx.error(ptr, error::VEC_CXX_TYPE.msg);
+        } else {
+            return;
+        }
+    }
+
+    cx.error(ptr, "unsupported target type of Vec");
+}
+
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
@@ -97,11 +114,31 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
             None | Some(CxxString) => return,
             _ => {}
         }
+    } else if let Type::Vector(_) = &ptr.inner {
+        return;
     }
 
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
+fn check_type_vector(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(ident) {
+            cx.error(ptr, "vector of a Rust type is not supported yet");
+        }
+
+        match Atom::from(ident) {
+            None => return,
+            Some(atom) => {
+                if atom.is_valid_vector_target() {
+                    return;
+                }
+            }
+        }
+    }
+    cx.error(ptr, "unsupported vector target type");
+}
+
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
     if ty.lifetime.is_some() {
         cx.error(ty, "references with explicit lifetimes are not supported");
@@ -310,9 +347,11 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
             }
         }
         Type::RustBox(_) => "Box".to_owned(),
+        Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Vector(_) => "vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
diff --git a/syntax/error.rs b/syntax/error.rs
index f52d651..103a54f 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -15,6 +15,7 @@ impl Display for Error {
 
 pub static ERRORS: &[Error] = &[
     BOX_CXX_TYPE,
+    VEC_CXX_TYPE,
     CXXBRIDGE_RESERVED,
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
@@ -29,6 +30,12 @@ pub static BOX_CXX_TYPE: Error = Error {
     note: Some("hint: use UniquePtr<>"),
 };
 
+pub static VEC_CXX_TYPE: Error = Error {
+    msg: "Vec of a C++ type is not supported yet",
+    label: None,
+    note: Some("hint: use UniquePtr<>"),
+};
+
 pub static CXXBRIDGE_RESERVED: Error = Error {
     msg: "identifiers starting with cxxbridge are reserved",
     label: Some("reserved identifier"),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a2ce05b..8e94f06 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -26,6 +26,8 @@ impl Hash for Type {
             Type::UniquePtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
+            Type::RustVec(t) => t.hash(state),
+            Type::Vector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
@@ -44,6 +46,8 @@ impl PartialEq for Type {
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
+            (Type::Vector(lhs), Type::Vector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
             (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
new file mode 100644
index 0000000..56e8b73
--- /dev/null
+++ b/syntax/mangled.rs
@@ -0,0 +1,30 @@
+use crate::syntax::{Atom, Type};
+
+pub trait ToMangled {
+    fn to_mangled(&self, namespace: &Vec<String>) -> String;
+}
+
+impl ToMangled for Type {
+    fn to_mangled(&self, namespace: &Vec<String>) -> String {
+        match self {
+            Type::Ident(ident) => {
+                let mut instance = String::new();
+                // Do not apply namespace to built-in type
+                let is_user_type = Atom::from(ident).is_none();
+                if is_user_type {
+                    for name in namespace {
+                        instance += name;
+                        instance += "$";
+                    }
+                }
+                instance += &ident.to_string();
+                instance
+            }
+            Type::RustBox(ptr) => format!("rust_box${}", ptr.inner.to_mangled(namespace)),
+            Type::RustVec(ptr) => format!("rust_vec${}", ptr.inner.to_mangled(namespace)),
+            Type::UniquePtr(ptr) => format!("std$unique_ptr${}", ptr.inner.to_mangled(namespace)),
+            Type::Vector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
+            _ => unimplemented!(),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index ab5cecc..4e0b908 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -8,11 +8,13 @@ pub mod error;
 pub mod ident;
 mod impls;
 pub mod mangle;
+pub mod mangled;
 pub mod namespace;
 mod parse;
 pub mod set;
 pub mod symbol;
 mod tokens;
+pub mod typename;
 pub mod types;
 
 use self::parse::kw;
@@ -86,9 +88,11 @@ pub struct Receiver {
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),
+    RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Vector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
     Slice(Box<Slice>),
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index d26bb9e..a4e972b 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -11,7 +11,7 @@ mod kw {
 
 #[derive(Clone)]
 pub struct Namespace {
-    segments: Vec<String>,
+    pub segments: Vec<String>,
 }
 
 impl Namespace {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7d92b1b..f5c598d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,6 +300,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "Vector" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::Vector(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
@@ -310,6 +320,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "Vec" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::RustVec(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 26bb3d1..3d67a0a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -14,7 +14,9 @@ impl ToTokens for Type {
                 }
                 ident.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
+            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+                ty.to_tokens(tokens)
+            }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
             Type::Slice(s) => s.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
@@ -33,7 +35,8 @@ impl ToTokens for Var {
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if self.name == "UniquePtr" {
+        // Do not add cxx namespace to Vector since we're defining it in the user crate
+        if self.name == "UniquePtr" || self.name == "RustVec" {
             let span = self.name.span();
             tokens.extend(quote_spanned!(span=> ::cxx::));
         }
diff --git a/syntax/typename.rs b/syntax/typename.rs
new file mode 100644
index 0000000..883e1fb
--- /dev/null
+++ b/syntax/typename.rs
@@ -0,0 +1,36 @@
+use crate::syntax::{Atom, Type};
+
+pub trait ToTypename {
+    fn to_typename(&self, namespace: &Vec<String>) -> String;
+}
+
+impl ToTypename for Type {
+    fn to_typename(&self, namespace: &Vec<String>) -> String {
+        match self {
+            Type::Ident(ident) => {
+                let mut inner = String::new();
+                // Do not apply namespace to built-in type
+                let is_user_type = Atom::from(ident).is_none();
+                if is_user_type {
+                    for name in namespace {
+                        inner += name;
+                        inner += "::";
+                    }
+                }
+                if let Some(ti) = Atom::from(ident) {
+                    inner += ti.to_cxx();
+                } else {
+                    inner += &ident.to_string();
+                };
+                inner
+            }
+            Type::RustBox(ptr) => format!("rust_box<{}>", ptr.inner.to_typename(namespace)),
+            Type::RustVec(ptr) => format!("rust_vec<{}>", ptr.inner.to_typename(namespace)),
+            Type::UniquePtr(ptr) => {
+                format!("std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
+            }
+            Type::Vector(ptr) => format!("std::vector<{}>", ptr.inner.to_typename(namespace)),
+            _ => unimplemented!(),
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 6f3af09..7bce154 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -24,7 +24,9 @@ impl<'a> Types<'a> {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
-                Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
+                Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+                    visit(all, &ty.inner)
+                }
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index efdd1fa..27f5f6d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -27,6 +27,9 @@ pub mod ffi {
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
+        fn c_return_unique_ptr_vector_u8() -> UniquePtr<Vector<u8>>;
+        fn c_return_unique_ptr_vector_f64() -> UniquePtr<Vector<f64>>;
+        fn c_return_unique_ptr_vector_shared() -> UniquePtr<Vector<Shared>>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -38,11 +41,19 @@ pub mod ffi {
         fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn c_take_unique_ptr_vector_u8(s: UniquePtr<Vector<u8>>);
+        fn c_take_unique_ptr_vector_f64(s: UniquePtr<Vector<f64>>);
+        fn c_take_unique_ptr_vector_shared(s: UniquePtr<Vector<Shared>>);
+
+        fn c_take_vec_u8(v: &Vec<u8>);
+        fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
         fn c_fail_return_primitive() -> Result<usize>;
+        fn c_try_return_string() -> Result<UniquePtr<CxxString>>;
+        fn c_fail_return_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_box() -> Result<Box<R>>;
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 619485a..9f11d9f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,3 +1,4 @@
+#include <numeric>
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs.h"
 #include <cstring>
@@ -57,6 +58,31 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
 }
 
+std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
+  auto retval = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  retval->push_back(86);
+  retval->push_back(75);
+  retval->push_back(30);
+  retval->push_back(9);
+  return retval;
+}
+
+std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
+  auto retval = std::unique_ptr<std::vector<double>>(new std::vector<double>());
+  retval->push_back(86.0);
+  retval->push_back(75.0);
+  retval->push_back(30.0);
+  retval->push_back(9.5);
+  return retval;
+}
+
+std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
+  auto retval = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
+  retval->push_back(Shared{1010});
+  retval->push_back(Shared{1011});
+  return retval;
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -118,6 +144,43 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v) {
+  if (v->size() == 4) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
+  if (v->size() == 4) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
+  if (v->size() == 2) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_vec_u8(const ::rust::Vec<uint8_t>& v) {
+  auto cv = static_cast<std::vector<uint8_t>>(v);
+  uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
+  if (sum == 200) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_vec_shared(const ::rust::Vec<Shared>& v) {
+  auto cv = static_cast<std::vector<Shared>>(v);
+  uint32_t sum = 0;
+  for (auto i: cv) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
@@ -128,6 +191,14 @@ size_t c_try_return_primitive() { return 2020; }
 
 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
 
+std::unique_ptr<std::string> c_try_return_string() {
+  return std::unique_ptr<std::string>(new std::string("ok"));
+}
+
+std::unique_ptr<std::string> c_fail_return_string() { 
+  throw std::logic_error("logic error getting string"); 
+}
+
 rust::Box<R> c_try_return_box() { return c_return_box(); }
 
 const rust::String &c_try_return_ref(const rust::String &s) { return s; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index ed6d541..9e75c37 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -29,6 +29,9 @@ rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
+std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
+std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
+std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -40,11 +43,19 @@ void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
+void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
+void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
+
+void c_take_vec_u8(const ::rust::Vec<uint8_t>& v);
+void c_take_vec_shared(const ::rust::Vec<Shared>& v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
 size_t c_fail_return_primitive();
+std::unique_ptr<std::string> c_try_return_string();
+std::unique_ptr<std::string> c_fail_return_string();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
diff --git a/tests/test.rs b/tests/test.rs
index 1cd85df..17fcfca 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -32,6 +32,45 @@ fn test_c_return() {
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
+    assert_eq!(
+        4,
+        ffi::c_return_unique_ptr_vector_u8()
+            .as_ref()
+            .unwrap()
+            .size()
+    );
+    assert_eq!(
+        200_u8,
+        ffi::c_return_unique_ptr_vector_u8()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .sum()
+    );
+    assert_eq!(
+        200.5_f64,
+        ffi::c_return_unique_ptr_vector_f64()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .sum()
+    );
+    assert_eq!(
+        2,
+        ffi::c_return_unique_ptr_vector_shared()
+            .as_ref()
+            .unwrap()
+            .size()
+    );
+    assert_eq!(
+        2021_usize,
+        ffi::c_return_unique_ptr_vector_shared()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .map(|o| o.z)
+            .sum()
+    );
 }
 
 #[test]
@@ -42,6 +81,18 @@ fn test_c_try_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
+    assert_eq!(
+        "ok",
+        ffi::c_try_return_string()
+            .unwrap()
+            .as_ref()
+            .unwrap()
+            .to_string()
+    );
+    assert_eq!(
+        "logic error getting string",
+        ffi::c_fail_return_string().unwrap_err().what(),
+    );
     assert_eq!(2020, *ffi::c_try_return_box().unwrap());
     assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
@@ -65,6 +116,22 @@ fn test_c_take() {
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()
     ));
+    check!(ffi::c_take_unique_ptr_vector_u8(
+        ffi::c_return_unique_ptr_vector_u8()
+    ));
+    check!(ffi::c_take_unique_ptr_vector_f64(
+        ffi::c_return_unique_ptr_vector_f64()
+    ));
+    check!(ffi::c_take_unique_ptr_vector_shared(
+        ffi::c_return_unique_ptr_vector_shared()
+    ));
+
+    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
+
+    check!(ffi::c_take_vec_shared(&vec![
+        ffi::Shared { z: 1010 },
+        ffi::Shared { z: 1011 }
+    ]));
 }
 
 #[test]
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2e70499..4552f46 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -54,6 +54,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "codespan"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
 name = "codespan-reporting"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -69,6 +78,7 @@ version = "0.2.10"
 dependencies = [
  "anyhow",
  "cc",
+ "codespan",
  "codespan-reporting",
  "cxx-test-suite",
  "cxxbridge-macro",

From 37dd7e11742d7fd0d7d67813e520186625281986 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 25 2020 19:51:59 +0000
Subject: [PATCH 356/2232] Format with clang-format


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 387c56a..0274ff1 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -24,7 +24,7 @@ std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
   return vec;
 }
 
-JsonBlob get_jb(const ::rust::Vec<uint8_t>& vec) {
+JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec) {
   JsonBlob retval;
 
   std::cout << "incoming vec length is " << vec.size() << "\n";
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index eea0af7..29a3ba1 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -20,7 +20,7 @@ struct JsonBlob;
 std::unique_ptr<ThingC> make_demo(::rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
-JsonBlob get_jb(const ::rust::Vec<uint8_t>& vec);
+JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec);
 
 } // namespace example
 } // namespace org
diff --git a/include/cxx.h b/include/cxx.h
index 35e9059..0a664d0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -5,9 +5,9 @@
 #include <exception>
 #include <iosfwd>
 #include <string>
-#include <vector>
 #include <type_traits>
 #include <utility>
+#include <vector>
 #if defined(_WIN32)
 #include <BaseTsd.h>
 #endif
@@ -97,7 +97,7 @@ private:
   Vec(const Vec &other) noexcept;
   Vec &operator=(Vec other) noexcept;
   void drop() noexcept;
-  
+
   // Repr
   const T *ptr;
   size_t len;
diff --git a/src/cxx.cc b/src/cxx.cc
index 916f525..a0e92ac 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -3,8 +3,8 @@
 #include <exception>
 #include <iostream>
 #include <memory>
-#include <vector>
 #include <stdexcept>
+#include <vector>
 
 template <typename Exception>
 static void panic [[noreturn]] (const char *msg) {
@@ -199,38 +199,56 @@ void cxxbridge02$unique_ptr$std$string$drop(
 }
 } // extern "C"
 
-#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \
-extern "C" { \
-size_t cxxbridge02$std$vector$##RUST_TYPE##$length(const std::vector<CXX_TYPE> &s) noexcept { \
-  return s.size(); \
-} \
-void cxxbridge02$std$vector$##RUST_TYPE##$push_back(std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept { \
-  s.push_back(item); \
-} \
-const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(const std::vector<CXX_TYPE> &s, size_t pos) noexcept { \
-  return &s[pos]; \
-} \
-static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) == sizeof(void *), ""); \
-static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) == alignof(void *), ""); \
-void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
-  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(); \
-} \
-void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr, std::vector<CXX_TYPE> *value) noexcept { \
-  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(new std::vector<CXX_TYPE>(::std::move(*value))); \
-} \
-void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr, std::vector<CXX_TYPE> *raw) noexcept { \
-  new (ptr) ::std::unique_ptr<std::vector<CXX_TYPE>>(raw); \
-} \
-const std::vector<CXX_TYPE> *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(const ::std::unique_ptr<std::vector<CXX_TYPE>>& ptr) noexcept { \
-  return ptr.get(); \
-} \
-std::vector<CXX_TYPE> *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(::std::unique_ptr<std::vector<CXX_TYPE>>& ptr) noexcept { \
-  return ptr.release(); \
-} \
-void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \
-  ptr->~unique_ptr(); \
-} \
-} // extern "C"
+#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
+  extern "C" {                                                                 \
+  size_t cxxbridge02$std$vector$##RUST_TYPE##$length(                          \
+      const std::vector<CXX_TYPE> &s) noexcept {                               \
+    return s.size();                                                           \
+  }                                                                            \
+  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
+      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
+    s.push_back(item);                                                         \
+  }                                                                            \
+  const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
+      const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
+    return &s[pos];                                                            \
+  }                                                                            \
+  static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
+                    sizeof(void *),                                            \
+                "");                                                           \
+  static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==           \
+                    alignof(void *),                                           \
+                "");                                                           \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>();                       \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(                    \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::vector<CXX_TYPE> *value) noexcept {                                 \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(                         \
+        new std::vector<CXX_TYPE>(::std::move(*value)));                       \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::vector<CXX_TYPE> *raw) noexcept {                                   \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(raw);                    \
+  }                                                                            \
+  const std::vector<CXX_TYPE> *                                                \
+      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
+          const ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {      \
+    return ptr.get();                                                          \
+  }                                                                            \
+  std::vector<CXX_TYPE> *                                                      \
+      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
+          ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {            \
+    return ptr.release();                                                      \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+    ptr->~unique_ptr();                                                        \
+  }                                                                            \
+  } // extern "C"
 
 STD_VECTOR_OPS(u8, uint8_t);
 STD_VECTOR_OPS(u16, uint16_t);
@@ -244,4 +262,3 @@ STD_VECTOR_OPS(i64, int64_t);
 STD_VECTOR_OPS(isize, rust::isize);
 STD_VECTOR_OPS(f32, float);
 STD_VECTOR_OPS(f64, double);
-
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9f11d9f..446486d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,7 +1,7 @@
-#include <numeric>
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs.h"
 #include <cstring>
+#include <numeric>
 #include <stdexcept>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
@@ -59,7 +59,8 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
 }
 
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
-  auto retval = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  auto retval =
+      std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
   retval->push_back(86);
   retval->push_back(75);
   retval->push_back(30);
@@ -162,7 +163,7 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   }
 }
 
-void c_take_vec_u8(const ::rust::Vec<uint8_t>& v) {
+void c_take_vec_u8(const ::rust::Vec<uint8_t> &v) {
   auto cv = static_cast<std::vector<uint8_t>>(v);
   uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
   if (sum == 200) {
@@ -170,10 +171,10 @@ void c_take_vec_u8(const ::rust::Vec<uint8_t>& v) {
   }
 }
 
-void c_take_vec_shared(const ::rust::Vec<Shared>& v) {
+void c_take_vec_shared(const ::rust::Vec<Shared> &v) {
   auto cv = static_cast<std::vector<Shared>>(v);
   uint32_t sum = 0;
-  for (auto i: cv) {
+  for (auto i : cv) {
     sum += i.z;
   }
   if (sum == 2021) {
@@ -195,8 +196,8 @@ std::unique_ptr<std::string> c_try_return_string() {
   return std::unique_ptr<std::string>(new std::string("ok"));
 }
 
-std::unique_ptr<std::string> c_fail_return_string() { 
-  throw std::logic_error("logic error getting string"); 
+std::unique_ptr<std::string> c_fail_return_string() {
+  throw std::logic_error("logic error getting string");
 }
 
 rust::Box<R> c_try_return_box() { return c_return_box(); }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 9e75c37..d2ce44e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -47,8 +47,8 @@ void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 
-void c_take_vec_u8(const ::rust::Vec<uint8_t>& v);
-void c_take_vec_shared(const ::rust::Vec<Shared>& v);
+void c_take_vec_u8(const ::rust::Vec<uint8_t> &v);
+void c_take_vec_shared(const ::rust::Vec<Shared> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();

From 7c29546739e60197982bfe9d229ca7ac4d493475 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 25 2020 20:13:43 +0000
Subject: [PATCH 357/2232] Revert some unrelated changes from PR 67


---

diff --git a/Cargo.toml b/Cargo.toml
index 95cd87d..f497482 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,7 +17,6 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 cc = "1.0.49"
-codespan = "0.7"
 codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.10", path = "macro" }
 link-cplusplus = "1.0"
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 0274ff1..4940834 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -9,7 +9,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
-std::unique_ptr<ThingC> make_demo(::rust::Str appname) {
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
   return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
 }
 
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 29a3ba1..2c9f1c0 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -17,7 +17,7 @@ public:
 struct SharedThing;
 struct JsonBlob;
 
-std::unique_ptr<ThingC> make_demo(::rust::Str appname);
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
 JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec);
diff --git a/gen/write.rs b/gen/write.rs
index a74833f..8a60f17 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -44,7 +44,7 @@ pub(super) fn gen(
             Api::Struct(strct) => write_struct_decl(out, &strct.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident),
             Api::RustType(ety) => write_struct_decl(out, &ety.ident),
-            _ => (),
+            _ => {}
         }
     }
 
@@ -127,7 +127,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             Type::UniquePtr(_) => out.include.memory = true,
             Type::Vector(_) => out.include.vector = true,
             Type::SliceRefU8(_) => out.include.cstdint = true,
-            _ => (),
+            _ => {}
         }
     }
 }
@@ -139,6 +139,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_box = false;
     let mut needs_rust_vec = false;
     let mut needs_rust_fn = false;
+    let mut needs_rust_isize = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -160,6 +161,10 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Type::Slice(_) | Type::SliceRefU8(_) => {
                 needs_rust_slice = true;
             }
+            ty if ty == Isize => {
+                out.include.base_tsd = true;
+                needs_rust_isize = true;
+            }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
@@ -219,6 +224,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_rust_vec
         || needs_rust_fn
         || needs_rust_error
+        || needs_rust_isize
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
@@ -239,6 +245,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
     write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
 
     if needs_manually_drop {
diff --git a/include/cxx.h b/include/cxx.h
index 0a664d0..31b3dde 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -256,11 +256,14 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_ERROR
 
+#ifndef CXXBRIDGE02_RUST_ISIZE
+#define CXXBRIDGE02_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
+#endif // CXXBRIDGE02_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 99ae923..ca0e326 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -19,7 +19,7 @@ quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.2.7-alpha-1", path = ".." }
+cxx = { version = "0.2", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 27f5f6d..da0040a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -44,7 +44,6 @@ pub mod ffi {
         fn c_take_unique_ptr_vector_u8(s: UniquePtr<Vector<u8>>);
         fn c_take_unique_ptr_vector_f64(s: UniquePtr<Vector<f64>>);
         fn c_take_unique_ptr_vector_shared(s: UniquePtr<Vector<Shared>>);
-
         fn c_take_vec_u8(v: &Vec<u8>);
         fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);
@@ -52,8 +51,6 @@ pub mod ffi {
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
         fn c_fail_return_primitive() -> Result<usize>;
-        fn c_try_return_string() -> Result<UniquePtr<CxxString>>;
-        fn c_fail_return_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_box() -> Result<Box<R>>;
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 446486d..a8d7018 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -192,14 +192,6 @@ size_t c_try_return_primitive() { return 2020; }
 
 size_t c_fail_return_primitive() { throw std::logic_error("logic error"); }
 
-std::unique_ptr<std::string> c_try_return_string() {
-  return std::unique_ptr<std::string>(new std::string("ok"));
-}
-
-std::unique_ptr<std::string> c_fail_return_string() {
-  throw std::logic_error("logic error getting string");
-}
-
 rust::Box<R> c_try_return_box() { return c_return_box(); }
 
 const rust::String &c_try_return_ref(const rust::String &s) { return s; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index d2ce44e..876e3c5 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -46,7 +46,6 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
-
 void c_take_vec_u8(const ::rust::Vec<uint8_t> &v);
 void c_take_vec_shared(const ::rust::Vec<Shared> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
@@ -54,8 +53,6 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_try_return_void();
 size_t c_try_return_primitive();
 size_t c_fail_return_primitive();
-std::unique_ptr<std::string> c_try_return_string();
-std::unique_ptr<std::string> c_fail_return_string();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
diff --git a/tests/test.rs b/tests/test.rs
index 17fcfca..b33c675 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -81,18 +81,6 @@ fn test_c_try_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
-    assert_eq!(
-        "ok",
-        ffi::c_try_return_string()
-            .unwrap()
-            .as_ref()
-            .unwrap()
-            .to_string()
-    );
-    assert_eq!(
-        "logic error getting string",
-        ffi::c_fail_return_string().unwrap_err().what(),
-    );
     assert_eq!(2020, *ffi::c_try_return_box().unwrap());
     assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
@@ -125,9 +113,7 @@ fn test_c_take() {
     check!(ffi::c_take_unique_ptr_vector_shared(
         ffi::c_return_unique_ptr_vector_shared()
     ));
-
     check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
-
     check!(ffi::c_take_vec_shared(&vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4552f46..2e70499 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -54,15 +54,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "codespan"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21094c000d5db8035900662bbfddec754e79f795324254ac0817f36e5ccfc3f5"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "codespan-reporting"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -78,7 +69,6 @@ version = "0.2.10"
 dependencies = [
  "anyhow",
  "cc",
- "codespan",
  "codespan-reporting",
  "cxx-test-suite",
  "cxxbridge-macro",

From 507c2d75cfb929b7c153a0f2eb11529cb085dd82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:01:54 +0000
Subject: [PATCH 358/2232] Merge pull request #67 from myronahn/master


C++ std::vector<T> and Rust std::vec::Vec<T> support
---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..4940834 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -15,7 +15,35 @@ std::unique_ptr<ThingC> make_demo(rust::Str appname) {
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
-void do_thing(SharedThing state) { print_r(*state.y); }
+std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
+  print_r(*state.y);
+  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  for (uint8_t i = 0; i < 10; i++) {
+    vec->push_back(i * i);
+  }
+  return vec;
+}
+
+JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec) {
+  JsonBlob retval;
+
+  std::cout << "incoming vec length is " << vec.size() << "\n";
+  auto vec_copy = static_cast<std::vector<uint8_t>>(vec);
+  std::cout << "vec_copy length is " << vec_copy.size() << "\n";
+  std::cout << "vec_copy[0] is " << (int)vec_copy[0] << "\n";
+
+  auto blob = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  for (uint8_t i = 0; i < 10; i++) {
+    blob->push_back(i * 2);
+  }
+
+  auto json = std::unique_ptr<std::string>(new std::string("{\"demo\": 23}"));
+
+  retval.json = std::move(json);
+  retval.blob = std::move(blob);
+
+  return retval;
+}
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index fafc474..2c9f1c0 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -15,10 +15,12 @@ public:
 };
 
 struct SharedThing;
+struct JsonBlob;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
+std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
+JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec);
 
 } // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 66dfc79..8bf9926 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -6,13 +6,19 @@ mod ffi {
         x: UniquePtr<ThingC>,
     }
 
+    struct JsonBlob {
+        json: UniquePtr<CxxString>,
+        blob: UniquePtr<Vector<u8>>,
+    }
+
     extern "C" {
         include!("demo-cxx/demo.h");
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
         fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
+        fn do_thing(state: SharedThing) -> UniquePtr<Vector<u8>>;
+        fn get_jb(v: &Vec<u8>) -> JsonBlob;
     }
 
     extern "Rust" {
@@ -31,9 +37,24 @@ fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
     println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
 
-    ffi::do_thing(ffi::SharedThing {
+    let vec = ffi::do_thing(ffi::SharedThing {
         z: 222,
         y: Box::new(ThingR(333)),
         x,
     });
+
+    println!("vec length = {}", vec.as_ref().unwrap().size());
+    for (i, v) in vec.as_ref().unwrap().into_iter().enumerate() {
+        println!("vec[{}] = {}", i, v);
+    }
+
+    let mut rv: Vec<u8> = Vec::new();
+    for _ in 0..1000 {
+        rv.push(33);
+    }
+    let jb = ffi::get_jb(&rv);
+    println!("json: {}", jb.json.as_ref().unwrap());
+    for (i, v) in jb.blob.as_ref().unwrap().into_iter().enumerate() {
+        println!("jb.blob[{}] = {}", i, v);
+    }
 }
diff --git a/gen/include.rs b/gen/include.rs
index 8f38fe3..077d03e 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -36,6 +36,7 @@ pub struct Includes {
     pub exception: bool,
     pub memory: bool,
     pub string: bool,
+    pub vector: bool,
     pub type_traits: bool,
     pub utility: bool,
     pub base_tsd: bool,
diff --git a/gen/write.rs b/gen/write.rs
index a8e3fd4..8a60f17 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,8 +1,10 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
+use crate::syntax::typename::ToTypename;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -123,6 +125,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
+            Type::Vector(_) => out.include.vector = true,
             Type::SliceRefU8(_) => out.include.cstdint = true,
             _ => {}
         }
@@ -134,6 +137,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_str = false;
     let mut needs_rust_slice = false;
     let mut needs_rust_box = false;
+    let mut needs_rust_vec = false;
     let mut needs_rust_fn = false;
     let mut needs_rust_isize = false;
     for ty in types {
@@ -142,6 +146,10 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 out.include.type_traits = true;
                 needs_rust_box = true;
             }
+            Type::RustVec(_) => {
+                out.include.type_traits = true;
+                needs_rust_vec = true;
+            }
             Type::Str(_) => {
                 out.include.cstdint = true;
                 out.include.string = true;
@@ -213,6 +221,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_rust_str
         || needs_rust_slice
         || needs_rust_box
+        || needs_rust_vec
         || needs_rust_fn
         || needs_rust_error
         || needs_rust_isize
@@ -233,6 +242,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
     write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
     write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
     write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
     write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
     write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
@@ -469,6 +479,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::Vector(_)) => write!(
+            out,
+            " /* Use RVO to convert to r-value and move construct */"
+        ),
         Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
@@ -779,7 +793,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) => {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) => {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
@@ -796,21 +810,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
+            Some(a) => write!(out, "{}", a.to_cxx()),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
@@ -818,11 +818,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ty.inner);
             write!(out, ">");
         }
+        Type::RustVec(ty) => {
+            write!(out, "::rust::Vec<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
         Type::UniquePtr(ptr) => {
             write!(out, "::std::unique_ptr<");
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::Vector(ty) => {
+            write!(out, "::std::vector<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
         Type::Ref(r) => {
             if r.mutability.is_none() {
                 write!(out, "const ");
@@ -870,6 +880,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::Str(_)
+        | Type::Vector(_)
+        | Type::RustVec(_)
         | Type::SliceRefU8(_)
         | Type::Fn(_) => write!(out, " "),
         Type::Ref(_) => {}
@@ -882,6 +894,11 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         Atom::from(ident).is_none()
     }
 
+    fn allow_vector(ident: &Ident) -> bool {
+        // Note: built-in types such as u8 are already defined in cxx.cc
+        Atom::from(ident).is_none()
+    }
+
     out.begin_block("extern \"C\"");
     for ty in types {
         if let Type::RustBox(ty) = ty {
@@ -889,11 +906,30 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 out.next_section();
                 write_rust_box_extern(out, inner);
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(_) = &ty.inner {
+                out.next_section();
+                write_rust_vec_extern(out, &ty.inner);
+            }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, inner, types);
+                    write_unique_ptr(out, &ptr.inner, types);
+                }
+            } else if let Type::Vector(ptr1) = &ptr.inner {
+                if let Type::Ident(inner) = &ptr1.inner {
+                    if allow_vector(inner) {
+                        out.next_section();
+                        write_unique_ptr(out, &ptr.inner, types);
+                    }
+                }
+            }
+        } else if let Type::Vector(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if allow_vector(inner) {
+                    out.next_section();
+                    write_vector(out, inner);
                 }
             }
         }
@@ -907,6 +943,10 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ty.inner {
                 write_rust_box_impl(out, inner);
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(_) = &ty.inner {
+                write_rust_vec_impl(out, &ty.inner);
+            }
         }
     }
     out.end_block("namespace cxxbridge02");
@@ -937,6 +977,31 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
 }
 
+fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const std::vector<{}> &vector) noexcept;",
+        instance, inner, inner
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
+}
+
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let mut inner = String::new();
     for name in &out.namespace {
@@ -957,16 +1022,44 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
-    out.include.utility = true;
+fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
 
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$drop(this);",
+        instance
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(
+        out,
+        "Vec<{}>::operator std::vector<{}>() const noexcept {{",
+        inner, inner
+    );
+    writeln!(
+        out,
+        "  std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
+        inner, instance,
+    );
+    writeln!(out, "}}");
+}
+
+fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.utility = true;
+    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
+    let inner = ty.to_typename(&namespace);
+    let instance = ty.to_mangled(&namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
@@ -987,18 +1080,21 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    if types.structs.contains_key(ident) {
-        writeln!(
+    match ty {
+        Type::Ident(ident) if types.structs.contains_key(ident) => {
+            writeln!(
             out,
             "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
-        writeln!(
-            out,
-            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
-        );
-        writeln!(out, "}}");
+            writeln!(
+                out,
+                "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+                inner, inner,
+            );
+            writeln!(out, "}}");
+        }
+        _ => (),
     }
     writeln!(
         out,
@@ -1030,3 +1126,50 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     writeln!(out, "}}");
     writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
 }
+
+fn write_vector(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    // Do not apply namespace to built-in type
+    let is_user_type = Atom::from(ident).is_none();
+    if is_user_type {
+        for name in &out.namespace {
+            inner += name;
+            inner += "::";
+        }
+    }
+    let mut instance = inner.clone();
+    if let Some(ti) = Atom::from(ident) {
+        inner += ti.to_cxx();
+    } else {
+        inner += &ident.to_string();
+    };
+    instance += &ident.to_string();
+    let instance = instance.replace("::", "$");
+
+    writeln!(out, "#ifndef CXXBRIDGE02_vector_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
+    writeln!(
+        out,
+        "size_t cxxbridge02$std$vector${}$length(const std::vector<{}> &s) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  return s.size();");
+    writeln!(out, "}}");
+
+    writeln!(
+        out,
+        "void cxxbridge02$std$vector${}$push_back(std::vector<{}> &s, const {} &item) noexcept {{",
+        instance, inner, inner
+    );
+    writeln!(out, "  s.push_back(item);");
+    writeln!(out, "}}");
+
+    writeln!(
+        out,
+        "const {} *cxxbridge02$std$vector${}$get_unchecked(const std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return &s[pos];");
+    writeln!(out, "}}");
+    writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
+}
diff --git a/include/cxx.h b/include/cxx.h
index 7c2594c..8f03cbb 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -7,6 +7,7 @@
 #include <string>
 #include <type_traits>
 #include <utility>
+#include <vector>
 #if defined(_WIN32)
 #include <BaseTsd.h>
 #endif
@@ -83,6 +84,27 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_STR
 
+#ifndef CXXBRIDGE02_RUST_VEC
+#define CXXBRIDGE02_RUST_VEC
+template <typename T>
+class Vec final {
+public:
+  size_t size() const noexcept;
+  explicit operator std::vector<T>() const noexcept;
+
+private:
+  Vec() noexcept;
+  Vec(const Vec &other) noexcept;
+  Vec &operator=(Vec other) noexcept;
+  void drop() noexcept;
+
+  // Repr
+  const T *ptr;
+  size_t len;
+  size_t capacity;
+};
+#endif // CXXBRIDGE02_RUST_VEC
+
 #ifndef CXXBRIDGE02_RUST_SLICE
 #define CXXBRIDGE02_RUST_SLICE
 template <typename T>
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8223572..95a6f1a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,14 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
+use crate::syntax::typename::ToTypename;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, Error, ItemMod, Result, Token};
+use syn::{parse_quote, spanned::Spanned, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -21,6 +23,38 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
+    // "Header" to define newtypes locally so we can implement
+    // traits on them.
+    expanded.extend(quote! {
+        pub struct Vector<T>(pub ::cxx::RealVector<T>);
+        impl<T: cxx::private::VectorTarget<T>> Vector<T> {
+            pub fn size(&self) -> usize {
+                self.0.size()
+            }
+            pub fn get(&self, pos: usize) -> Option<&T> {
+                self.0.get(pos)
+            }
+            pub fn get_unchecked(&self, pos: usize) -> &T {
+                self.0.get_unchecked(pos)
+            }
+            pub fn is_empty(&self) -> bool {
+                self.0.is_empty()
+            }
+            pub fn push_back(&mut self, item: &T) {
+                self.0.push_back(item)
+            }
+        }
+        impl<'a, T: cxx::private::VectorTarget<T>> IntoIterator for &'a Vector<T> {
+            type Item = &'a T;
+            type IntoIter = <&'a ::cxx::RealVector<T> as IntoIterator>::IntoIter;
+
+            fn into_iter(self) -> Self::IntoIter {
+                self.0.into_iter()
+            }
+        }
+        unsafe impl<T> Send for Vector<T> where T: Send + cxx::private::VectorTarget<T> {}
+    });
+
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
@@ -53,10 +87,34 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                     hidden.extend(expand_rust_box(namespace, ident));
                 }
             }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(ident) = &ty.inner {
+                hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+            }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types));
+                    expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
+                }
+            } else if let Type::Vector(_) = &ptr.inner {
+                // Generate code for unique_ptr<vector<T>> if T is not an atom
+                // or if T is a primitive.
+                // Code for primitives is already generated
+                match Atom::from(ident) {
+                    None => expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types)),
+                    Some(atom) => {
+                        if atom.is_valid_vector_target() {
+                            expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
+                        }
+                    }
+                }
+            }
+        } else if let Type::Vector(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(ident).is_none() {
+                    // Generate code for Vector<T> if T is not an atom
+                    // Code for atoms is already generated
+                    expanded.extend(expand_vector(namespace, &ptr.inner));
                 }
             }
         }
@@ -192,10 +250,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
+            Type::RustVec(_) => quote!(::cxx::RustVec::from(#var)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
                 }
+                Type::RustVec(_) => quote!(::cxx::RustVec::from_ref(#var)),
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -518,9 +578,42 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
-    let name = ident.to_string();
-    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
+fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
+    let link_drop = format!("{}drop", link_prefix);
+    let link_vector_from = format!("{}vector_from", link_prefix);
+    let link_len = format!("{}len", link_prefix);
+
+    let local_prefix = format_ident!("{}__vec_", ident);
+    let local_drop = format_ident!("{}drop", local_prefix);
+    let local_vector_from = format_ident!("{}vector_from", local_prefix);
+    let local_len = format_ident!("{}len", local_prefix);
+
+    let span = ty.span();
+    quote_spanned! {span=>
+        #[doc(hidden)]
+        #[export_name = #link_drop]
+        unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
+            std::ptr::drop_in_place(this);
+        }
+        #[export_name = #link_vector_from]
+        unsafe extern "C" fn #local_vector_from(this: *mut ::cxx::RustVec<#inner>, vector: *mut ::cxx::RealVector<#inner>) {
+            this.as_ref().unwrap().into_vector(vector.as_mut().unwrap());
+        }
+        #[export_name = #link_len]
+        unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
+            this.as_ref().unwrap().len()
+        }
+    }
+}
+
+fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
+    let name = ty.to_typename(&namespace.segments);
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -528,8 +621,8 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) {
-        Some(quote! {
+    let new_method = match ty {
+        Type::Ident(ident) if types.structs.contains_key(ident) => Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
@@ -539,13 +632,12 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
                 unsafe { __new(&mut repr, &mut value) }
                 repr
             }
-        })
-    } else {
-        None
+        }),
+        _ => None,
     };
 
     quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+        unsafe impl ::cxx::private::UniquePtrTarget for #inner {
             const __NAME: &'static str = #name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -560,7 +652,7 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
-                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #ident);
+                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #inner);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __raw(&mut repr, raw);
@@ -569,14 +661,14 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #ident;
+                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #inner;
                 }
                 __get(&repr)
             }
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
-                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #ident;
+                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #inner;
                 }
                 __release(&mut repr)
             }
@@ -591,6 +683,90 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     }
 }
 
+fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
+    let inner = ty;
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$std$vector${}", mangled);
+    let link_length = format!("{}length", prefix);
+    let link_get_unchecked = format!("{}get_unchecked", prefix);
+    let link_push_back = format!("{}push_back", prefix);
+
+    quote! {
+        impl ::cxx::private::VectorTarget<#inner> for #inner {
+            fn get_unchecked(v: &::cxx::RealVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &::cxx::RealVector<#inner>, _: usize) -> &#inner;
+                }
+                unsafe {
+                    __get_unchecked(v, pos)
+                }
+            }
+            fn vector_length(v: &::cxx::RealVector<#inner>) -> usize {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_length]
+                        fn __vector_length(_: &::cxx::RealVector<#inner>) -> usize;
+                    }
+                    __vector_length(v)
+                }
+            }
+            fn push_back(v: &::cxx::RealVector<#inner>, item: &#inner) {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_push_back]
+                        fn __push_back(_: &::cxx::RealVector<#inner>, _: &#inner) -> usize;
+                    }
+                    __push_back(v, item);
+                }
+            }
+        }
+    }
+}
+
+pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
+    let ty = Type::Ident(ident);
+    let inner = &ty;
+    let namespace = Namespace { segments: vec![] };
+    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let prefix = format!("cxxbridge02$std$vector${}", mangled);
+    let link_length = format!("{}length", prefix);
+    let link_get_unchecked = format!("{}get_unchecked", prefix);
+    let link_push_back = format!("{}push_back", prefix);
+
+    quote! {
+        impl VectorTarget<#inner> for #inner {
+            fn get_unchecked(v: &RealVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &RealVector<#inner>, _: usize) -> &#inner;
+                }
+                unsafe {
+                    __get_unchecked(v, pos)
+                }
+            }
+            fn vector_length(v: &RealVector<#inner>) -> usize {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_length]
+                        fn __vector_length(_: &RealVector<#inner>) -> usize;
+                    }
+                    __vector_length(v)
+                }
+            }
+            fn push_back(v: &RealVector<#inner>, item: &#inner) {
+                unsafe {
+                    extern "C" {
+                        #[link_name = #link_push_back]
+                        fn __push_back(_: &RealVector<#inner>, _: &#inner) -> usize;
+                    }
+                    __push_back(v, item);
+                }
+            }
+        }
+    }
+}
+
 fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     match ret {
         Some(ret) => quote!(-> #ret),
@@ -608,11 +784,16 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
     match ty {
         Type::Ident(ident) if ident == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            let inner = &ty.inner;
+            let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
         }
+        Type::RustVec(ty) => quote!(::cxx::RustVec<#ty>),
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
+            Type::RustVec(ty) => {
+                let inner = expand_extern_type(&ty.inner);
+                quote!(&::cxx::RustVec<#inner>)
+            }
             _ => quote!(#ty),
         },
         Type::Str(_) => quote!(::cxx::private::RustStr),
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b56f58e..87fe405 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -14,7 +14,7 @@ mod syntax;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod};
+use syn::{parse_macro_input, Ident, ItemMod};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,3 +44,9 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
+
+#[proc_macro]
+pub fn vector_builtin(input: TokenStream) -> TokenStream {
+    let ident = parse_macro_input!(input as Ident);
+    expand::expand_vector_builtin(ident).into()
+}
diff --git a/src/cxx.cc b/src/cxx.cc
index b64333c..a0e92ac 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -4,6 +4,7 @@
 #include <iostream>
 #include <memory>
 #include <stdexcept>
+#include <vector>
 
 template <typename Exception>
 static void panic [[noreturn]] (const char *msg) {
@@ -197,3 +198,67 @@ void cxxbridge02$unique_ptr$std$string$drop(
   ptr->~unique_ptr();
 }
 } // extern "C"
+
+#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
+  extern "C" {                                                                 \
+  size_t cxxbridge02$std$vector$##RUST_TYPE##$length(                          \
+      const std::vector<CXX_TYPE> &s) noexcept {                               \
+    return s.size();                                                           \
+  }                                                                            \
+  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
+      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
+    s.push_back(item);                                                         \
+  }                                                                            \
+  const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
+      const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
+    return &s[pos];                                                            \
+  }                                                                            \
+  static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
+                    sizeof(void *),                                            \
+                "");                                                           \
+  static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==           \
+                    alignof(void *),                                           \
+                "");                                                           \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>();                       \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(                    \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::vector<CXX_TYPE> *value) noexcept {                                 \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(                         \
+        new std::vector<CXX_TYPE>(::std::move(*value)));                       \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::vector<CXX_TYPE> *raw) noexcept {                                   \
+    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(raw);                    \
+  }                                                                            \
+  const std::vector<CXX_TYPE> *                                                \
+      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
+          const ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {      \
+    return ptr.get();                                                          \
+  }                                                                            \
+  std::vector<CXX_TYPE> *                                                      \
+      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
+          ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {            \
+    return ptr.release();                                                      \
+  }                                                                            \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+    ptr->~unique_ptr();                                                        \
+  }                                                                            \
+  } // extern "C"
+
+STD_VECTOR_OPS(u8, uint8_t);
+STD_VECTOR_OPS(u16, uint16_t);
+STD_VECTOR_OPS(u32, uint32_t);
+STD_VECTOR_OPS(u64, uint64_t);
+STD_VECTOR_OPS(usize, size_t);
+STD_VECTOR_OPS(i8, int8_t);
+STD_VECTOR_OPS(i16, int16_t);
+STD_VECTOR_OPS(i32, int32_t);
+STD_VECTOR_OPS(i64, int64_t);
+STD_VECTOR_OPS(isize, rust::isize);
+STD_VECTOR_OPS(f32, float);
+STD_VECTOR_OPS(f64, double);
diff --git a/src/lib.rs b/src/lib.rs
index 304a87a..e23be69 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -370,13 +370,18 @@ mod result;
 mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
+mod rust_vec;
 mod syntax;
 mod unique_ptr;
 mod unwind;
+mod vector;
 
 pub use crate::cxx_string::CxxString;
 pub use crate::exception::Exception;
+pub use crate::rust_vec::RustVec;
 pub use crate::unique_ptr::UniquePtr;
+pub use crate::vector::RealVector;
+pub use crate::vector::VectorIntoIterator;
 pub use cxxbridge_macro::bridge;
 
 // Not public API.
@@ -390,6 +395,7 @@ pub mod private {
     pub use crate::rust_string::RustString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
+    pub use crate::vector::VectorTarget;
 }
 
 use crate::error::Result;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
new file mode 100644
index 0000000..a28570d
--- /dev/null
+++ b/src/rust_vec.rs
@@ -0,0 +1,39 @@
+use crate::vector::RealVector;
+use crate::vector::VectorTarget;
+
+#[repr(C)]
+pub struct RustVec<T: VectorTarget<T>> {
+    repr: Vec<T>,
+}
+
+impl<T: VectorTarget<T>> RustVec<T> {
+    pub fn from(v: Vec<T>) -> Self {
+        RustVec { repr: v }
+    }
+
+    pub fn from_ref(v: &Vec<T>) -> &Self {
+        unsafe { std::mem::transmute::<&Vec<T>, &RustVec<T>>(v) }
+    }
+
+    pub fn into_vec(self) -> Vec<T> {
+        self.repr
+    }
+
+    pub fn as_vec(&self) -> &Vec<T> {
+        &self.repr
+    }
+
+    pub fn as_mut_vec(&mut self) -> &mut Vec<T> {
+        &mut self.repr
+    }
+
+    pub fn len(&self) -> usize {
+        self.repr.len()
+    }
+
+    pub fn into_vector(&self, vec: &mut RealVector<T>) {
+        for item in &self.repr {
+            vec.push_back(item);
+        }
+    }
+}
diff --git a/src/vector.rs b/src/vector.rs
new file mode 100644
index 0000000..805bdbb
--- /dev/null
+++ b/src/vector.rs
@@ -0,0 +1,91 @@
+pub trait VectorTarget<T> {
+    fn get_unchecked(v: &RealVector<T>, pos: usize) -> &T
+    where
+        Self: Sized;
+    fn vector_length(v: &RealVector<T>) -> usize
+    where
+        Self: Sized;
+    fn push_back(v: &RealVector<T>, item: &T)
+    where
+        Self: Sized;
+}
+
+/// Binding to C++ `std::vector`.
+///
+/// # Invariants
+///
+/// As an invariant of this API and the static analysis of the cxx::bridge
+/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
+/// requires a move constructor and may hold internal pointers, which is not
+/// compatible with Rust's move behavior. Instead in Rust code we will only ever
+/// look at a Vector through a reference or smart pointer, as in `&Vector`
+/// or `UniquePtr<Vector>`.
+#[repr(C)]
+pub struct RealVector<T> {
+    _private: [T; 0],
+}
+
+impl<T: VectorTarget<T>> RealVector<T> {
+    /// Returns the length of the vector in bytes.
+    pub fn size(&self) -> usize {
+        T::vector_length(self)
+    }
+
+    pub fn get_unchecked(&self, pos: usize) -> &T {
+        T::get_unchecked(self, pos)
+    }
+
+    /// Returns true if `self` has a length of zero bytes.
+    pub fn is_empty(&self) -> bool {
+        self.size() == 0
+    }
+
+    pub fn get(&self, pos: usize) -> Option<&T> {
+        if pos < self.size() {
+            Some(self.get_unchecked(pos))
+        } else {
+            None
+        }
+    }
+
+    pub fn push_back(&mut self, item: &T) {
+        T::push_back(self, item);
+    }
+}
+
+unsafe impl<T> Send for RealVector<T> where T: Send + VectorTarget<T> {}
+
+pub struct VectorIntoIterator<'a, T> {
+    v: &'a RealVector<T>,
+    index: usize,
+}
+
+impl<'a, T: VectorTarget<T>> IntoIterator for &'a RealVector<T> {
+    type Item = &'a T;
+    type IntoIter = VectorIntoIterator<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        VectorIntoIterator { v: self, index: 0 }
+    }
+}
+
+impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
+    type Item = &'a T;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.index = self.index + 1;
+        self.v.get(self.index - 1)
+    }
+}
+
+cxxbridge_macro::vector_builtin!(u8);
+cxxbridge_macro::vector_builtin!(u16);
+cxxbridge_macro::vector_builtin!(u32);
+cxxbridge_macro::vector_builtin!(u64);
+cxxbridge_macro::vector_builtin!(usize);
+cxxbridge_macro::vector_builtin!(i8);
+cxxbridge_macro::vector_builtin!(i16);
+cxxbridge_macro::vector_builtin!(i32);
+cxxbridge_macro::vector_builtin!(i64);
+cxxbridge_macro::vector_builtin!(isize);
+cxxbridge_macro::vector_builtin!(f32);
+cxxbridge_macro::vector_builtin!(f64);
diff --git a/syntax/atom.rs b/syntax/atom.rs
index eeea831..c68b3fe 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -42,6 +42,43 @@ impl Atom {
             _ => None,
         }
     }
+
+    pub fn to_cxx(&self) -> &'static str {
+        use self::Atom::*;
+        match self {
+            Bool => "bool",
+            U8 => "uint8_t",
+            U16 => "uint16_t",
+            U32 => "uint32_t",
+            U64 => "uint64_t",
+            Usize => "size_t",
+            I8 => "int8_t",
+            I16 => "int16_t",
+            I32 => "int32_t",
+            I64 => "int64_t",
+            Isize => "::rust::isize",
+            F32 => "float",
+            F64 => "double",
+            CxxString => "::std::string",
+            RustString => "::rust::String",
+        }
+    }
+
+    pub fn is_valid_vector_target(&self) -> bool {
+        use self::Atom::*;
+        *self == U8
+            || *self == U16
+            || *self == U32
+            || *self == U64
+            || *self == Usize
+            || *self == I8
+            || *self == I16
+            || *self == I32
+            || *self == I64
+            || *self == Isize
+            || *self == F32
+            || *self == F64
+    }
 }
 
 impl PartialEq<Atom> for Ident {
diff --git a/syntax/check.rs b/syntax/check.rs
index 5e8cc09..387f9a6 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,7 +29,9 @@ fn do_typecheck(cx: &mut Check) {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
+            Type::RustVec(ptr) => check_type_vec(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::Vector(ptr) => check_type_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
@@ -87,6 +89,21 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported target type of Box");
 }
 
+fn check_type_vec(cx: &mut Check, ptr: &Ty1) {
+    // Vec can contain either user-defined type or u8
+    if let Type::Ident(ident) = &ptr.inner {
+        if Atom::from(ident).map(|a| a.is_valid_vector_target()) == Some(true) {
+            return;
+        } else if cx.types.cxx.contains(ident) {
+            cx.error(ptr, error::VEC_CXX_TYPE.msg);
+        } else {
+            return;
+        }
+    }
+
+    cx.error(ptr, "unsupported target type of Vec");
+}
+
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
@@ -97,11 +114,31 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
             None | Some(CxxString) => return,
             _ => {}
         }
+    } else if let Type::Vector(_) = &ptr.inner {
+        return;
     }
 
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
+fn check_type_vector(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(ident) {
+            cx.error(ptr, "vector of a Rust type is not supported yet");
+        }
+
+        match Atom::from(ident) {
+            None => return,
+            Some(atom) => {
+                if atom.is_valid_vector_target() {
+                    return;
+                }
+            }
+        }
+    }
+    cx.error(ptr, "unsupported vector target type");
+}
+
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
     if ty.lifetime.is_some() {
         cx.error(ty, "references with explicit lifetimes are not supported");
@@ -310,9 +347,11 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
             }
         }
         Type::RustBox(_) => "Box".to_owned(),
+        Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
+        Type::Vector(_) => "vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
diff --git a/syntax/error.rs b/syntax/error.rs
index f52d651..103a54f 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -15,6 +15,7 @@ impl Display for Error {
 
 pub static ERRORS: &[Error] = &[
     BOX_CXX_TYPE,
+    VEC_CXX_TYPE,
     CXXBRIDGE_RESERVED,
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
@@ -29,6 +30,12 @@ pub static BOX_CXX_TYPE: Error = Error {
     note: Some("hint: use UniquePtr<>"),
 };
 
+pub static VEC_CXX_TYPE: Error = Error {
+    msg: "Vec of a C++ type is not supported yet",
+    label: None,
+    note: Some("hint: use UniquePtr<>"),
+};
+
 pub static CXXBRIDGE_RESERVED: Error = Error {
     msg: "identifiers starting with cxxbridge are reserved",
     label: Some("reserved identifier"),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a2ce05b..8e94f06 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -26,6 +26,8 @@ impl Hash for Type {
             Type::UniquePtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
+            Type::RustVec(t) => t.hash(state),
+            Type::Vector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
@@ -44,6 +46,8 @@ impl PartialEq for Type {
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
+            (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
+            (Type::Vector(lhs), Type::Vector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
             (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
new file mode 100644
index 0000000..56e8b73
--- /dev/null
+++ b/syntax/mangled.rs
@@ -0,0 +1,30 @@
+use crate::syntax::{Atom, Type};
+
+pub trait ToMangled {
+    fn to_mangled(&self, namespace: &Vec<String>) -> String;
+}
+
+impl ToMangled for Type {
+    fn to_mangled(&self, namespace: &Vec<String>) -> String {
+        match self {
+            Type::Ident(ident) => {
+                let mut instance = String::new();
+                // Do not apply namespace to built-in type
+                let is_user_type = Atom::from(ident).is_none();
+                if is_user_type {
+                    for name in namespace {
+                        instance += name;
+                        instance += "$";
+                    }
+                }
+                instance += &ident.to_string();
+                instance
+            }
+            Type::RustBox(ptr) => format!("rust_box${}", ptr.inner.to_mangled(namespace)),
+            Type::RustVec(ptr) => format!("rust_vec${}", ptr.inner.to_mangled(namespace)),
+            Type::UniquePtr(ptr) => format!("std$unique_ptr${}", ptr.inner.to_mangled(namespace)),
+            Type::Vector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
+            _ => unimplemented!(),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index ab5cecc..4e0b908 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -8,11 +8,13 @@ pub mod error;
 pub mod ident;
 mod impls;
 pub mod mangle;
+pub mod mangled;
 pub mod namespace;
 mod parse;
 pub mod set;
 pub mod symbol;
 mod tokens;
+pub mod typename;
 pub mod types;
 
 use self::parse::kw;
@@ -86,9 +88,11 @@ pub struct Receiver {
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),
+    RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
+    Vector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
     Slice(Box<Slice>),
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index d26bb9e..a4e972b 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -11,7 +11,7 @@ mod kw {
 
 #[derive(Clone)]
 pub struct Namespace {
-    segments: Vec<String>,
+    pub segments: Vec<String>,
 }
 
 impl Namespace {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7d92b1b..f5c598d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,6 +300,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "Vector" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::Vector(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
@@ -310,6 +320,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "Vec" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::RustVec(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 26bb3d1..3d67a0a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -14,7 +14,9 @@ impl ToTokens for Type {
                 }
                 ident.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens),
+            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+                ty.to_tokens(tokens)
+            }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
             Type::Slice(s) => s.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
@@ -33,7 +35,8 @@ impl ToTokens for Var {
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if self.name == "UniquePtr" {
+        // Do not add cxx namespace to Vector since we're defining it in the user crate
+        if self.name == "UniquePtr" || self.name == "RustVec" {
             let span = self.name.span();
             tokens.extend(quote_spanned!(span=> ::cxx::));
         }
diff --git a/syntax/typename.rs b/syntax/typename.rs
new file mode 100644
index 0000000..883e1fb
--- /dev/null
+++ b/syntax/typename.rs
@@ -0,0 +1,36 @@
+use crate::syntax::{Atom, Type};
+
+pub trait ToTypename {
+    fn to_typename(&self, namespace: &Vec<String>) -> String;
+}
+
+impl ToTypename for Type {
+    fn to_typename(&self, namespace: &Vec<String>) -> String {
+        match self {
+            Type::Ident(ident) => {
+                let mut inner = String::new();
+                // Do not apply namespace to built-in type
+                let is_user_type = Atom::from(ident).is_none();
+                if is_user_type {
+                    for name in namespace {
+                        inner += name;
+                        inner += "::";
+                    }
+                }
+                if let Some(ti) = Atom::from(ident) {
+                    inner += ti.to_cxx();
+                } else {
+                    inner += &ident.to_string();
+                };
+                inner
+            }
+            Type::RustBox(ptr) => format!("rust_box<{}>", ptr.inner.to_typename(namespace)),
+            Type::RustVec(ptr) => format!("rust_vec<{}>", ptr.inner.to_typename(namespace)),
+            Type::UniquePtr(ptr) => {
+                format!("std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
+            }
+            Type::Vector(ptr) => format!("std::vector<{}>", ptr.inner.to_typename(namespace)),
+            _ => unimplemented!(),
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 6f3af09..7bce154 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -24,7 +24,9 @@ impl<'a> Types<'a> {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
-                Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner),
+                Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+                    visit(all, &ty.inner)
+                }
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index efdd1fa..da0040a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -27,6 +27,9 @@ pub mod ffi {
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
+        fn c_return_unique_ptr_vector_u8() -> UniquePtr<Vector<u8>>;
+        fn c_return_unique_ptr_vector_f64() -> UniquePtr<Vector<f64>>;
+        fn c_return_unique_ptr_vector_shared() -> UniquePtr<Vector<Shared>>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -38,6 +41,11 @@ pub mod ffi {
         fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn c_take_unique_ptr_vector_u8(s: UniquePtr<Vector<u8>>);
+        fn c_take_unique_ptr_vector_f64(s: UniquePtr<Vector<f64>>);
+        fn c_take_unique_ptr_vector_shared(s: UniquePtr<Vector<Shared>>);
+        fn c_take_vec_u8(v: &Vec<u8>);
+        fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 619485a..a8d7018 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,6 +1,7 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs.h"
 #include <cstring>
+#include <numeric>
 #include <stdexcept>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
@@ -57,6 +58,32 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
   return std::unique_ptr<std::string>(new std::string("2020"));
 }
 
+std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
+  auto retval =
+      std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  retval->push_back(86);
+  retval->push_back(75);
+  retval->push_back(30);
+  retval->push_back(9);
+  return retval;
+}
+
+std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
+  auto retval = std::unique_ptr<std::vector<double>>(new std::vector<double>());
+  retval->push_back(86.0);
+  retval->push_back(75.0);
+  retval->push_back(30.0);
+  retval->push_back(9.5);
+  return retval;
+}
+
+std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
+  auto retval = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
+  retval->push_back(Shared{1010});
+  retval->push_back(Shared{1011});
+  return retval;
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -118,6 +145,43 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s) {
   }
 }
 
+void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v) {
+  if (v->size() == 4) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
+  if (v->size() == 4) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
+  if (v->size() == 2) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_vec_u8(const ::rust::Vec<uint8_t> &v) {
+  auto cv = static_cast<std::vector<uint8_t>>(v);
+  uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
+  if (sum == 200) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_vec_shared(const ::rust::Vec<Shared> &v) {
+  auto cv = static_cast<std::vector<Shared>>(v);
+  uint32_t sum = 0;
+  for (auto i : cv) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index ed6d541..876e3c5 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -29,6 +29,9 @@ rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
+std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
+std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
+std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -40,6 +43,11 @@ void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
+void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
+void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
+void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
+void c_take_vec_u8(const ::rust::Vec<uint8_t> &v);
+void c_take_vec_shared(const ::rust::Vec<Shared> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
diff --git a/tests/test.rs b/tests/test.rs
index 1cd85df..b33c675 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -32,6 +32,45 @@ fn test_c_return() {
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
+    assert_eq!(
+        4,
+        ffi::c_return_unique_ptr_vector_u8()
+            .as_ref()
+            .unwrap()
+            .size()
+    );
+    assert_eq!(
+        200_u8,
+        ffi::c_return_unique_ptr_vector_u8()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .sum()
+    );
+    assert_eq!(
+        200.5_f64,
+        ffi::c_return_unique_ptr_vector_f64()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .sum()
+    );
+    assert_eq!(
+        2,
+        ffi::c_return_unique_ptr_vector_shared()
+            .as_ref()
+            .unwrap()
+            .size()
+    );
+    assert_eq!(
+        2021_usize,
+        ffi::c_return_unique_ptr_vector_shared()
+            .as_ref()
+            .unwrap()
+            .into_iter()
+            .map(|o| o.z)
+            .sum()
+    );
 }
 
 #[test]
@@ -65,6 +104,20 @@ fn test_c_take() {
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()
     ));
+    check!(ffi::c_take_unique_ptr_vector_u8(
+        ffi::c_return_unique_ptr_vector_u8()
+    ));
+    check!(ffi::c_take_unique_ptr_vector_f64(
+        ffi::c_return_unique_ptr_vector_f64()
+    ));
+    check!(ffi::c_take_unique_ptr_vector_shared(
+        ffi::c_return_unique_ptr_vector_shared()
+    ));
+    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
+    check!(ffi::c_take_vec_shared(&vec![
+        ffi::Shared { z: 1010 },
+        ffi::Shared { z: 1011 }
+    ]));
 }
 
 #[test]

From 8b7f8993479a981d5a4b5129e364c28cee5d5fc5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 359/2232] Place vector include in sorted order


---

diff --git a/gen/include.rs b/gen/include.rs
index 077d03e..137f52b 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -36,9 +36,9 @@ pub struct Includes {
     pub exception: bool,
     pub memory: bool,
     pub string: bool,
-    pub vector: bool,
     pub type_traits: bool,
     pub utility: bool,
+    pub vector: bool,
     pub base_tsd: bool,
 }
 

From 122905eb229ce5f64f3933a9ebe4b63aef19f962 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 360/2232] Emit <vector> include if generated code requires it


---

diff --git a/gen/include.rs b/gen/include.rs
index 137f52b..129a8e6 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -90,6 +90,9 @@ impl Display for Includes {
         if self.utility {
             writeln!(f, "#include <utility>")?;
         }
+        if self.vector {
+            writeln!(f, "#include <vector>")?;
+        }
         if self.base_tsd {
             writeln!(f, "#if defined(_WIN32)")?;
             writeln!(f, "#include <BaseTsd.h>")?;

From 76c13bf9da2f4a43ba51f0720a739b9b43021b6a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 361/2232] Remove unused type_traits import when generating Rust Vec


---

diff --git a/gen/write.rs b/gen/write.rs
index 8a60f17..270b26e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -147,7 +147,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_box = true;
             }
             Type::RustVec(_) => {
-                out.include.type_traits = true;
                 needs_rust_vec = true;
             }
             Type::Str(_) => {

From 4f6dd4e631173453859ba318a3afb69779158555 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 362/2232] Simplify vector tests using UniquePtr deref


---

diff --git a/tests/test.rs b/tests/test.rs
index b33c675..f394c7a 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -32,44 +32,22 @@ fn test_c_return() {
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
-    assert_eq!(
-        4,
-        ffi::c_return_unique_ptr_vector_u8()
-            .as_ref()
-            .unwrap()
-            .size()
-    );
+    assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().size());
     assert_eq!(
         200_u8,
-        ffi::c_return_unique_ptr_vector_u8()
-            .as_ref()
-            .unwrap()
-            .into_iter()
-            .sum()
+        ffi::c_return_unique_ptr_vector_u8().into_iter().sum(),
     );
     assert_eq!(
         200.5_f64,
-        ffi::c_return_unique_ptr_vector_f64()
-            .as_ref()
-            .unwrap()
-            .into_iter()
-            .sum()
-    );
-    assert_eq!(
-        2,
-        ffi::c_return_unique_ptr_vector_shared()
-            .as_ref()
-            .unwrap()
-            .size()
+        ffi::c_return_unique_ptr_vector_f64().into_iter().sum(),
     );
+    assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().size());
     assert_eq!(
         2021_usize,
         ffi::c_return_unique_ptr_vector_shared()
-            .as_ref()
-            .unwrap()
             .into_iter()
             .map(|o| o.z)
-            .sum()
+            .sum(),
     );
 }
 

From d1413040aed617ec8653942cd925d909746f0ee3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 363/2232] Remove absolute paths in non-generated code


---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 4940834..efa1d1e 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -24,7 +24,7 @@ std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
   return vec;
 }
 
-JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec) {
+JsonBlob get_jb(const rust::Vec<uint8_t> &vec) {
   JsonBlob retval;
 
   std::cout << "incoming vec length is " << vec.size() << "\n";
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 2c9f1c0..9a90716 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -20,7 +20,7 @@ struct JsonBlob;
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
 std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
-JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec);
+JsonBlob get_jb(const rust::Vec<uint8_t> &vec);
 
 } // namespace example
 } // namespace org
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a8d7018..1dd3b73 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -163,7 +163,7 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   }
 }
 
-void c_take_vec_u8(const ::rust::Vec<uint8_t> &v) {
+void c_take_vec_u8(const rust::Vec<uint8_t> &v) {
   auto cv = static_cast<std::vector<uint8_t>>(v);
   uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
   if (sum == 200) {
@@ -171,7 +171,7 @@ void c_take_vec_u8(const ::rust::Vec<uint8_t> &v) {
   }
 }
 
-void c_take_vec_shared(const ::rust::Vec<Shared> &v) {
+void c_take_vec_shared(const rust::Vec<Shared> &v) {
   auto cv = static_cast<std::vector<Shared>>(v);
   uint32_t sum = 0;
   for (auto i : cv) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 876e3c5..e1e163d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -46,8 +46,8 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
-void c_take_vec_u8(const ::rust::Vec<uint8_t> &v);
-void c_take_vec_shared(const ::rust::Vec<Shared> &v);
+void c_take_vec_u8(const rust::Vec<uint8_t> &v);
+void c_take_vec_shared(const rust::Vec<Shared> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();

From 91d1bb9b7dec795f24a25a31f675d721c8e069bb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 364/2232] Use absolute paths consistently in generated code


---

diff --git a/gen/write.rs b/gen/write.rs
index 270b26e..cb61978 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -990,7 +990,7 @@ fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
     );
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const std::vector<{}> &vector) noexcept;",
+        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const ::std::vector<{}> &vector) noexcept;",
         instance, inner, inner
     );
     writeln!(
@@ -1043,12 +1043,12 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "Vec<{}>::operator std::vector<{}>() const noexcept {{",
+        "Vec<{}>::operator ::std::vector<{}>() const noexcept {{",
         inner, inner
     );
     writeln!(
         out,
-        "  std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
+        "  ::std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
         inner, instance,
     );
     writeln!(out, "}}");
@@ -1149,7 +1149,7 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge02$std$vector${}$length(const std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge02$std$vector${}$length(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
@@ -1157,7 +1157,7 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
 
     writeln!(
         out,
-        "void cxxbridge02$std$vector${}$push_back(std::vector<{}> &s, const {} &item) noexcept {{",
+        "void cxxbridge02$std$vector${}$push_back(::std::vector<{}> &s, const {} &item) noexcept {{",
         instance, inner, inner
     );
     writeln!(out, "  s.push_back(item);");
@@ -1165,7 +1165,7 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
 
     writeln!(
         out,
-        "const {} *cxxbridge02$std$vector${}$get_unchecked(const std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return &s[pos];");
diff --git a/syntax/typename.rs b/syntax/typename.rs
index 883e1fb..7ad1be2 100644
--- a/syntax/typename.rs
+++ b/syntax/typename.rs
@@ -27,9 +27,9 @@ impl ToTypename for Type {
             Type::RustBox(ptr) => format!("rust_box<{}>", ptr.inner.to_typename(namespace)),
             Type::RustVec(ptr) => format!("rust_vec<{}>", ptr.inner.to_typename(namespace)),
             Type::UniquePtr(ptr) => {
-                format!("std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
+                format!("::std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
             }
-            Type::Vector(ptr) => format!("std::vector<{}>", ptr.inner.to_typename(namespace)),
+            Type::Vector(ptr) => format!("::std::vector<{}>", ptr.inner.to_typename(namespace)),
             _ => unimplemented!(),
         }
     }

From 4fcfa945c65851149cd9ed9db0ccd49d4e154e92 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:07 +0000
Subject: [PATCH 365/2232] Wrap implementation of vector type conversion


---

diff --git a/gen/write.rs b/gen/write.rs
index cb61978..e89cf0b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1046,11 +1046,14 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
         "Vec<{}>::operator ::std::vector<{}>() const noexcept {{",
         inner, inner
     );
+    writeln!(out, "  ::std::vector<{}> v;", inner);
+    writeln!(out, "  v.reserve(this->size());");
     writeln!(
         out,
-        "  ::std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
-        inner, instance,
+        "  cxxbridge02$rust_vec${}$vector_from(this, v);",
+        instance,
     );
+    writeln!(out, "  return v;");
     writeln!(out, "}}");
 }
 

From 85db5a01b2fc9f6513ee17b93f2f6d2fbb1d5285 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 366/2232] Touch up PR 67


---

diff --git a/gen/write.rs b/gen/write.rs
index e89cf0b..911a3d2 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1031,7 +1031,7 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(
         out,
         "  return cxxbridge02$rust_vec${}$drop(this);",
-        instance
+        instance,
     );
     writeln!(out, "}}");
 
@@ -1044,7 +1044,7 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(
         out,
         "Vec<{}>::operator ::std::vector<{}>() const noexcept {{",
-        inner, inner
+        inner, inner,
     );
     writeln!(out, "  ::std::vector<{}> v;", inner);
     writeln!(out, "  v.reserve(this->size());");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 95a6f1a..1d40419 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -602,6 +602,7 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         unsafe extern "C" fn #local_vector_from(this: *mut ::cxx::RustVec<#inner>, vector: *mut ::cxx::RealVector<#inner>) {
             this.as_ref().unwrap().into_vector(vector.as_mut().unwrap());
         }
+        #[doc(hidden)]
         #[export_name = #link_len]
         unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
             this.as_ref().unwrap().len()
diff --git a/src/vector.rs b/src/vector.rs
index 805bdbb..1436165 100644
--- a/src/vector.rs
+++ b/src/vector.rs
@@ -71,6 +71,7 @@ impl<'a, T: VectorTarget<T>> IntoIterator for &'a RealVector<T> {
 
 impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
     type Item = &'a T;
+
     fn next(&mut self) -> Option<Self::Item> {
         self.index = self.index + 1;
         self.v.get(self.index - 1)
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 1dd3b73..46f04be 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -59,29 +59,28 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
 }
 
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
-  auto retval =
-      std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  retval->push_back(86);
-  retval->push_back(75);
-  retval->push_back(30);
-  retval->push_back(9);
-  return retval;
+  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  vec->push_back(86);
+  vec->push_back(75);
+  vec->push_back(30);
+  vec->push_back(9);
+  return vec;
 }
 
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
-  auto retval = std::unique_ptr<std::vector<double>>(new std::vector<double>());
-  retval->push_back(86.0);
-  retval->push_back(75.0);
-  retval->push_back(30.0);
-  retval->push_back(9.5);
-  return retval;
+  auto vec = std::unique_ptr<std::vector<double>>(new std::vector<double>());
+  vec->push_back(86.0);
+  vec->push_back(75.0);
+  vec->push_back(30.0);
+  vec->push_back(9.5);
+  return vec;
 }
 
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
-  auto retval = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
-  retval->push_back(Shared{1010});
-  retval->push_back(Shared{1011});
-  return retval;
+  auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
+  vec->push_back(Shared{1010});
+  vec->push_back(Shared{1011});
+  return vec;
 }
 
 void c_take_primitive(size_t n) {

From 4f644704123d6614a627a91aae600dd4c6721af3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 367/2232] Remove vector manipulation from demo project


The vector support needs to be covered by our test suite, but it doesn't
need to be featured to this extent in our intro code.

---

diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index efa1d1e..cd447ea 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -15,35 +15,7 @@ std::unique_ptr<ThingC> make_demo(rust::Str appname) {
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
-std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
-  print_r(*state.y);
-  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  for (uint8_t i = 0; i < 10; i++) {
-    vec->push_back(i * i);
-  }
-  return vec;
-}
-
-JsonBlob get_jb(const rust::Vec<uint8_t> &vec) {
-  JsonBlob retval;
-
-  std::cout << "incoming vec length is " << vec.size() << "\n";
-  auto vec_copy = static_cast<std::vector<uint8_t>>(vec);
-  std::cout << "vec_copy length is " << vec_copy.size() << "\n";
-  std::cout << "vec_copy[0] is " << (int)vec_copy[0] << "\n";
-
-  auto blob = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  for (uint8_t i = 0; i < 10; i++) {
-    blob->push_back(i * 2);
-  }
-
-  auto json = std::unique_ptr<std::string>(new std::string("{\"demo\": 23}"));
-
-  retval.json = std::move(json);
-  retval.blob = std::move(blob);
-
-  return retval;
-}
+void do_thing(SharedThing state) { print_r(*state.y); }
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 9a90716..fafc474 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -15,12 +15,10 @@ public:
 };
 
 struct SharedThing;
-struct JsonBlob;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
-std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
-JsonBlob get_jb(const rust::Vec<uint8_t> &vec);
+void do_thing(SharedThing state);
 
 } // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 8bf9926..66dfc79 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -6,19 +6,13 @@ mod ffi {
         x: UniquePtr<ThingC>,
     }
 
-    struct JsonBlob {
-        json: UniquePtr<CxxString>,
-        blob: UniquePtr<Vector<u8>>,
-    }
-
     extern "C" {
         include!("demo-cxx/demo.h");
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
         fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing) -> UniquePtr<Vector<u8>>;
-        fn get_jb(v: &Vec<u8>) -> JsonBlob;
+        fn do_thing(state: SharedThing);
     }
 
     extern "Rust" {
@@ -37,24 +31,9 @@ fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
     println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
 
-    let vec = ffi::do_thing(ffi::SharedThing {
+    ffi::do_thing(ffi::SharedThing {
         z: 222,
         y: Box::new(ThingR(333)),
         x,
     });
-
-    println!("vec length = {}", vec.as_ref().unwrap().size());
-    for (i, v) in vec.as_ref().unwrap().into_iter().enumerate() {
-        println!("vec[{}] = {}", i, v);
-    }
-
-    let mut rv: Vec<u8> = Vec::new();
-    for _ in 0..1000 {
-        rv.push(33);
-    }
-    let jb = ffi::get_jb(&rv);
-    println!("json: {}", jb.json.as_ref().unwrap());
-    for (i, v) in jb.blob.as_ref().unwrap().into_iter().enumerate() {
-        println!("jb.blob[{}] = {}", i, v);
-    }
 }

From a9a7ed18e688456c38ad7bc9362bfe8e72a0f1c3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 368/2232] Remove rust::Vec<T>::operator std::vector<T>


---

diff --git a/gen/write.rs b/gen/write.rs
index 911a3d2..c1aa2f7 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -990,11 +990,6 @@ fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
     );
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const ::std::vector<{}> &vector) noexcept;",
-        instance, inner, inner
-    );
-    writeln!(
-        out,
         "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
@@ -1039,22 +1034,6 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(
-        out,
-        "Vec<{}>::operator ::std::vector<{}>() const noexcept {{",
-        inner, inner,
-    );
-    writeln!(out, "  ::std::vector<{}> v;", inner);
-    writeln!(out, "  v.reserve(this->size());");
-    writeln!(
-        out,
-        "  cxxbridge02$rust_vec${}$vector_from(this, v);",
-        instance,
-    );
-    writeln!(out, "  return v;");
-    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
diff --git a/include/cxx.h b/include/cxx.h
index 8f03cbb..c62faad 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -90,7 +90,6 @@ template <typename T>
 class Vec final {
 public:
   size_t size() const noexcept;
-  explicit operator std::vector<T>() const noexcept;
 
 private:
   Vec() noexcept;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1d40419..f29eeeb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -583,12 +583,10 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
     let mangled = ty.to_mangled(&namespace.segments) + "$";
     let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
     let link_drop = format!("{}drop", link_prefix);
-    let link_vector_from = format!("{}vector_from", link_prefix);
     let link_len = format!("{}len", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", ident);
     let local_drop = format_ident!("{}drop", local_prefix);
-    let local_vector_from = format_ident!("{}vector_from", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
 
     let span = ty.span();
@@ -598,10 +596,6 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
             std::ptr::drop_in_place(this);
         }
-        #[export_name = #link_vector_from]
-        unsafe extern "C" fn #local_vector_from(this: *mut ::cxx::RustVec<#inner>, vector: *mut ::cxx::RealVector<#inner>) {
-            this.as_ref().unwrap().into_vector(vector.as_mut().unwrap());
-        }
         #[doc(hidden)]
         #[export_name = #link_len]
         unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index a28570d..2c8441b 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,4 +1,3 @@
-use crate::vector::RealVector;
 use crate::vector::VectorTarget;
 
 #[repr(C)]
@@ -30,10 +29,4 @@ impl<T: VectorTarget<T>> RustVec<T> {
     pub fn len(&self) -> usize {
         self.repr.len()
     }
-
-    pub fn into_vector(&self, vec: &mut RealVector<T>) {
-        for item in &self.repr {
-            vec.push_back(item);
-        }
-    }
 }

From 4c64afbcbee153b1d9609488b442df0606957ae1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 369/2232] Fix missing absolute path to drop_in_place


It's possible for `std` to mean something different from `::std` if the
user's ffi mod contains a type named `std`.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f29eeeb..e882087 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -594,7 +594,7 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         #[doc(hidden)]
         #[export_name = #link_drop]
         unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
-            std::ptr::drop_in_place(this);
+            ::std::ptr::drop_in_place(this);
         }
         #[doc(hidden)]
         #[export_name = #link_len]

From 2cef5df835fd8443ad9fad9998484d48621a1b47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 370/2232] Remove panicking codepath from vec$len


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e882087..89d15a9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -599,7 +599,7 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         #[doc(hidden)]
         #[export_name = #link_len]
         unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
-            this.as_ref().unwrap().len()
+            (*this).len()
         }
     }
 }

From fac8b25a2590ffc1fca971d71ff037288af422f2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 371/2232] Update RustVec::from_ref to match RustString::from_ref


---

diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 2c8441b..b4eed3b 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -11,7 +11,7 @@ impl<T: VectorTarget<T>> RustVec<T> {
     }
 
     pub fn from_ref(v: &Vec<T>) -> &Self {
-        unsafe { std::mem::transmute::<&Vec<T>, &RustVec<T>>(v) }
+        unsafe { &*(v as *const Vec<T> as *const RustVec<T>) }
     }
 
     pub fn into_vec(self) -> Vec<T> {

From 6c6b7e0cec18c580737b935b3f02cc53751d68b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 372/2232] Remove private Vec ffi wrapper from public API


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 89d15a9..5554d28 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -250,12 +250,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
-            Type::RustVec(_) => quote!(::cxx::RustVec::from(#var)),
+            Type::RustVec(_) => quote!(::cxx::private::RustVec::from(#var)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
                 }
-                Type::RustVec(_) => quote!(::cxx::RustVec::from_ref(#var)),
+                Type::RustVec(_) => quote!(::cxx::private::RustVec::from_ref(#var)),
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -593,12 +593,12 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
     quote_spanned! {span=>
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
+        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#inner>) {
             ::std::ptr::drop_in_place(this);
         }
         #[doc(hidden)]
         #[export_name = #link_len]
-        unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
+        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#inner>) -> usize {
             (*this).len()
         }
     }
@@ -782,12 +782,12 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
         }
-        Type::RustVec(ty) => quote!(::cxx::RustVec<#ty>),
+        Type::RustVec(ty) => quote!(::cxx::private::RustVec<#ty>),
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
             Type::RustVec(ty) => {
                 let inner = expand_extern_type(&ty.inner);
-                quote!(&::cxx::RustVec<#inner>)
+                quote!(&::cxx::private::RustVec<#inner>)
             }
             _ => quote!(#ty),
         },
diff --git a/src/lib.rs b/src/lib.rs
index e23be69..a8ce904 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -378,7 +378,6 @@ mod vector;
 
 pub use crate::cxx_string::CxxString;
 pub use crate::exception::Exception;
-pub use crate::rust_vec::RustVec;
 pub use crate::unique_ptr::UniquePtr;
 pub use crate::vector::RealVector;
 pub use crate::vector::VectorIntoIterator;
@@ -393,6 +392,7 @@ pub mod private {
     pub use crate::rust_sliceu8::RustSliceU8;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
+    pub use crate::rust_vec::RustVec;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorTarget;

From e90be1da4dc67406db3d2aff183a37ec09a09f83 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:08 +0000
Subject: [PATCH 373/2232] Rename std::vector binding to CxxVector


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 5554d28..782da05 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -26,7 +26,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     // "Header" to define newtypes locally so we can implement
     // traits on them.
     expanded.extend(quote! {
-        pub struct Vector<T>(pub ::cxx::RealVector<T>);
+        pub struct Vector<T>(pub ::cxx::CxxVector<T>);
         impl<T: cxx::private::VectorTarget<T>> Vector<T> {
             pub fn size(&self) -> usize {
                 self.0.size()
@@ -46,7 +46,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         }
         impl<'a, T: cxx::private::VectorTarget<T>> IntoIterator for &'a Vector<T> {
             type Item = &'a T;
-            type IntoIter = <&'a ::cxx::RealVector<T> as IntoIterator>::IntoIter;
+            type IntoIter = <&'a ::cxx::CxxVector<T> as IntoIterator>::IntoIter;
 
             fn into_iter(self) -> Self::IntoIter {
                 self.0.into_iter()
@@ -112,7 +112,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::Vector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    // Generate code for Vector<T> if T is not an atom
+                    // Generate code for CxxVector<T> if T is not an atom
                     // Code for atoms is already generated
                     expanded.extend(expand_vector(namespace, &ptr.inner));
                 }
@@ -688,29 +688,29 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
 
     quote! {
         impl ::cxx::private::VectorTarget<#inner> for #inner {
-            fn get_unchecked(v: &::cxx::RealVector<#inner>, pos: usize) -> &#inner {
+            fn get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::RealVector<#inner>, _: usize) -> &#inner;
+                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
                 }
                 unsafe {
                     __get_unchecked(v, pos)
                 }
             }
-            fn vector_length(v: &::cxx::RealVector<#inner>) -> usize {
+            fn vector_length(v: &::cxx::CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
-                        fn __vector_length(_: &::cxx::RealVector<#inner>) -> usize;
+                        fn __vector_length(_: &::cxx::CxxVector<#inner>) -> usize;
                     }
                     __vector_length(v)
                 }
             }
-            fn push_back(v: &::cxx::RealVector<#inner>, item: &#inner) {
+            fn push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
-                        fn __push_back(_: &::cxx::RealVector<#inner>, _: &#inner) -> usize;
+                        fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner) -> usize;
                     }
                     __push_back(v, item);
                 }
@@ -731,29 +731,29 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
 
     quote! {
         impl VectorTarget<#inner> for #inner {
-            fn get_unchecked(v: &RealVector<#inner>, pos: usize) -> &#inner {
+            fn get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &RealVector<#inner>, _: usize) -> &#inner;
+                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
                 }
                 unsafe {
                     __get_unchecked(v, pos)
                 }
             }
-            fn vector_length(v: &RealVector<#inner>) -> usize {
+            fn vector_length(v: &CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
-                        fn __vector_length(_: &RealVector<#inner>) -> usize;
+                        fn __vector_length(_: &CxxVector<#inner>) -> usize;
                     }
                     __vector_length(v)
                 }
             }
-            fn push_back(v: &RealVector<#inner>, item: &#inner) {
+            fn push_back(v: &CxxVector<#inner>, item: &#inner) {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
-                        fn __push_back(_: &RealVector<#inner>, _: &#inner) -> usize;
+                        fn __push_back(_: &CxxVector<#inner>, _: &#inner) -> usize;
                     }
                     __push_back(v, item);
                 }
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
new file mode 100644
index 0000000..feb2e29
--- /dev/null
+++ b/src/cxx_vector.rs
@@ -0,0 +1,92 @@
+pub trait VectorTarget<T> {
+    fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
+    where
+        Self: Sized;
+    fn vector_length(v: &CxxVector<T>) -> usize
+    where
+        Self: Sized;
+    fn push_back(v: &CxxVector<T>, item: &T)
+    where
+        Self: Sized;
+}
+
+/// Binding to C++ `std::vector<T>`.
+///
+/// # Invariants
+///
+/// As an invariant of this API and the static analysis of the cxx::bridge
+/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
+/// requires a move constructor and may hold internal pointers, which is not
+/// compatible with Rust's move behavior. Instead in Rust code we will only ever
+/// look at a Vector through a reference or smart pointer, as in `&Vector`
+/// or `UniquePtr<Vector>`.
+#[repr(C)]
+pub struct CxxVector<T> {
+    _private: [T; 0],
+}
+
+impl<T: VectorTarget<T>> CxxVector<T> {
+    /// Returns the length of the vector in bytes.
+    pub fn size(&self) -> usize {
+        T::vector_length(self)
+    }
+
+    pub fn get_unchecked(&self, pos: usize) -> &T {
+        T::get_unchecked(self, pos)
+    }
+
+    /// Returns true if `self` has a length of zero bytes.
+    pub fn is_empty(&self) -> bool {
+        self.size() == 0
+    }
+
+    pub fn get(&self, pos: usize) -> Option<&T> {
+        if pos < self.size() {
+            Some(self.get_unchecked(pos))
+        } else {
+            None
+        }
+    }
+
+    pub fn push_back(&mut self, item: &T) {
+        T::push_back(self, item);
+    }
+}
+
+unsafe impl<T> Send for CxxVector<T> where T: Send + VectorTarget<T> {}
+
+pub struct VectorIntoIterator<'a, T> {
+    v: &'a CxxVector<T>,
+    index: usize,
+}
+
+impl<'a, T: VectorTarget<T>> IntoIterator for &'a CxxVector<T> {
+    type Item = &'a T;
+    type IntoIter = VectorIntoIterator<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        VectorIntoIterator { v: self, index: 0 }
+    }
+}
+
+impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.index = self.index + 1;
+        self.v.get(self.index - 1)
+    }
+}
+
+cxxbridge_macro::vector_builtin!(u8);
+cxxbridge_macro::vector_builtin!(u16);
+cxxbridge_macro::vector_builtin!(u32);
+cxxbridge_macro::vector_builtin!(u64);
+cxxbridge_macro::vector_builtin!(usize);
+cxxbridge_macro::vector_builtin!(i8);
+cxxbridge_macro::vector_builtin!(i16);
+cxxbridge_macro::vector_builtin!(i32);
+cxxbridge_macro::vector_builtin!(i64);
+cxxbridge_macro::vector_builtin!(isize);
+cxxbridge_macro::vector_builtin!(f32);
+cxxbridge_macro::vector_builtin!(f64);
diff --git a/src/lib.rs b/src/lib.rs
index a8ce904..a25f83d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,6 +360,7 @@ extern crate link_cplusplus;
 mod assert;
 
 mod cxx_string;
+mod cxx_vector;
 mod error;
 mod exception;
 mod function;
@@ -374,18 +375,17 @@ mod rust_vec;
 mod syntax;
 mod unique_ptr;
 mod unwind;
-mod vector;
 
 pub use crate::cxx_string::CxxString;
+pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::unique_ptr::UniquePtr;
-pub use crate::vector::RealVector;
-pub use crate::vector::VectorIntoIterator;
 pub use cxxbridge_macro::bridge;
 
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_vector::VectorTarget;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
@@ -395,7 +395,6 @@ pub mod private {
     pub use crate::rust_vec::RustVec;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
-    pub use crate::vector::VectorTarget;
 }
 
 use crate::error::Result;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index b4eed3b..671d8f7 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,4 +1,4 @@
-use crate::vector::VectorTarget;
+use crate::cxx_vector::VectorTarget;
 
 #[repr(C)]
 pub struct RustVec<T: VectorTarget<T>> {
diff --git a/src/vector.rs b/src/vector.rs
deleted file mode 100644
index 1436165..0000000
--- a/src/vector.rs
+++ /dev/null
@@ -1,92 +0,0 @@
-pub trait VectorTarget<T> {
-    fn get_unchecked(v: &RealVector<T>, pos: usize) -> &T
-    where
-        Self: Sized;
-    fn vector_length(v: &RealVector<T>) -> usize
-    where
-        Self: Sized;
-    fn push_back(v: &RealVector<T>, item: &T)
-    where
-        Self: Sized;
-}
-
-/// Binding to C++ `std::vector`.
-///
-/// # Invariants
-///
-/// As an invariant of this API and the static analysis of the cxx::bridge
-/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
-/// requires a move constructor and may hold internal pointers, which is not
-/// compatible with Rust's move behavior. Instead in Rust code we will only ever
-/// look at a Vector through a reference or smart pointer, as in `&Vector`
-/// or `UniquePtr<Vector>`.
-#[repr(C)]
-pub struct RealVector<T> {
-    _private: [T; 0],
-}
-
-impl<T: VectorTarget<T>> RealVector<T> {
-    /// Returns the length of the vector in bytes.
-    pub fn size(&self) -> usize {
-        T::vector_length(self)
-    }
-
-    pub fn get_unchecked(&self, pos: usize) -> &T {
-        T::get_unchecked(self, pos)
-    }
-
-    /// Returns true if `self` has a length of zero bytes.
-    pub fn is_empty(&self) -> bool {
-        self.size() == 0
-    }
-
-    pub fn get(&self, pos: usize) -> Option<&T> {
-        if pos < self.size() {
-            Some(self.get_unchecked(pos))
-        } else {
-            None
-        }
-    }
-
-    pub fn push_back(&mut self, item: &T) {
-        T::push_back(self, item);
-    }
-}
-
-unsafe impl<T> Send for RealVector<T> where T: Send + VectorTarget<T> {}
-
-pub struct VectorIntoIterator<'a, T> {
-    v: &'a RealVector<T>,
-    index: usize,
-}
-
-impl<'a, T: VectorTarget<T>> IntoIterator for &'a RealVector<T> {
-    type Item = &'a T;
-    type IntoIter = VectorIntoIterator<'a, T>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        VectorIntoIterator { v: self, index: 0 }
-    }
-}
-
-impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.index = self.index + 1;
-        self.v.get(self.index - 1)
-    }
-}
-
-cxxbridge_macro::vector_builtin!(u8);
-cxxbridge_macro::vector_builtin!(u16);
-cxxbridge_macro::vector_builtin!(u32);
-cxxbridge_macro::vector_builtin!(u64);
-cxxbridge_macro::vector_builtin!(usize);
-cxxbridge_macro::vector_builtin!(i8);
-cxxbridge_macro::vector_builtin!(i16);
-cxxbridge_macro::vector_builtin!(i32);
-cxxbridge_macro::vector_builtin!(i64);
-cxxbridge_macro::vector_builtin!(isize);
-cxxbridge_macro::vector_builtin!(f32);
-cxxbridge_macro::vector_builtin!(f64);

From 4f7e6fa1f55866d131cfc8d685ceb267febac237 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 374/2232] Fix align of CxxVector


A vector whose element type is highly aligned need not itself be highly
aligned. If C++ passed in a reference to a vector which is less aligned
than its element type, and Rust thought vectors were more highly aligned
then they really are, then that would have been undefined behavior.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index feb2e29..6cf927b 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,5 @@
+use std::mem;
+
 pub trait VectorTarget<T> {
     fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
     where
@@ -20,7 +22,7 @@ pub trait VectorTarget<T> {
 /// compatible with Rust's move behavior. Instead in Rust code we will only ever
 /// look at a Vector through a reference or smart pointer, as in `&Vector`
 /// or `UniquePtr<Vector>`.
-#[repr(C)]
+#[repr(C, packed)]
 pub struct CxxVector<T> {
     _private: [T; 0],
 }
@@ -90,3 +92,5 @@ cxxbridge_macro::vector_builtin!(i64);
 cxxbridge_macro::vector_builtin!(isize);
 cxxbridge_macro::vector_builtin!(f32);
 cxxbridge_macro::vector_builtin!(f64);
+
+const_assert_eq!(1, mem::align_of::<CxxVector<usize>>());

From 3a8ae095a3922551f3191844437894217f41d3f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 375/2232] Decouple Vec ffi wrapper from C++ vector elements


---

diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 671d8f7..a8a144a 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,11 +1,9 @@
-use crate::cxx_vector::VectorTarget;
-
 #[repr(C)]
-pub struct RustVec<T: VectorTarget<T>> {
+pub struct RustVec<T> {
     repr: Vec<T>,
 }
 
-impl<T: VectorTarget<T>> RustVec<T> {
+impl<T> RustVec<T> {
     pub fn from(v: Vec<T>) -> Self {
         RustVec { repr: v }
     }

From 9e8ec74f2b1996952b9f51369f341ef6f0cd4a94 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 376/2232] Remove unneeded unsafe Send impl for CxxVector


This autotrait impl is already inferred.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 782da05..9eb1e56 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -52,7 +52,6 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                 self.0.into_iter()
             }
         }
-        unsafe impl<T> Send for Vector<T> where T: Send + cxx::private::VectorTarget<T> {}
     });
 
     for api in &apis {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 6cf927b..3e3fd03 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -55,8 +55,6 @@ impl<T: VectorTarget<T>> CxxVector<T> {
     }
 }
 
-unsafe impl<T> Send for CxxVector<T> where T: Send + VectorTarget<T> {}
-
 pub struct VectorIntoIterator<'a, T> {
     v: &'a CxxVector<T>,
     index: usize,

From 5fe936375e5b5ae27ad4f95e0dcdedd23e9e05f3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 377/2232] Update CxxVector invariant documentation


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 3e3fd03..0be971d 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -17,11 +17,9 @@ pub trait VectorTarget<T> {
 /// # Invariants
 ///
 /// As an invariant of this API and the static analysis of the cxx::bridge
-/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
-/// requires a move constructor and may hold internal pointers, which is not
-/// compatible with Rust's move behavior. Instead in Rust code we will only ever
-/// look at a Vector through a reference or smart pointer, as in `&Vector`
-/// or `UniquePtr<Vector>`.
+/// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in
+/// Rust code we will only ever look at a vector behind a reference or smart
+/// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`.
 #[repr(C, packed)]
 pub struct CxxVector<T> {
     _private: [T; 0],

From 67ba0b523191488ab4875065eb90ff010d48c511 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 378/2232] Rename VectorTarget to VectorElement


I assume VectorTarget was copied from the naming of UniquePtrTarget, but
pointers have a "target" (i.e. Deref<Target = T>) while vectors have an
"element".

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9eb1e56..4ecaf07 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -27,7 +27,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     // traits on them.
     expanded.extend(quote! {
         pub struct Vector<T>(pub ::cxx::CxxVector<T>);
-        impl<T: cxx::private::VectorTarget<T>> Vector<T> {
+        impl<T: cxx::private::VectorElement<T>> Vector<T> {
             pub fn size(&self) -> usize {
                 self.0.size()
             }
@@ -44,7 +44,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                 self.0.push_back(item)
             }
         }
-        impl<'a, T: cxx::private::VectorTarget<T>> IntoIterator for &'a Vector<T> {
+        impl<'a, T: cxx::private::VectorElement<T>> IntoIterator for &'a Vector<T> {
             type Item = &'a T;
             type IntoIter = <&'a ::cxx::CxxVector<T> as IntoIterator>::IntoIter;
 
@@ -686,7 +686,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        impl ::cxx::private::VectorTarget<#inner> for #inner {
+        impl ::cxx::private::VectorElement<#inner> for #inner {
             fn get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
@@ -729,7 +729,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        impl VectorTarget<#inner> for #inner {
+        impl VectorElement<#inner> for #inner {
             fn get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 0be971d..d81b4fe 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,6 +1,6 @@
 use std::mem;
 
-pub trait VectorTarget<T> {
+pub trait VectorElement<T> {
     fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
     where
         Self: Sized;
@@ -25,7 +25,7 @@ pub struct CxxVector<T> {
     _private: [T; 0],
 }
 
-impl<T: VectorTarget<T>> CxxVector<T> {
+impl<T: VectorElement<T>> CxxVector<T> {
     /// Returns the length of the vector in bytes.
     pub fn size(&self) -> usize {
         T::vector_length(self)
@@ -58,7 +58,7 @@ pub struct VectorIntoIterator<'a, T> {
     index: usize,
 }
 
-impl<'a, T: VectorTarget<T>> IntoIterator for &'a CxxVector<T> {
+impl<'a, T: VectorElement<T>> IntoIterator for &'a CxxVector<T> {
     type Item = &'a T;
     type IntoIter = VectorIntoIterator<'a, T>;
 
@@ -67,7 +67,7 @@ impl<'a, T: VectorTarget<T>> IntoIterator for &'a CxxVector<T> {
     }
 }
 
-impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
+impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {
diff --git a/src/lib.rs b/src/lib.rs
index a25f83d..1af4d0f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -385,7 +385,7 @@ pub use cxxbridge_macro::bridge;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
-    pub use crate::cxx_vector::VectorTarget;
+    pub use crate::cxx_vector::VectorElement;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};

From b0b83b2477b3675d2b0a951a4c57fb6213b49d78 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 379/2232] Fix missing absolute paths in vector-related Rust codegen


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4ecaf07..d8c47d4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -27,11 +27,11 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     // traits on them.
     expanded.extend(quote! {
         pub struct Vector<T>(pub ::cxx::CxxVector<T>);
-        impl<T: cxx::private::VectorElement<T>> Vector<T> {
+        impl<T: ::cxx::private::VectorElement<T>> Vector<T> {
             pub fn size(&self) -> usize {
                 self.0.size()
             }
-            pub fn get(&self, pos: usize) -> Option<&T> {
+            pub fn get(&self, pos: usize) -> ::std::option::Option<&T> {
                 self.0.get(pos)
             }
             pub fn get_unchecked(&self, pos: usize) -> &T {
@@ -44,9 +44,9 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                 self.0.push_back(item)
             }
         }
-        impl<'a, T: cxx::private::VectorElement<T>> IntoIterator for &'a Vector<T> {
+        impl<'a, T: ::cxx::private::VectorElement<T>> ::std::iter::IntoIterator for &'a Vector<T> {
             type Item = &'a T;
-            type IntoIter = <&'a ::cxx::CxxVector<T> as IntoIterator>::IntoIter;
+            type IntoIter = <&'a ::cxx::CxxVector<T> as ::std::iter::IntoIterator>::IntoIter;
 
             fn into_iter(self) -> Self::IntoIter {
                 self.0.into_iter()

From 69b7f17bc6e0af7c829d48ad183114886c88dbf3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 380/2232] Remove unused Vector wrapper around CxxVector


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d8c47d4..8b0b6a1 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -23,37 +23,6 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
-    // "Header" to define newtypes locally so we can implement
-    // traits on them.
-    expanded.extend(quote! {
-        pub struct Vector<T>(pub ::cxx::CxxVector<T>);
-        impl<T: ::cxx::private::VectorElement<T>> Vector<T> {
-            pub fn size(&self) -> usize {
-                self.0.size()
-            }
-            pub fn get(&self, pos: usize) -> ::std::option::Option<&T> {
-                self.0.get(pos)
-            }
-            pub fn get_unchecked(&self, pos: usize) -> &T {
-                self.0.get_unchecked(pos)
-            }
-            pub fn is_empty(&self) -> bool {
-                self.0.is_empty()
-            }
-            pub fn push_back(&mut self, item: &T) {
-                self.0.push_back(item)
-            }
-        }
-        impl<'a, T: ::cxx::private::VectorElement<T>> ::std::iter::IntoIterator for &'a Vector<T> {
-            type Item = &'a T;
-            type IntoIter = <&'a ::cxx::CxxVector<T> as ::std::iter::IntoIterator>::IntoIter;
-
-            fn into_iter(self) -> Self::IntoIter {
-                self.0.into_iter()
-            }
-        }
-    });
-
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));

From 1b34119261e2b5c5be1ee2216758d903b97f8a7a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:09 +0000
Subject: [PATCH 381/2232] Hide VectorElement trait from docs


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d81b4fe..f7185bb 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,17 +1,5 @@
 use std::mem;
 
-pub trait VectorElement<T> {
-    fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
-    where
-        Self: Sized;
-    fn vector_length(v: &CxxVector<T>) -> usize
-    where
-        Self: Sized;
-    fn push_back(v: &CxxVector<T>, item: &T)
-    where
-        Self: Sized;
-}
-
 /// Binding to C++ `std::vector<T>`.
 ///
 /// # Invariants
@@ -76,6 +64,19 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
     }
 }
 
+#[doc(hidden)]
+pub trait VectorElement<T> {
+    fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
+    where
+        Self: Sized;
+    fn vector_length(v: &CxxVector<T>) -> usize
+    where
+        Self: Sized;
+    fn push_back(v: &CxxVector<T>, item: &T)
+    where
+        Self: Sized;
+}
+
 cxxbridge_macro::vector_builtin!(u8);
 cxxbridge_macro::vector_builtin!(u16);
 cxxbridge_macro::vector_builtin!(u32);

From 0a63b4cf1053383c82392c1af17d0bace08a0b72 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 382/2232] Hide VectorElement methods from autocomplete


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8b0b6a1..477495a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -656,7 +656,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
 
     quote! {
         impl ::cxx::private::VectorElement<#inner> for #inner {
-            fn get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
+            fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
@@ -665,7 +665,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                     __get_unchecked(v, pos)
                 }
             }
-            fn vector_length(v: &::cxx::CxxVector<#inner>) -> usize {
+            fn __vector_length(v: &::cxx::CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
@@ -674,7 +674,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                     __vector_length(v)
                 }
             }
-            fn push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
+            fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
@@ -699,7 +699,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
 
     quote! {
         impl VectorElement<#inner> for #inner {
-            fn get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
+            fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
@@ -708,7 +708,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
                     __get_unchecked(v, pos)
                 }
             }
-            fn vector_length(v: &CxxVector<#inner>) -> usize {
+            fn __vector_length(v: &CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
@@ -717,7 +717,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
                     __vector_length(v)
                 }
             }
-            fn push_back(v: &CxxVector<#inner>, item: &#inner) {
+            fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index f7185bb..7db8a45 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -16,11 +16,11 @@ pub struct CxxVector<T> {
 impl<T: VectorElement<T>> CxxVector<T> {
     /// Returns the length of the vector in bytes.
     pub fn size(&self) -> usize {
-        T::vector_length(self)
+        T::__vector_length(self)
     }
 
     pub fn get_unchecked(&self, pos: usize) -> &T {
-        T::get_unchecked(self, pos)
+        T::__get_unchecked(self, pos)
     }
 
     /// Returns true if `self` has a length of zero bytes.
@@ -37,7 +37,7 @@ impl<T: VectorElement<T>> CxxVector<T> {
     }
 
     pub fn push_back(&mut self, item: &T) {
-        T::push_back(self, item);
+        T::__push_back(self, item);
     }
 }
 
@@ -66,13 +66,13 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
 
 #[doc(hidden)]
 pub trait VectorElement<T> {
-    fn get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
+    fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
     where
         Self: Sized;
-    fn vector_length(v: &CxxVector<T>) -> usize
+    fn __vector_length(v: &CxxVector<T>) -> usize
     where
         Self: Sized;
-    fn push_back(v: &CxxVector<T>, item: &T)
+    fn __push_back(v: &CxxVector<T>, item: &T)
     where
         Self: Sized;
 }

From 5104c8658b08cc6ab696d302055272afb3412dee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 383/2232] Clarify that VectorElement is not meant to be implemented


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 477495a..657bcd2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -655,7 +655,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        impl ::cxx::private::VectorElement<#inner> for #inner {
+        unsafe impl ::cxx::private::VectorElement<#inner> for #inner {
             fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
@@ -698,7 +698,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        impl VectorElement<#inner> for #inner {
+        unsafe impl VectorElement<#inner> for #inner {
             fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 7db8a45..c3f4fe7 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -64,8 +64,10 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
     }
 }
 
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
 #[doc(hidden)]
-pub trait VectorElement<T> {
+pub unsafe trait VectorElement<T> {
     fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
     where
         Self: Sized;

From 33050ece6badd78a68f1ac24efa9c326e99a0144 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 384/2232] Remove unneeded vector element Sized constraints


We only implement VectorElement for sized types anyway.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c3f4fe7..c0d2f6b 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -68,15 +68,9 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement<T> {
-    fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T
-    where
-        Self: Sized;
-    fn __vector_length(v: &CxxVector<T>) -> usize
-    where
-        Self: Sized;
-    fn __push_back(v: &CxxVector<T>, item: &T)
-    where
-        Self: Sized;
+    fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T;
+    fn __vector_length(v: &CxxVector<T>) -> usize;
+    fn __push_back(v: &CxxVector<T>, item: &T);
 }
 
 cxxbridge_macro::vector_builtin!(u8);

From 31ad0be65398b5fbc746a24f9011b040fd5b7d19 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 385/2232] Unsafe CxxVector::get_unchecked


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 657bcd2..1b3aab3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -656,14 +656,12 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
 
     quote! {
         unsafe impl ::cxx::private::VectorElement<#inner> for #inner {
-            fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
                 }
-                unsafe {
-                    __get_unchecked(v, pos)
-                }
+                __get_unchecked(v, pos)
             }
             fn __vector_length(v: &::cxx::CxxVector<#inner>) -> usize {
                 unsafe {
@@ -699,14 +697,12 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
 
     quote! {
         unsafe impl VectorElement<#inner> for #inner {
-            fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
+            unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
                 }
-                unsafe {
-                    __get_unchecked(v, pos)
-                }
+                __get_unchecked(v, pos)
             }
             fn __vector_length(v: &CxxVector<#inner>) -> usize {
                 unsafe {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c0d2f6b..7b985d8 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -19,7 +19,7 @@ impl<T: VectorElement<T>> CxxVector<T> {
         T::__vector_length(self)
     }
 
-    pub fn get_unchecked(&self, pos: usize) -> &T {
+    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
         T::__get_unchecked(self, pos)
     }
 
@@ -30,7 +30,7 @@ impl<T: VectorElement<T>> CxxVector<T> {
 
     pub fn get(&self, pos: usize) -> Option<&T> {
         if pos < self.size() {
-            Some(self.get_unchecked(pos))
+            Some(unsafe { T::__get_unchecked(self, pos) })
         } else {
             None
         }
@@ -68,7 +68,7 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement<T> {
-    fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T;
+    unsafe fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T;
     fn __vector_length(v: &CxxVector<T>) -> usize;
     fn __push_back(v: &CxxVector<T>, item: &T);
 }

From c01d0a0f8470416ff617b5097773345b53e6caa6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 386/2232] Rename CxxVector::size to len to match Rust conventions


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 7b985d8..bf9f5fa 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -15,7 +15,7 @@ pub struct CxxVector<T> {
 
 impl<T: VectorElement<T>> CxxVector<T> {
     /// Returns the length of the vector in bytes.
-    pub fn size(&self) -> usize {
+    pub fn len(&self) -> usize {
         T::__vector_length(self)
     }
 
@@ -25,11 +25,11 @@ impl<T: VectorElement<T>> CxxVector<T> {
 
     /// Returns true if `self` has a length of zero bytes.
     pub fn is_empty(&self) -> bool {
-        self.size() == 0
+        self.len() == 0
     }
 
     pub fn get(&self, pos: usize) -> Option<&T> {
-        if pos < self.size() {
+        if pos < self.len() {
             Some(unsafe { T::__get_unchecked(self, pos) })
         } else {
             None
diff --git a/tests/test.rs b/tests/test.rs
index f394c7a..1d903f0 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -32,7 +32,7 @@ fn test_c_return() {
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
-    assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().size());
+    assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len());
     assert_eq!(
         200_u8,
         ffi::c_return_unique_ptr_vector_u8().into_iter().sum(),
@@ -41,7 +41,7 @@ fn test_c_return() {
         200.5_f64,
         ffi::c_return_unique_ptr_vector_f64().into_iter().sum(),
     );
-    assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().size());
+    assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len());
     assert_eq!(
         2021_usize,
         ffi::c_return_unique_ptr_vector_shared()

From c3ed3a67aa07a9b6473924095276caa71c3416ad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 387/2232] Remove redundant type parameter of VectorElement


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1b3aab3..510fcca 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -655,7 +655,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        unsafe impl ::cxx::private::VectorElement<#inner> for #inner {
+        unsafe impl ::cxx::private::VectorElement for #inner {
             unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
@@ -696,7 +696,7 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        unsafe impl VectorElement<#inner> for #inner {
+        unsafe impl VectorElement for #inner {
             unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index bf9f5fa..5c7c46c 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -13,7 +13,7 @@ pub struct CxxVector<T> {
     _private: [T; 0],
 }
 
-impl<T: VectorElement<T>> CxxVector<T> {
+impl<T: VectorElement> CxxVector<T> {
     /// Returns the length of the vector in bytes.
     pub fn len(&self) -> usize {
         T::__vector_length(self)
@@ -46,7 +46,7 @@ pub struct VectorIntoIterator<'a, T> {
     index: usize,
 }
 
-impl<'a, T: VectorElement<T>> IntoIterator for &'a CxxVector<T> {
+impl<'a, T: VectorElement> IntoIterator for &'a CxxVector<T> {
     type Item = &'a T;
     type IntoIter = VectorIntoIterator<'a, T>;
 
@@ -55,7 +55,7 @@ impl<'a, T: VectorElement<T>> IntoIterator for &'a CxxVector<T> {
     }
 }
 
-impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
+impl<'a, T: VectorElement> Iterator for VectorIntoIterator<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -67,10 +67,10 @@ impl<'a, T: VectorElement<T>> Iterator for VectorIntoIterator<'a, T> {
 // Methods are private; not intended to be implemented outside of cxxbridge
 // codebase.
 #[doc(hidden)]
-pub unsafe trait VectorElement<T> {
-    unsafe fn __get_unchecked(v: &CxxVector<T>, pos: usize) -> &T;
-    fn __vector_length(v: &CxxVector<T>) -> usize;
-    fn __push_back(v: &CxxVector<T>, item: &T);
+pub unsafe trait VectorElement: Sized {
+    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
+    fn __vector_length(v: &CxxVector<Self>) -> usize;
+    fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 
 cxxbridge_macro::vector_builtin!(u8);

From cdc8796d62ac42e879488010f10f6d65acde2e1f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 388/2232] Document CxxVector associated methods


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 5c7c46c..4a5e8e6 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -14,20 +14,27 @@ pub struct CxxVector<T> {
 }
 
 impl<T: VectorElement> CxxVector<T> {
-    /// Returns the length of the vector in bytes.
+    /// Returns the number of elements in the vector.
     pub fn len(&self) -> usize {
         T::__vector_length(self)
     }
 
+    /// Returns a reference to an element without doing bounds checking.
+    ///
+    /// This is generally not recommended, use with caution! Calling this method
+    /// with an out-of-bounds index is undefined behavior even if the resulting
+    /// reference is not used.
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
         T::__get_unchecked(self, pos)
     }
 
-    /// Returns true if `self` has a length of zero bytes.
+    /// Returns true if the vector contains no elements.
     pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
 
+    /// Returns a reference to an element at the given position, or `None` if
+    /// out of bounds.
     pub fn get(&self, pos: usize) -> Option<&T> {
         if pos < self.len() {
             Some(unsafe { T::__get_unchecked(self, pos) })
@@ -36,6 +43,7 @@ impl<T: VectorElement> CxxVector<T> {
         }
     }
 
+    /// Appends an element to the back of the vector.
     pub fn push_back(&mut self, item: &T) {
         T::__push_back(self, item);
     }

From 4944f2f07310cd679812b95a8fc33e7a982b5c46 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:10 +0000
Subject: [PATCH 389/2232] Move get_unchecked after safe get method


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 4a5e8e6..02069e3 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -19,15 +19,6 @@ impl<T: VectorElement> CxxVector<T> {
         T::__vector_length(self)
     }
 
-    /// Returns a reference to an element without doing bounds checking.
-    ///
-    /// This is generally not recommended, use with caution! Calling this method
-    /// with an out-of-bounds index is undefined behavior even if the resulting
-    /// reference is not used.
-    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
-        T::__get_unchecked(self, pos)
-    }
-
     /// Returns true if the vector contains no elements.
     pub fn is_empty(&self) -> bool {
         self.len() == 0
@@ -43,6 +34,15 @@ impl<T: VectorElement> CxxVector<T> {
         }
     }
 
+    /// Returns a reference to an element without doing bounds checking.
+    ///
+    /// This is generally not recommended, use with caution! Calling this method
+    /// with an out-of-bounds index is undefined behavior even if the resulting
+    /// reference is not used.
+    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
+        T::__get_unchecked(self, pos)
+    }
+
     /// Appends an element to the back of the vector.
     pub fn push_back(&mut self, item: &T) {
         T::__push_back(self, item);

From 3d88bdc9875c5ff1df5976505a192fa14ce145a4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 390/2232] Rename VectorIntoIterator to Iter


This matches the name of std::slice::Iter.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 02069e3..862c990 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -49,21 +49,21 @@ impl<T: VectorElement> CxxVector<T> {
     }
 }
 
-pub struct VectorIntoIterator<'a, T> {
+pub struct Iter<'a, T> {
     v: &'a CxxVector<T>,
     index: usize,
 }
 
 impl<'a, T: VectorElement> IntoIterator for &'a CxxVector<T> {
     type Item = &'a T;
-    type IntoIter = VectorIntoIterator<'a, T>;
+    type IntoIter = Iter<'a, T>;
 
     fn into_iter(self) -> Self::IntoIter {
-        VectorIntoIterator { v: self, index: 0 }
+        Iter { v: self, index: 0 }
     }
 }
 
-impl<'a, T: VectorElement> Iterator for VectorIntoIterator<'a, T> {
+impl<'a, T: VectorElement> Iterator for Iter<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {

From 0e08466bbba3e64c38edbff89774973c263d7c5f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 391/2232] Rename to vector_size to match std::vector<>::size


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 510fcca..8eb6fe8 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -663,13 +663,13 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                 }
                 __get_unchecked(v, pos)
             }
-            fn __vector_length(v: &::cxx::CxxVector<#inner>) -> usize {
+            fn __vector_size(v: &::cxx::CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
-                        fn __vector_length(_: &::cxx::CxxVector<#inner>) -> usize;
+                        fn __vector_size(_: &::cxx::CxxVector<#inner>) -> usize;
                     }
-                    __vector_length(v)
+                    __vector_size(v)
                 }
             }
             fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
@@ -704,13 +704,13 @@ pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
                 }
                 __get_unchecked(v, pos)
             }
-            fn __vector_length(v: &CxxVector<#inner>) -> usize {
+            fn __vector_size(v: &CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_length]
-                        fn __vector_length(_: &CxxVector<#inner>) -> usize;
+                        fn __vector_size(_: &CxxVector<#inner>) -> usize;
                     }
-                    __vector_length(v)
+                    __vector_size(v)
                 }
             }
             fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 862c990..f5db334 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -16,7 +16,7 @@ pub struct CxxVector<T> {
 impl<T: VectorElement> CxxVector<T> {
     /// Returns the number of elements in the vector.
     pub fn len(&self) -> usize {
-        T::__vector_length(self)
+        T::__vector_size(self)
     }
 
     /// Returns true if the vector contains no elements.
@@ -77,7 +77,7 @@ impl<'a, T: VectorElement> Iterator for Iter<'a, T> {
 #[doc(hidden)]
 pub unsafe trait VectorElement: Sized {
     unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
-    fn __vector_length(v: &CxxVector<Self>) -> usize;
+    fn __vector_size(v: &CxxVector<Self>) -> usize;
     fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 

From 147fcc501ae158fd0002a850662e92fcc6591af2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 392/2232] Call vector_builtin macro via import


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index f5db334..2aae4a8 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,4 @@
+use cxxbridge_macro::vector_builtin;
 use std::mem;
 
 /// Binding to C++ `std::vector<T>`.
@@ -81,17 +82,17 @@ pub unsafe trait VectorElement: Sized {
     fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 
-cxxbridge_macro::vector_builtin!(u8);
-cxxbridge_macro::vector_builtin!(u16);
-cxxbridge_macro::vector_builtin!(u32);
-cxxbridge_macro::vector_builtin!(u64);
-cxxbridge_macro::vector_builtin!(usize);
-cxxbridge_macro::vector_builtin!(i8);
-cxxbridge_macro::vector_builtin!(i16);
-cxxbridge_macro::vector_builtin!(i32);
-cxxbridge_macro::vector_builtin!(i64);
-cxxbridge_macro::vector_builtin!(isize);
-cxxbridge_macro::vector_builtin!(f32);
-cxxbridge_macro::vector_builtin!(f64);
+vector_builtin!(u8);
+vector_builtin!(u16);
+vector_builtin!(u32);
+vector_builtin!(u64);
+vector_builtin!(usize);
+vector_builtin!(i8);
+vector_builtin!(i16);
+vector_builtin!(i32);
+vector_builtin!(i64);
+vector_builtin!(isize);
+vector_builtin!(f32);
+vector_builtin!(f64);
 
 const_assert_eq!(1, mem::align_of::<CxxVector<usize>>());

From 4b91eaaf7fca9df3d9cb49e114e1361bce9ed2f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 393/2232] More explicit naming for vector element primitive macro


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8eb6fe8..be23fcf 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -685,7 +685,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     }
 }
 
-pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
+pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
     let ty = Type::Ident(ident);
     let inner = &ty;
     let namespace = Namespace { segments: vec![] };
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 87fe405..e6e5f2e 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -46,7 +46,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
 }
 
 #[proc_macro]
-pub fn vector_builtin(input: TokenStream) -> TokenStream {
+pub fn impl_vector_element_for_primitive(input: TokenStream) -> TokenStream {
     let ident = parse_macro_input!(input as Ident);
-    expand::expand_vector_builtin(ident).into()
+    expand::impl_vector_element_for_primitive(ident).into()
 }
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 2aae4a8..3742fa4 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,4 +1,4 @@
-use cxxbridge_macro::vector_builtin;
+use cxxbridge_macro::impl_vector_element_for_primitive;
 use std::mem;
 
 /// Binding to C++ `std::vector<T>`.
@@ -82,17 +82,17 @@ pub unsafe trait VectorElement: Sized {
     fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 
-vector_builtin!(u8);
-vector_builtin!(u16);
-vector_builtin!(u32);
-vector_builtin!(u64);
-vector_builtin!(usize);
-vector_builtin!(i8);
-vector_builtin!(i16);
-vector_builtin!(i32);
-vector_builtin!(i64);
-vector_builtin!(isize);
-vector_builtin!(f32);
-vector_builtin!(f64);
+impl_vector_element_for_primitive!(u8);
+impl_vector_element_for_primitive!(u16);
+impl_vector_element_for_primitive!(u32);
+impl_vector_element_for_primitive!(u64);
+impl_vector_element_for_primitive!(usize);
+impl_vector_element_for_primitive!(i8);
+impl_vector_element_for_primitive!(i16);
+impl_vector_element_for_primitive!(i32);
+impl_vector_element_for_primitive!(i64);
+impl_vector_element_for_primitive!(isize);
+impl_vector_element_for_primitive!(f32);
+impl_vector_element_for_primitive!(f64);
 
 const_assert_eq!(1, mem::align_of::<CxxVector<usize>>());

From a83247c5a3d79a414015ebda9108fb3400919849 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 394/2232] Rename std$vector$T$length to match std::vector<T>::size


---

diff --git a/gen/write.rs b/gen/write.rs
index c1aa2f7..3da42b3 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1131,7 +1131,7 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge02$std$vector${}$length(const ::std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index be23fcf..b2278e0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -650,7 +650,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let inner = ty;
     let mangled = ty.to_mangled(&namespace.segments) + "$";
     let prefix = format!("cxxbridge02$std$vector${}", mangled);
-    let link_length = format!("{}length", prefix);
+    let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let link_push_back = format!("{}push_back", prefix);
 
@@ -666,7 +666,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
             fn __vector_size(v: &::cxx::CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
-                        #[link_name = #link_length]
+                        #[link_name = #link_size]
                         fn __vector_size(_: &::cxx::CxxVector<#inner>) -> usize;
                     }
                     __vector_size(v)
@@ -691,7 +691,7 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
     let namespace = Namespace { segments: vec![] };
     let mangled = ty.to_mangled(&namespace.segments) + "$";
     let prefix = format!("cxxbridge02$std$vector${}", mangled);
-    let link_length = format!("{}length", prefix);
+    let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let link_push_back = format!("{}push_back", prefix);
 
@@ -707,7 +707,7 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
             fn __vector_size(v: &CxxVector<#inner>) -> usize {
                 unsafe {
                     extern "C" {
-                        #[link_name = #link_length]
+                        #[link_name = #link_size]
                         fn __vector_size(_: &CxxVector<#inner>) -> usize;
                     }
                     __vector_size(v)
diff --git a/src/cxx.cc b/src/cxx.cc
index a0e92ac..15f888d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -201,7 +201,7 @@ void cxxbridge02$unique_ptr$std$string$drop(
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   extern "C" {                                                                 \
-  size_t cxxbridge02$std$vector$##RUST_TYPE##$length(                          \
+  size_t cxxbridge02$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \

From 61677aa8135912377e03bd35e69bf4f267692363 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 395/2232] Fix push_back extern decl to match the C++ signature


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b2278e0..8ec1107 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -676,7 +676,7 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
-                        fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner) -> usize;
+                        fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner);
                     }
                     __push_back(v, item);
                 }
@@ -717,7 +717,7 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
                 unsafe {
                     extern "C" {
                         #[link_name = #link_push_back]
-                        fn __push_back(_: &CxxVector<#inner>, _: &#inner) -> usize;
+                        fn __push_back(_: &CxxVector<#inner>, _: &#inner);
                     }
                     __push_back(v, item);
                 }

From dd3f6344e77b3d0bc2ee9c4f6f909472c5b33db2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 396/2232] Fix get_unchecked impl signature to match Rust


---

diff --git a/gen/write.rs b/gen/write.rs
index 3da42b3..2db985c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1147,10 +1147,10 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
 
     writeln!(
         out,
-        "const {} *cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
-    writeln!(out, "  return &s[pos];");
+    writeln!(out, "  return s[pos];");
     writeln!(out, "}}");
     writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index 15f888d..e716aee 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -209,9 +209,9 @@ void cxxbridge02$unique_ptr$std$string$drop(
       std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
     s.push_back(item);                                                         \
   }                                                                            \
-  const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE &cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
-    return &s[pos];                                                            \
+    return s[pos];                                                             \
   }                                                                            \
   static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
                     sizeof(void *),                                            \

From fa2119c886a22c943fd05ef6e9ff07d20b0c0733 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:11 +0000
Subject: [PATCH 397/2232] Make some unsafe blocks smaller in vector generated code


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8ec1107..3aeb831 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -664,22 +664,18 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                 __get_unchecked(v, pos)
             }
             fn __vector_size(v: &::cxx::CxxVector<#inner>) -> usize {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_size]
-                        fn __vector_size(_: &::cxx::CxxVector<#inner>) -> usize;
-                    }
-                    __vector_size(v)
+                extern "C" {
+                    #[link_name = #link_size]
+                    fn __vector_size(_: &::cxx::CxxVector<#inner>) -> usize;
                 }
+                unsafe { __vector_size(v) }
             }
             fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_push_back]
-                        fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner);
-                    }
-                    __push_back(v, item);
+                extern "C" {
+                    #[link_name = #link_push_back]
+                    fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner);
                 }
+                unsafe { __push_back(v, item) }
             }
         }
     }
@@ -705,22 +701,18 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
                 __get_unchecked(v, pos)
             }
             fn __vector_size(v: &CxxVector<#inner>) -> usize {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_size]
-                        fn __vector_size(_: &CxxVector<#inner>) -> usize;
-                    }
-                    __vector_size(v)
+                extern "C" {
+                    #[link_name = #link_size]
+                    fn __vector_size(_: &CxxVector<#inner>) -> usize;
                 }
+                unsafe { __vector_size(v) }
             }
             fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_push_back]
-                        fn __push_back(_: &CxxVector<#inner>, _: &#inner);
-                    }
-                    __push_back(v, item);
+                extern "C" {
+                    #[link_name = #link_push_back]
+                    fn __push_back(_: &CxxVector<#inner>, _: &#inner);
                 }
+                unsafe { __push_back(v, item) }
             }
         }
     }

From cc75ad201ed818769f2039737047988d9d79620d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 398/2232] Reorder vector-element methods to a consistent order


---

diff --git a/gen/write.rs b/gen/write.rs
index 2db985c..6c43928 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1136,21 +1136,19 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
-
     writeln!(
         out,
-        "void cxxbridge02$std$vector${}$push_back(::std::vector<{}> &s, const {} &item) noexcept {{",
-        instance, inner, inner
+        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
     );
-    writeln!(out, "  s.push_back(item);");
+    writeln!(out, "  return s[pos];");
     writeln!(out, "}}");
-
     writeln!(
         out,
-        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
-        inner, instance, inner,
+        "void cxxbridge02$std$vector${}$push_back(::std::vector<{}> &s, const {} &item) noexcept {{",
+        instance, inner, inner
     );
-    writeln!(out, "  return s[pos];");
+    writeln!(out, "  s.push_back(item);");
     writeln!(out, "}}");
     writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3aeb831..6ec40e0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -656,13 +656,6 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
 
     quote! {
         unsafe impl ::cxx::private::VectorElement for #inner {
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
-                extern "C" {
-                    #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
-                }
-                __get_unchecked(v, pos)
-            }
             fn __vector_size(v: &::cxx::CxxVector<#inner>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
@@ -670,6 +663,13 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
                 }
                 unsafe { __vector_size(v) }
             }
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
+                }
+                __get_unchecked(v, pos)
+            }
             fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
                 extern "C" {
                     #[link_name = #link_push_back]
@@ -693,13 +693,6 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
 
     quote! {
         unsafe impl VectorElement for #inner {
-            unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
-                extern "C" {
-                    #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
-                }
-                __get_unchecked(v, pos)
-            }
             fn __vector_size(v: &CxxVector<#inner>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
@@ -707,6 +700,13 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
                 }
                 unsafe { __vector_size(v) }
             }
+            unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
+                }
+                __get_unchecked(v, pos)
+            }
             fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
                 extern "C" {
                     #[link_name = #link_push_back]
diff --git a/src/cxx.cc b/src/cxx.cc
index e716aee..f1cc455 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -205,14 +205,14 @@ void cxxbridge02$unique_ptr$std$string$drop(
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
-      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
-    s.push_back(item);                                                         \
-  }                                                                            \
   const CXX_TYPE &cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return s[pos];                                                             \
   }                                                                            \
+  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
+      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
+    s.push_back(item);                                                         \
+  }                                                                            \
   static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
                     sizeof(void *),                                            \
                 "");                                                           \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 3742fa4..829e12a 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -77,8 +77,8 @@ impl<'a, T: VectorElement> Iterator for Iter<'a, T> {
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement: Sized {
-    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
+    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
     fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 

From 996db1efb1e77b4c17517dd04981d262d4e8e17c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 399/2232] Remove unneeded absolute paths in cxx.cc vector code


---

diff --git a/src/cxx.cc b/src/cxx.cc
index f1cc455..a3ff557 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -213,39 +213,39 @@ void cxxbridge02$unique_ptr$std$string$drop(
       std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
     s.push_back(item);                                                         \
   }                                                                            \
-  static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
+  static_assert(sizeof(std::unique_ptr<std::vector<CXX_TYPE>>) ==              \
                     sizeof(void *),                                            \
                 "");                                                           \
-  static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==           \
+  static_assert(alignof(std::unique_ptr<std::vector<CXX_TYPE>>) ==             \
                     alignof(void *),                                           \
                 "");                                                           \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>();                       \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
+    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(                    \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *value) noexcept {                                 \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(                         \
-        new std::vector<CXX_TYPE>(::std::move(*value)));                       \
+    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(                          \
+        new std::vector<CXX_TYPE>(std::move(*value)));                         \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(raw);                    \
+    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
   const std::vector<CXX_TYPE> *                                                \
       cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
-          const ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {      \
+          const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
   std::vector<CXX_TYPE> *                                                      \
       cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
-          ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {            \
+          std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
   }                                                                            \
   } // extern "C"

From 4e7e7c47cfc8f5f47890d5998bd6d189cc9c7710 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 400/2232] Collect std vector ops into one extern "C" block


---

diff --git a/src/cxx.cc b/src/cxx.cc
index a3ff557..d9be1fb 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -200,7 +200,6 @@ void cxxbridge02$unique_ptr$std$string$drop(
 } // extern "C"
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  extern "C" {                                                                 \
   size_t cxxbridge02$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
@@ -213,12 +212,10 @@ void cxxbridge02$unique_ptr$std$string$drop(
       std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
     s.push_back(item);                                                         \
   }                                                                            \
-  static_assert(sizeof(std::unique_ptr<std::vector<CXX_TYPE>>) ==              \
-                    sizeof(void *),                                            \
-                "");                                                           \
-  static_assert(alignof(std::unique_ptr<std::vector<CXX_TYPE>>) ==             \
-                    alignof(void *),                                           \
-                "");                                                           \
+  static_assert(                                                               \
+      sizeof(std::unique_ptr<std::vector<CXX_TYPE>>) == sizeof(void *), "");   \
+  static_assert(                                                               \
+      alignof(std::unique_ptr<std::vector<CXX_TYPE>>) == alignof(void *), ""); \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
@@ -234,22 +231,22 @@ void cxxbridge02$unique_ptr$std$string$drop(
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
-  const std::vector<CXX_TYPE> *                                                \
-      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
+  const std::vector<CXX_TYPE>                                                  \
+      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
           const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
-  std::vector<CXX_TYPE> *                                                      \
-      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
+  std::vector<CXX_TYPE>                                                        \
+      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                \
           std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
-  }                                                                            \
-  } // extern "C"
+  }
 
+extern "C" {
 STD_VECTOR_OPS(u8, uint8_t);
 STD_VECTOR_OPS(u16, uint16_t);
 STD_VECTOR_OPS(u32, uint32_t);
@@ -262,3 +259,4 @@ STD_VECTOR_OPS(i64, int64_t);
 STD_VECTOR_OPS(isize, rust::isize);
 STD_VECTOR_OPS(f32, float);
 STD_VECTOR_OPS(f64, double);
+} // extern "C"

From 9626d081b59be90aa24316aa4fe8ecf95fdf52c0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 401/2232] Update get_unchecked to void Wreturn-type-c-linkage


Otherwise:

    'cxxbridge02$std$vector$u8$get_unchecked' has C-linkage specified,
    but returns user-defined type 'const uint8_t &' (aka 'const unsigned
    char &') which is incompatible with C [-Wreturn-type-c-linkage]

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6ec40e0..04003a0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -666,9 +666,9 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
             unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> &#inner;
+                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> *const #inner;
                 }
-                __get_unchecked(v, pos)
+                &*__get_unchecked(v, pos)
             }
             fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
                 extern "C" {
@@ -703,9 +703,9 @@ pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
             unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> &#inner;
+                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> *const #inner;
                 }
-                __get_unchecked(v, pos)
+                &*__get_unchecked(v, pos)
             }
             fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
                 extern "C" {
diff --git a/src/cxx.cc b/src/cxx.cc
index d9be1fb..b9e4826 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -204,9 +204,9 @@ void cxxbridge02$unique_ptr$std$string$drop(
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE &cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
-    return s[pos];                                                             \
+    return &s[pos];                                                            \
   }                                                                            \
   void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
       std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \

From e4b6a62d337fc02fd48ea2c796718bc2db2f9103 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 402/2232] Move vector element primitive macro to macro_rules


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 04003a0..1966d7a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -681,43 +681,6 @@ fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     }
 }
 
-pub fn impl_vector_element_for_primitive(ident: Ident) -> TokenStream {
-    let ty = Type::Ident(ident);
-    let inner = &ty;
-    let namespace = Namespace { segments: vec![] };
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
-    let prefix = format!("cxxbridge02$std$vector${}", mangled);
-    let link_size = format!("{}size", prefix);
-    let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let link_push_back = format!("{}push_back", prefix);
-
-    quote! {
-        unsafe impl VectorElement for #inner {
-            fn __vector_size(v: &CxxVector<#inner>) -> usize {
-                extern "C" {
-                    #[link_name = #link_size]
-                    fn __vector_size(_: &CxxVector<#inner>) -> usize;
-                }
-                unsafe { __vector_size(v) }
-            }
-            unsafe fn __get_unchecked(v: &CxxVector<#inner>, pos: usize) -> &#inner {
-                extern "C" {
-                    #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &CxxVector<#inner>, _: usize) -> *const #inner;
-                }
-                &*__get_unchecked(v, pos)
-            }
-            fn __push_back(v: &CxxVector<#inner>, item: &#inner) {
-                extern "C" {
-                    #[link_name = #link_push_back]
-                    fn __push_back(_: &CxxVector<#inner>, _: &#inner);
-                }
-                unsafe { __push_back(v, item) }
-            }
-        }
-    }
-}
-
 fn expand_return_type(ret: &Option<Type>) -> TokenStream {
     match ret {
         Some(ret) => quote!(-> #ret),
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index e6e5f2e..b56f58e 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -14,7 +14,7 @@ mod syntax;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, Ident, ItemMod};
+use syn::{parse_macro_input, ItemMod};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,9 +44,3 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
-
-#[proc_macro]
-pub fn impl_vector_element_for_primitive(input: TokenStream) -> TokenStream {
-    let ident = parse_macro_input!(input as Ident);
-    expand::impl_vector_element_for_primitive(ident).into()
-}
diff --git a/src/concat.rs b/src/concat.rs
new file mode 100644
index 0000000..e67e50d
--- /dev/null
+++ b/src/concat.rs
@@ -0,0 +1,6 @@
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 829e12a..f7fb5ac 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,4 +1,3 @@
-use cxxbridge_macro::impl_vector_element_for_primitive;
 use std::mem;
 
 /// Binding to C++ `std::vector<T>`.
@@ -82,6 +81,40 @@ pub unsafe trait VectorElement: Sized {
     fn __push_back(v: &CxxVector<Self>, item: &Self);
 }
 
+macro_rules! impl_vector_element_for_primitive {
+    ($ty:ident) => {
+        unsafe impl VectorElement for $ty {
+            fn __vector_size(v: &CxxVector<$ty>) -> usize {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$size")]
+                        fn __vector_size(_: &CxxVector<$ty>) -> usize;
+                    }
+                }
+                unsafe { __vector_size(v) }
+            }
+            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$get_unchecked")]
+                        fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
+                    }
+                }
+                &*__get_unchecked(v, pos)
+            }
+            fn __push_back(v: &CxxVector<$ty>, item: &$ty) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$push_back")]
+                        fn __push_back(_: &CxxVector<$ty>, _: &$ty);
+                    }
+                }
+                unsafe { __push_back(v, item) }
+            }
+        }
+    };
+}
+
 impl_vector_element_for_primitive!(u8);
 impl_vector_element_for_primitive!(u16);
 impl_vector_element_for_primitive!(u32);
diff --git a/src/lib.rs b/src/lib.rs
index 1af4d0f..c9f4667 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -358,6 +358,8 @@ extern crate link_cplusplus;
 
 #[macro_use]
 mod assert;
+#[macro_use]
+mod concat;
 
 mod cxx_string;
 mod cxx_vector;

From 4377a9e8379fe45b4404700ecd93e7dd3eb3c0c8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 403/2232] Rename Type::Vector to CxxVector


---

diff --git a/gen/write.rs b/gen/write.rs
index 6c43928..deae886 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -125,7 +125,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
-            Type::Vector(_) => out.include.vector = true,
+            Type::CxxVector(_) => out.include.vector = true,
             Type::SliceRefU8(_) => out.include.cstdint = true,
             _ => {}
         }
@@ -478,7 +478,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Vector(_)) => write!(
+        Some(Type::CxxVector(_)) => write!(
             out,
             " /* Use RVO to convert to r-value and move construct */"
         ),
@@ -792,7 +792,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) => {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
@@ -827,7 +827,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
-        Type::Vector(ty) => {
+        Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
             write!(out, ">");
@@ -879,7 +879,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::Str(_)
-        | Type::Vector(_)
+        | Type::CxxVector(_)
         | Type::RustVec(_)
         | Type::SliceRefU8(_)
         | Type::Fn(_) => write!(out, " "),
@@ -916,7 +916,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                     out.next_section();
                     write_unique_ptr(out, &ptr.inner, types);
                 }
-            } else if let Type::Vector(ptr1) = &ptr.inner {
+            } else if let Type::CxxVector(ptr1) = &ptr.inner {
                 if let Type::Ident(inner) = &ptr1.inner {
                     if allow_vector(inner) {
                         out.next_section();
@@ -924,7 +924,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                     }
                 }
             }
-        } else if let Type::Vector(ptr) = ty {
+        } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_vector(inner) {
                     out.next_section();
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1966d7a..9b17b11 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -64,7 +64,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                 if Atom::from(ident).is_none() {
                     expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
                 }
-            } else if let Type::Vector(_) = &ptr.inner {
+            } else if let Type::CxxVector(_) = &ptr.inner {
                 // Generate code for unique_ptr<vector<T>> if T is not an atom
                 // or if T is a primitive.
                 // Code for primitives is already generated
@@ -77,7 +77,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
                     }
                 }
             }
-        } else if let Type::Vector(ptr) = ty {
+        } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
                     // Generate code for CxxVector<T> if T is not an atom
diff --git a/syntax/check.rs b/syntax/check.rs
index 387f9a6..cbfa91b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -31,7 +31,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ptr) => check_type_vec(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
-            Type::Vector(ptr) => check_type_vector(cx, ptr),
+            Type::CxxVector(ptr) => check_type_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
@@ -114,7 +114,7 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
             None | Some(CxxString) => return,
             _ => {}
         }
-    } else if let Type::Vector(_) = &ptr.inner {
+    } else if let Type::CxxVector(_) = &ptr.inner {
         return;
     }
 
@@ -351,7 +351,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
-        Type::Vector(_) => "vector".to_owned(),
+        Type::CxxVector(_) => "vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8e94f06..c34e3e5 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -27,7 +27,7 @@ impl Hash for Type {
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
-            Type::Vector(t) => t.hash(state),
+            Type::CxxVector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
@@ -47,7 +47,7 @@ impl PartialEq for Type {
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
-            (Type::Vector(lhs), Type::Vector(rhs)) => lhs == rhs,
+            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
             (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
index 56e8b73..2a2fa4c 100644
--- a/syntax/mangled.rs
+++ b/syntax/mangled.rs
@@ -23,7 +23,7 @@ impl ToMangled for Type {
             Type::RustBox(ptr) => format!("rust_box${}", ptr.inner.to_mangled(namespace)),
             Type::RustVec(ptr) => format!("rust_vec${}", ptr.inner.to_mangled(namespace)),
             Type::UniquePtr(ptr) => format!("std$unique_ptr${}", ptr.inner.to_mangled(namespace)),
-            Type::Vector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
+            Type::CxxVector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
             _ => unimplemented!(),
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4e0b908..c992690 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -92,7 +92,7 @@ pub enum Type {
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
-    Vector(Box<Ty1>),
+    CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
     Slice(Box<Slice>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f5c598d..f32894b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -303,7 +303,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                 } else if ident == "Vector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
-                        return Ok(Type::Vector(Box::new(Ty1 {
+                        return Ok(Type::CxxVector(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
                             inner,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 3d67a0a..7423f8e 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -14,7 +14,7 @@ impl ToTokens for Type {
                 }
                 ident.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                 ty.to_tokens(tokens)
             }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
diff --git a/syntax/typename.rs b/syntax/typename.rs
index 7ad1be2..016749a 100644
--- a/syntax/typename.rs
+++ b/syntax/typename.rs
@@ -29,7 +29,7 @@ impl ToTypename for Type {
             Type::UniquePtr(ptr) => {
                 format!("::std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
             }
-            Type::Vector(ptr) => format!("::std::vector<{}>", ptr.inner.to_typename(namespace)),
+            Type::CxxVector(ptr) => format!("::std::vector<{}>", ptr.inner.to_typename(namespace)),
             _ => unimplemented!(),
         }
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index 7bce154..2ef1e1e 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -24,9 +24,10 @@ impl<'a> Types<'a> {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
-                Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
-                    visit(all, &ty.inner)
-                }
+                Type::RustBox(ty)
+                | Type::UniquePtr(ty)
+                | Type::CxxVector(ty)
+                | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {

From 9c6bf2d8ef405d42257de71f2928527c81424d3e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 404/2232] Remove assumption of Vec field order


---

diff --git a/gen/write.rs b/gen/write.rs
index deae886..faf3311 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -147,6 +147,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_box = true;
             }
             Type::RustVec(_) => {
+                out.include.array = true;
                 needs_rust_vec = true;
             }
             Type::Str(_) => {
diff --git a/include/cxx.h b/include/cxx.h
index c62faad..1df6c9b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -97,10 +97,8 @@ private:
   Vec &operator=(Vec other) noexcept;
   void drop() noexcept;
 
-  // Repr
-  const T *ptr;
-  size_t len;
-  size_t capacity;
+  // Size and alignment statically verified by rust_vec.rs.
+  std::array<uintptr_t, 3> repr;
 };
 #endif // CXXBRIDGE02_RUST_VEC
 
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index a8a144a..1c0c64f 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,3 +1,5 @@
+use std::mem;
+
 #[repr(C)]
 pub struct RustVec<T> {
     repr: Vec<T>,
@@ -28,3 +30,6 @@ impl<T> RustVec<T> {
         self.repr.len()
     }
 }
+
+const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<i32>>());
+const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<i32>>());

From 347c3d01f4d6f8e23a75703be85be3998d7be1e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:12 +0000
Subject: [PATCH 405/2232] Add Vec and std::vector to builtin types list


---

diff --git a/README.md b/README.md
index a8f4093..f967762 100644
--- a/README.md
+++ b/README.md
@@ -303,6 +303,8 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
@@ -317,11 +319,9 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
diff --git a/src/lib.rs b/src/lib.rs
index c9f4667..e4ef8f2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -311,6 +311,8 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
@@ -325,11 +327,9 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th></tr>
-//! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>

From 61a9fdf313f7880669b6812cc0861bed3e95d970 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 406/2232] Be explit about binding only default vector allocator


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index f7fb5ac..8a73c7e 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,6 +1,6 @@
 use std::mem;
 
-/// Binding to C++ `std::vector<T>`.
+/// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
 /// # Invariants
 ///

From dd8391916fa9dc0ab527a0a35aa3f0f906d834b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 407/2232] Add C++ documentation links to CxxVector


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 8a73c7e..c30dd02 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -15,11 +15,19 @@ pub struct CxxVector<T> {
 
 impl<T: VectorElement> CxxVector<T> {
     /// Returns the number of elements in the vector.
+    ///
+    /// Matches the behavior of C++ [std::vector\<T\>::size][size].
+    ///
+    /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
     pub fn len(&self) -> usize {
         T::__vector_size(self)
     }
 
     /// Returns true if the vector contains no elements.
+    ///
+    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
+    ///
+    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
     pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
@@ -39,6 +47,11 @@ impl<T: VectorElement> CxxVector<T> {
     /// This is generally not recommended, use with caution! Calling this method
     /// with an out-of-bounds index is undefined behavior even if the resulting
     /// reference is not used.
+    ///
+    /// Matches the behavior of C++
+    /// [std::vector\<T\>::operator\[\]][operator_at].
+    ///
+    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
         T::__get_unchecked(self, pos)
     }

From 7f2dc3bab00a0cd2c5743bb731bfe89f7d49fa51 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 408/2232] Reorder rust::Vec below Box


---

diff --git a/include/cxx.h b/include/cxx.h
index 1df6c9b..a96e6fa 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -84,24 +84,6 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_STR
 
-#ifndef CXXBRIDGE02_RUST_VEC
-#define CXXBRIDGE02_RUST_VEC
-template <typename T>
-class Vec final {
-public:
-  size_t size() const noexcept;
-
-private:
-  Vec() noexcept;
-  Vec(const Vec &other) noexcept;
-  Vec &operator=(Vec other) noexcept;
-  void drop() noexcept;
-
-  // Size and alignment statically verified by rust_vec.rs.
-  std::array<uintptr_t, 3> repr;
-};
-#endif // CXXBRIDGE02_RUST_VEC
-
 #ifndef CXXBRIDGE02_RUST_SLICE
 #define CXXBRIDGE02_RUST_SLICE
 template <typename T>
@@ -218,6 +200,24 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+#ifndef CXXBRIDGE02_RUST_VEC
+#define CXXBRIDGE02_RUST_VEC
+template <typename T>
+class Vec final {
+public:
+  size_t size() const noexcept;
+
+private:
+  Vec() noexcept;
+  Vec(const Vec &other) noexcept;
+  Vec &operator=(Vec other) noexcept;
+  void drop() noexcept;
+
+  // Size and alignment statically verified by rust_vec.rs.
+  std::array<uintptr_t, 3> repr;
+};
+#endif // CXXBRIDGE02_RUST_VEC
+
 #ifndef CXXBRIDGE02_RUST_FN
 #define CXXBRIDGE02_RUST_FN
 template <typename Signature, bool Throws = false>

From 465305bdb4d05291460d42574c85e0f2c42042aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 409/2232] Add rust::Vec<T>::empty


---

diff --git a/include/cxx.h b/include/cxx.h
index a96e6fa..250eba2 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -206,6 +206,7 @@ template <typename T>
 class Vec final {
 public:
   size_t size() const noexcept;
+  bool empty() const noexcept { return size() == 0; }
 
 private:
   Vec() noexcept;

From e1dcdf731718e1012eb45d30322b2b0e55114233 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 410/2232] Parse vector's type as CxxVector


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index f32894b..d14806d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,7 +300,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
-                } else if ident == "Vector" && generic.args.len() == 1 {
+                } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index da0040a..0d904fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -27,9 +27,9 @@ pub mod ffi {
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
-        fn c_return_unique_ptr_vector_u8() -> UniquePtr<Vector<u8>>;
-        fn c_return_unique_ptr_vector_f64() -> UniquePtr<Vector<f64>>;
-        fn c_return_unique_ptr_vector_shared() -> UniquePtr<Vector<Shared>>;
+        fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
+        fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
+        fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -41,9 +41,9 @@ pub mod ffi {
         fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
-        fn c_take_unique_ptr_vector_u8(s: UniquePtr<Vector<u8>>);
-        fn c_take_unique_ptr_vector_f64(s: UniquePtr<Vector<f64>>);
-        fn c_take_unique_ptr_vector_shared(s: UniquePtr<Vector<Shared>>);
+        fn c_take_unique_ptr_vector_u8(s: UniquePtr<CxxVector<u8>>);
+        fn c_take_unique_ptr_vector_f64(s: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_shared(s: UniquePtr<CxxVector<Shared>>);
         fn c_take_vec_u8(v: &Vec<u8>);
         fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);

From 3a4299d0db6e1ec6ac9b68a1489ff36ecf314c93 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 411/2232] Emit prefixed path when using CxxVector type


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7423f8e..2962a2b 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -35,8 +35,7 @@ impl ToTokens for Var {
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        // Do not add cxx namespace to Vector since we're defining it in the user crate
-        if self.name == "UniquePtr" || self.name == "RustVec" {
+        if let "UniquePtr" | "RustVec" | "CxxVector" = self.name.to_string().as_str() {
             let span = self.name.span();
             tokens.extend(quote_spanned!(span=> ::cxx::));
         }

From 4074ad22d2a3c5a3e107416a51dfa90c9393ce9f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 412/2232] Prefer where-clause over trait bounds in CxxVector


Where-clauses show up less distractingly in rustdocs.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c30dd02..b47ec41 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -13,7 +13,10 @@ pub struct CxxVector<T> {
     _private: [T; 0],
 }
 
-impl<T: VectorElement> CxxVector<T> {
+impl<T> CxxVector<T>
+where
+    T: VectorElement,
+{
     /// Returns the number of elements in the vector.
     ///
     /// Matches the behavior of C++ [std::vector\<T\>::size][size].
@@ -67,7 +70,10 @@ pub struct Iter<'a, T> {
     index: usize,
 }
 
-impl<'a, T: VectorElement> IntoIterator for &'a CxxVector<T> {
+impl<'a, T> IntoIterator for &'a CxxVector<T>
+where
+    T: VectorElement,
+{
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
 
@@ -76,7 +82,10 @@ impl<'a, T: VectorElement> IntoIterator for &'a CxxVector<T> {
     }
 }
 
-impl<'a, T: VectorElement> Iterator for Iter<'a, T> {
+impl<'a, T> Iterator for Iter<'a, T>
+where
+    T: VectorElement,
+{
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {

From 4ef2743b295be5132916239555fd97525e29f216 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:13 +0000
Subject: [PATCH 413/2232] Keep type of namespace-iterator in helpers


---

diff --git a/gen/write.rs b/gen/write.rs
index faf3311..153b5b3 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -978,9 +978,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+    let inner = ty.to_typename(&out.namespace);
+    let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
@@ -1018,9 +1017,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+    let inner = ty.to_typename(&out.namespace);
+    let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
@@ -1039,9 +1037,8 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
 
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.utility = true;
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+    let inner = ty.to_typename(&out.namespace);
+    let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9b17b11..d1aa638 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -548,7 +548,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 
 fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
     let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let mangled = ty.to_mangled(namespace) + "$";
     let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -573,9 +573,9 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
 }
 
 fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
-    let name = ty.to_typename(&namespace.segments);
+    let name = ty.to_typename(namespace);
     let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let mangled = ty.to_mangled(namespace) + "$";
     let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
@@ -648,7 +648,7 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
 
 fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
+    let mangled = ty.to_mangled(namespace) + "$";
     let prefix = format!("cxxbridge02$std$vector${}", mangled);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
index 2a2fa4c..a89060d 100644
--- a/syntax/mangled.rs
+++ b/syntax/mangled.rs
@@ -1,11 +1,12 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{Atom, Type};
 
 pub trait ToMangled {
-    fn to_mangled(&self, namespace: &Vec<String>) -> String;
+    fn to_mangled(&self, namespace: &Namespace) -> String;
 }
 
 impl ToMangled for Type {
-    fn to_mangled(&self, namespace: &Vec<String>) -> String {
+    fn to_mangled(&self, namespace: &Namespace) -> String {
         match self {
             Type::Ident(ident) => {
                 let mut instance = String::new();
diff --git a/syntax/typename.rs b/syntax/typename.rs
index 016749a..b4261f9 100644
--- a/syntax/typename.rs
+++ b/syntax/typename.rs
@@ -1,11 +1,12 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{Atom, Type};
 
 pub trait ToTypename {
-    fn to_typename(&self, namespace: &Vec<String>) -> String;
+    fn to_typename(&self, namespace: &Namespace) -> String;
 }
 
 impl ToTypename for Type {
-    fn to_typename(&self, namespace: &Vec<String>) -> String {
+    fn to_typename(&self, namespace: &Namespace) -> String {
         match self {
             Type::Ident(ident) => {
                 let mut inner = String::new();

From 42a7742bcb9c0f1f9a36d4e4e43b1c91df5970d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 414/2232] Revert visibility of Namespace segments from PR 67


---

diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index a4e972b..d26bb9e 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -11,7 +11,7 @@ mod kw {
 
 #[derive(Clone)]
 pub struct Namespace {
-    pub segments: Vec<String>,
+    segments: Vec<String>,
 }
 
 impl Namespace {

From 4c4b550aede3ef0a38167b03061efbee796a0ca6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 415/2232] Eliminate unnecessary ToTypename trait


---

diff --git a/gen/write.rs b/gen/write.rs
index 153b5b3..42352d0 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -4,7 +4,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::ToTypename;
+use crate::syntax::typename::to_typename;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -978,7 +978,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
-    let inner = ty.to_typename(&out.namespace);
+    let inner = to_typename(&out.namespace, ty);
     let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
@@ -1017,7 +1017,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
-    let inner = ty.to_typename(&out.namespace);
+    let inner = to_typename(&out.namespace, ty);
     let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "template <>");
@@ -1037,7 +1037,7 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
 
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.utility = true;
-    let inner = ty.to_typename(&out.namespace);
+    let inner = to_typename(&out.namespace, ty);
     let instance = ty.to_mangled(&out.namespace);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d1aa638..720680d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::ToTypename;
+use crate::syntax::typename::to_typename;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
@@ -573,7 +573,7 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
 }
 
 fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
-    let name = ty.to_typename(namespace);
+    let name = to_typename(namespace, ty);
     let inner = ty;
     let mangled = ty.to_mangled(namespace) + "$";
     let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
diff --git a/syntax/typename.rs b/syntax/typename.rs
index b4261f9..9732d32 100644
--- a/syntax/typename.rs
+++ b/syntax/typename.rs
@@ -1,37 +1,31 @@
 use crate::syntax::namespace::Namespace;
 use crate::syntax::{Atom, Type};
 
-pub trait ToTypename {
-    fn to_typename(&self, namespace: &Namespace) -> String;
-}
-
-impl ToTypename for Type {
-    fn to_typename(&self, namespace: &Namespace) -> String {
-        match self {
-            Type::Ident(ident) => {
-                let mut inner = String::new();
-                // Do not apply namespace to built-in type
-                let is_user_type = Atom::from(ident).is_none();
-                if is_user_type {
-                    for name in namespace {
-                        inner += name;
-                        inner += "::";
-                    }
+pub fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut inner = String::new();
+            // Do not apply namespace to built-in type
+            let is_user_type = Atom::from(ident).is_none();
+            if is_user_type {
+                for name in namespace {
+                    inner += name;
+                    inner += "::";
                 }
-                if let Some(ti) = Atom::from(ident) {
-                    inner += ti.to_cxx();
-                } else {
-                    inner += &ident.to_string();
-                };
-                inner
             }
-            Type::RustBox(ptr) => format!("rust_box<{}>", ptr.inner.to_typename(namespace)),
-            Type::RustVec(ptr) => format!("rust_vec<{}>", ptr.inner.to_typename(namespace)),
-            Type::UniquePtr(ptr) => {
-                format!("::std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
-            }
-            Type::CxxVector(ptr) => format!("::std::vector<{}>", ptr.inner.to_typename(namespace)),
-            _ => unimplemented!(),
+            if let Some(ti) = Atom::from(ident) {
+                inner += ti.to_cxx();
+            } else {
+                inner += &ident.to_string();
+            };
+            inner
+        }
+        Type::RustBox(ptr) => format!("rust_box<{}>", to_typename(namespace, &ptr.inner)),
+        Type::RustVec(ptr) => format!("rust_vec<{}>", to_typename(namespace, &ptr.inner)),
+        Type::UniquePtr(ptr) => {
+            format!("::std::unique_ptr<{}>", to_typename(namespace, &ptr.inner))
         }
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        _ => unimplemented!(),
     }
 }

From f12e983d8c6c2147f8cccf20d0f34b588472c123 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 416/2232] Eliminate unnecessary ToMangled trait


---

diff --git a/gen/write.rs b/gen/write.rs
index 42352d0..150eb76 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,7 +1,7 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::ToMangled;
+use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::typename::to_typename;
@@ -979,7 +979,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
 
 fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
     let inner = to_typename(&out.namespace, ty);
-    let instance = ty.to_mangled(&out.namespace);
+    let instance = to_mangled(&out.namespace, ty);
 
     writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
@@ -1018,7 +1018,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
 fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     let inner = to_typename(&out.namespace, ty);
-    let instance = ty.to_mangled(&out.namespace);
+    let instance = to_mangled(&out.namespace, ty);
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
@@ -1038,7 +1038,7 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.utility = true;
     let inner = to_typename(&out.namespace, ty);
-    let instance = ty.to_mangled(&out.namespace);
+    let instance = to_mangled(&out.namespace, ty);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 720680d..8133e6d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::ToMangled;
+use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::typename::to_typename;
@@ -548,7 +548,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 
 fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
     let inner = ty;
-    let mangled = ty.to_mangled(namespace) + "$";
+    let mangled = to_mangled(namespace, ty) + "$";
     let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -575,7 +575,7 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
 fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
     let name = to_typename(namespace, ty);
     let inner = ty;
-    let mangled = ty.to_mangled(namespace) + "$";
+    let mangled = to_mangled(namespace, ty) + "$";
     let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
@@ -648,7 +648,7 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
 
 fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
     let inner = ty;
-    let mangled = ty.to_mangled(namespace) + "$";
+    let mangled = to_mangled(namespace, ty) + "$";
     let prefix = format!("cxxbridge02$std$vector${}", mangled);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
index a89060d..f52aa43 100644
--- a/syntax/mangled.rs
+++ b/syntax/mangled.rs
@@ -1,31 +1,25 @@
 use crate::syntax::namespace::Namespace;
 use crate::syntax::{Atom, Type};
 
-pub trait ToMangled {
-    fn to_mangled(&self, namespace: &Namespace) -> String;
-}
-
-impl ToMangled for Type {
-    fn to_mangled(&self, namespace: &Namespace) -> String {
-        match self {
-            Type::Ident(ident) => {
-                let mut instance = String::new();
-                // Do not apply namespace to built-in type
-                let is_user_type = Atom::from(ident).is_none();
-                if is_user_type {
-                    for name in namespace {
-                        instance += name;
-                        instance += "$";
-                    }
+pub fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut instance = String::new();
+            // Do not apply namespace to built-in type
+            let is_user_type = Atom::from(ident).is_none();
+            if is_user_type {
+                for name in namespace {
+                    instance += name;
+                    instance += "$";
                 }
-                instance += &ident.to_string();
-                instance
             }
-            Type::RustBox(ptr) => format!("rust_box${}", ptr.inner.to_mangled(namespace)),
-            Type::RustVec(ptr) => format!("rust_vec${}", ptr.inner.to_mangled(namespace)),
-            Type::UniquePtr(ptr) => format!("std$unique_ptr${}", ptr.inner.to_mangled(namespace)),
-            Type::CxxVector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
-            _ => unimplemented!(),
+            instance += &ident.to_string();
+            instance
         }
+        Type::RustBox(ptr) => format!("rust_box${}", to_mangled(namespace, &ptr.inner)),
+        Type::RustVec(ptr) => format!("rust_vec${}", to_mangled(namespace, &ptr.inner)),
+        Type::UniquePtr(ptr) => format!("std$unique_ptr${}", to_mangled(namespace, &ptr.inner)),
+        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        _ => unimplemented!(),
     }
 }

From 1763110fdab55a7bcdefd49a474ca8c22a26762b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 417/2232] Clean up VectorElement rust codegen


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8133e6d..96be928 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -80,9 +80,10 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    // Generate code for CxxVector<T> if T is not an atom
-                    // Code for atoms is already generated
-                    expanded.extend(expand_vector(namespace, &ptr.inner));
+                    // Generate impl for CxxVector<T> if T is a struct or opaque
+                    // C++ type. Impl for primitives is already provided by cxx
+                    // crate.
+                    expanded.extend(expand_cxx_vector(namespace, ident));
                 }
             }
         }
@@ -646,34 +647,32 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
     }
 }
 
-fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
-    let inner = ty;
-    let mangled = to_mangled(namespace, ty) + "$";
-    let prefix = format!("cxxbridge02$std$vector${}", mangled);
+fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
+    let prefix = format!("cxxbridge02$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let link_push_back = format!("{}push_back", prefix);
 
     quote! {
-        unsafe impl ::cxx::private::VectorElement for #inner {
-            fn __vector_size(v: &::cxx::CxxVector<#inner>) -> usize {
+        unsafe impl ::cxx::private::VectorElement for #elem {
+            fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
-                    fn __vector_size(_: &::cxx::CxxVector<#inner>) -> usize;
+                    fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<#inner>, pos: usize) -> &#inner {
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> &Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::CxxVector<#inner>, _: usize) -> *const #inner;
+                    fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
                 }
                 &*__get_unchecked(v, pos)
             }
-            fn __push_back(v: &::cxx::CxxVector<#inner>, item: &#inner) {
+            fn __push_back(v: &::cxx::CxxVector<Self>, item: &Self) {
                 extern "C" {
                     #[link_name = #link_push_back]
-                    fn __push_back(_: &::cxx::CxxVector<#inner>, _: &#inner);
+                    fn __push_back(_: &::cxx::CxxVector<#elem>, _: &#elem);
                 }
                 unsafe { __push_back(v, item) }
             }

From 3b40b6f8f03478e1fdf4448a813ab50dbd31e4a7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 418/2232] Move unique_ptr<vector<>> implementation into cxx crate


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 96be928..81cf025 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -2,7 +2,6 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::to_typename;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
@@ -62,19 +61,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
-                }
-            } else if let Type::CxxVector(_) = &ptr.inner {
-                // Generate code for unique_ptr<vector<T>> if T is not an atom
-                // or if T is a primitive.
-                // Code for primitives is already generated
-                match Atom::from(ident) {
-                    None => expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types)),
-                    Some(atom) => {
-                        if atom.is_valid_vector_target() {
-                            expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
-                        }
-                    }
+                    expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
@@ -573,11 +560,9 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
-    let name = to_typename(namespace, ty);
-    let inner = ty;
-    let mangled = to_mangled(namespace, ty) + "$";
-    let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
+fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
+    let name = ident.to_string();
+    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -585,8 +570,8 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = match ty {
-        Type::Ident(ident) if types.structs.contains_key(ident) => Some(quote! {
+    let new_method = if types.structs.contains_key(ident) {
+        Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
@@ -596,13 +581,14 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
                 unsafe { __new(&mut repr, &mut value) }
                 repr
             }
-        }),
-        _ => None,
+        })
+    } else {
+        None
     };
 
     quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #inner {
-            const __NAME: &'static str = #name;
+        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -616,7 +602,7 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
-                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #inner);
+                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #ident);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __raw(&mut repr, raw);
@@ -625,14 +611,14 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #inner;
+                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #ident;
                 }
                 __get(&repr)
             }
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
-                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #inner;
+                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #ident;
                 }
                 __release(&mut repr)
             }
@@ -648,13 +634,21 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
 }
 
 fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
+    let name = elem.to_string();
     let prefix = format!("cxxbridge02$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let link_push_back = format!("{}push_back", prefix);
+    let unique_ptr_prefix = format!("cxxbridge02$unique_ptr$std$vector${}{}$", namespace, elem);
+    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);
+    let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
+    let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
     quote! {
         unsafe impl ::cxx::private::VectorElement for #elem {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
@@ -676,6 +670,45 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
                 }
                 unsafe { __push_back(v, item) }
             }
+            fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_null]
+                    fn __unique_ptr_null(this: *mut *mut ::std::ffi::c_void);
+                }
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                unsafe { __unique_ptr_null(&mut repr) }
+                repr
+            }
+            unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_raw]
+                    fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
+                }
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                __unique_ptr_raw(&mut repr, raw);
+                repr
+            }
+            unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_get]
+                    fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
+                }
+                __unique_ptr_get(&repr)
+            }
+            unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_release]
+                    fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
+                }
+                __unique_ptr_release(&mut repr)
+            }
+            unsafe fn __unique_ptr_drop(mut repr: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_drop]
+                    fn __unique_ptr_drop(this: *mut *mut ::std::ffi::c_void);
+                }
+                __unique_ptr_drop(&mut repr);
+            }
         }
     }
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index b9e4826..aacea9c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -212,20 +212,10 @@ void cxxbridge02$unique_ptr$std$string$drop(
       std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
     s.push_back(item);                                                         \
   }                                                                            \
-  static_assert(                                                               \
-      sizeof(std::unique_ptr<std::vector<CXX_TYPE>>) == sizeof(void *), "");   \
-  static_assert(                                                               \
-      alignof(std::unique_ptr<std::vector<CXX_TYPE>>) == alignof(void *), ""); \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(                    \
-      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
-      std::vector<CXX_TYPE> *value) noexcept {                                 \
-    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(                          \
-        new std::vector<CXX_TYPE>(std::move(*value)));                         \
-  }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index b47ec41..d9e8892 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,4 +1,8 @@
+use std::ffi::c_void;
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
 use std::mem;
+use std::ptr;
 
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
@@ -94,18 +98,46 @@ where
     }
 }
 
+pub struct TypeName<T> {
+    element: PhantomData<T>,
+}
+
+impl<T> TypeName<T> {
+    pub const fn new() -> Self {
+        TypeName {
+            element: PhantomData,
+        }
+    }
+}
+
+impl<T> Display for TypeName<T>
+where
+    T: VectorElement,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "CxxVector<{}>", T::__NAME)
+    }
+}
+
 // Methods are private; not intended to be implemented outside of cxxbridge
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement: Sized {
+    const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
     unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
     fn __push_back(v: &CxxVector<Self>, item: &Self);
+    fn __unique_ptr_null() -> *mut c_void;
+    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
+    unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
+    unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
+    unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
 macro_rules! impl_vector_element_for_primitive {
     ($ty:ident) => {
         unsafe impl VectorElement for $ty {
+            const __NAME: &'static dyn Display = &stringify!($ty);
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
@@ -133,6 +165,55 @@ macro_rules! impl_vector_element_for_primitive {
                 }
                 unsafe { __push_back(v, item) }
             }
+            fn __unique_ptr_null() -> *mut c_void {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        fn __unique_ptr_null(this: *mut *mut c_void);
+                    }
+                }
+                let mut repr = ptr::null_mut::<c_void>();
+                unsafe { __unique_ptr_null(&mut repr) }
+                repr
+            }
+            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
+                    }
+                }
+                let mut repr = ptr::null_mut::<c_void>();
+                __unique_ptr_raw(&mut repr, raw);
+                repr
+            }
+            unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
+                    }
+                }
+                __unique_ptr_get(&repr)
+            }
+            unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
+                    }
+                }
+                __unique_ptr_release(&mut repr)
+            }
+            unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        fn __unique_ptr_drop(this: *mut *mut c_void);
+                    }
+                }
+                __unique_ptr_drop(&mut repr);
+            }
         }
     };
 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index b50e870..98b4b7d 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,4 +1,5 @@
 use crate::cxx_string::CxxString;
+use crate::cxx_vector::{self, CxxVector, VectorElement};
 use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
@@ -149,7 +150,7 @@ where
 // codebase.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static str;
+    const __NAME: &'static dyn Display;
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
@@ -186,7 +187,7 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
-    const __NAME: &'static str = "CxxString";
+    const __NAME: &'static dyn Display = &"CxxString";
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe { unique_ptr_std_string_null(&mut repr) }
@@ -207,3 +208,25 @@ unsafe impl UniquePtrTarget for CxxString {
         unique_ptr_std_string_drop(&mut repr);
     }
 }
+
+unsafe impl<T> UniquePtrTarget for CxxVector<T>
+where
+    T: VectorElement + 'static,
+{
+    const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
+    fn __null() -> *mut c_void {
+        T::__unique_ptr_null()
+    }
+    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
+        T::__unique_ptr_raw(raw)
+    }
+    unsafe fn __get(repr: *mut c_void) -> *const Self {
+        T::__unique_ptr_get(repr)
+    }
+    unsafe fn __release(repr: *mut c_void) -> *mut Self {
+        T::__unique_ptr_release(repr)
+    }
+    unsafe fn __drop(repr: *mut c_void) {
+        T::__unique_ptr_drop(repr);
+    }
+}

From 2eca4a0ce9ccff8ff14a542c5770bf7cdc406418 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 419/2232] Move C++-specific to_typename to C++ code generator


---

diff --git a/gen/write.rs b/gen/write.rs
index 150eb76..f8bd1d8 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -4,7 +4,6 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::to_typename;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -889,6 +888,35 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut inner = String::new();
+            // Do not apply namespace to built-in type
+            let is_user_type = Atom::from(ident).is_none();
+            if is_user_type {
+                for name in namespace {
+                    inner += name;
+                    inner += "::";
+                }
+            }
+            if let Some(ti) = Atom::from(ident) {
+                inner += ti.to_cxx();
+            } else {
+                inner += &ident.to_string();
+            };
+            inner
+        }
+        Type::RustBox(ptr) => format!("rust_box<{}>", to_typename(namespace, &ptr.inner)),
+        Type::RustVec(ptr) => format!("rust_vec<{}>", to_typename(namespace, &ptr.inner)),
+        Type::UniquePtr(ptr) => {
+            format!("::std::unique_ptr<{}>", to_typename(namespace, &ptr.inner))
+        }
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        _ => unimplemented!(),
+    }
+}
+
 fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     fn allow_unique_ptr(ident: &Ident) -> bool {
         Atom::from(ident).is_none()
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c992690..d5b90f0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -14,7 +14,6 @@ mod parse;
 pub mod set;
 pub mod symbol;
 mod tokens;
-pub mod typename;
 pub mod types;
 
 use self::parse::kw;
diff --git a/syntax/typename.rs b/syntax/typename.rs
deleted file mode 100644
index 9732d32..0000000
--- a/syntax/typename.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{Atom, Type};
-
-pub fn to_typename(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(ident) => {
-            let mut inner = String::new();
-            // Do not apply namespace to built-in type
-            let is_user_type = Atom::from(ident).is_none();
-            if is_user_type {
-                for name in namespace {
-                    inner += name;
-                    inner += "::";
-                }
-            }
-            if let Some(ti) = Atom::from(ident) {
-                inner += ti.to_cxx();
-            } else {
-                inner += &ident.to_string();
-            };
-            inner
-        }
-        Type::RustBox(ptr) => format!("rust_box<{}>", to_typename(namespace, &ptr.inner)),
-        Type::RustVec(ptr) => format!("rust_vec<{}>", to_typename(namespace, &ptr.inner)),
-        Type::UniquePtr(ptr) => {
-            format!("::std::unique_ptr<{}>", to_typename(namespace, &ptr.inner))
-        }
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
-        _ => unimplemented!(),
-    }
-}

From 0d3a7357fd59d126d147196775a9db0879e7af3e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 420/2232] Remove unimplemented constructors from rust::Vec header


---

diff --git a/include/cxx.h b/include/cxx.h
index 250eba2..5f369d4 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -209,9 +209,6 @@ public:
   bool empty() const noexcept { return size() == 0; }
 
 private:
-  Vec() noexcept;
-  Vec(const Vec &other) noexcept;
-  Vec &operator=(Vec other) noexcept;
   void drop() noexcept;
 
   // Size and alignment statically verified by rust_vec.rs.

From cb80057051e15ff0384497c064f4bc596412103f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:14 +0000
Subject: [PATCH 421/2232] Wire up Vec destructor


---

diff --git a/include/cxx.h b/include/cxx.h
index 5f369d4..d3721ea 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -205,6 +205,8 @@ private:
 template <typename T>
 class Vec final {
 public:
+  ~Vec() noexcept { this->drop(); }
+
   size_t size() const noexcept;
   bool empty() const noexcept { return size() == 0; }
 

From 219c0790d4e157ca358d5a7baa08972ab6fcd4af Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 422/2232] Generate data accessor for Vec


---

diff --git a/gen/write.rs b/gen/write.rs
index f8bd1d8..9192a7e 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1021,6 +1021,11 @@ fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
         "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
+    writeln!(
+        out,
+        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        inner, instance,
+    );
     writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
 }
 
@@ -1061,6 +1066,15 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$data(this);",
+        instance,
+    );
+    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
diff --git a/include/cxx.h b/include/cxx.h
index d3721ea..c3037bd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -209,6 +209,7 @@ public:
 
   size_t size() const noexcept;
   bool empty() const noexcept { return size() == 0; }
+  const T *data() const noexcept;
 
 private:
   void drop() noexcept;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 81cf025..15351f0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -540,10 +540,12 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
     let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
+    let link_data = format!("{}data", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", ident);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
+    let local_data = format_ident!("{}data", local_prefix);
 
     let span = ty.span();
     quote_spanned! {span=>
@@ -557,6 +559,11 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#inner>) -> usize {
             (*this).len()
         }
+        #[doc(hidden)]
+        #[export_name = #link_data]
+        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#inner>) -> *const #inner {
+            (*this).as_ptr()
+        }
     }
 }
 
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 1c0c64f..32db8cc 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -29,6 +29,10 @@ impl<T> RustVec<T> {
     pub fn len(&self) -> usize {
         self.repr.len()
     }
+
+    pub fn as_ptr(&self) -> *const T {
+        self.repr.as_ptr()
+    }
 }
 
 const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<i32>>());

From 503d01902a6cd9b0f2dfd81f2b39c361144c06da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 423/2232] Add stride accessor for Vec


Will be required for implementing an iterator.

---

diff --git a/gen/write.rs b/gen/write.rs
index 9192a7e..d963bb9 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1026,6 +1026,11 @@ fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
         "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
+        instance,
+    );
     writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
 }
 
@@ -1075,6 +1080,11 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
         instance,
     );
     writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
+    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
diff --git a/include/cxx.h b/include/cxx.h
index c3037bd..f40614b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -212,6 +212,7 @@ public:
   const T *data() const noexcept;
 
 private:
+  static size_t stride() noexcept;
   void drop() noexcept;
 
   // Size and alignment statically verified by rust_vec.rs.
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 15351f0..7503f3a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -541,11 +541,13 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
+    let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", ident);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
+    let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = ty.span();
     quote_spanned! {span=>
@@ -564,6 +566,11 @@ fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStre
         unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#inner>) -> *const #inner {
             (*this).as_ptr()
         }
+        #[doc(hidden)]
+        #[export_name = #link_stride]
+        unsafe extern "C" fn #local_stride() -> usize {
+            ::std::mem::size_of::<#inner>()
+        }
     }
 }
 

From c87c215f56183fca32b2d82d4739043c72a3d10a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 424/2232] Add begin/end iterators to rust::Vec


---

diff --git a/gen/write.rs b/gen/write.rs
index d963bb9..f67057b 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -147,6 +147,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             }
             Type::RustVec(_) => {
                 out.include.array = true;
+                out.include.type_traits = true;
                 needs_rust_vec = true;
             }
             Type::Str(_) => {
diff --git a/include/cxx.h b/include/cxx.h
index f40614b..e16d9e0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -205,12 +205,50 @@ private:
 template <typename T>
 class Vec final {
 public:
+  using value_type = T;
+
   ~Vec() noexcept { this->drop(); }
 
   size_t size() const noexcept;
   bool empty() const noexcept { return size() == 0; }
   const T *data() const noexcept;
 
+  class const_iterator {
+  public:
+    using value_type = typename std::add_const<T>::type;
+    using reference = typename std::add_lvalue_reference<
+        typename std::add_const<T>::type>::type;
+
+    const T &operator*() const { return *static_cast<const T *>(this->pos); }
+    const_iterator &operator++() {
+      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+      return *this;
+    }
+    bool operator==(const const_iterator &other) const {
+      return this->pos == other.pos;
+    }
+    bool operator!=(const const_iterator &other) const {
+      return this->pos != other.pos;
+    }
+
+  private:
+    friend class Vec;
+    const void *pos;
+    size_t stride;
+  };
+
+  const_iterator begin() const noexcept {
+    const_iterator it;
+    it.pos = this->data();
+    it.stride = this->stride();
+    return it;
+  }
+  const_iterator end() const noexcept {
+    const_iterator it = this->begin();
+    it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+    return it;
+  }
+
 private:
   static size_t stride() noexcept;
   void drop() noexcept;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 46f04be..502be05 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -163,17 +163,15 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
 }
 
 void c_take_vec_u8(const rust::Vec<uint8_t> &v) {
-  auto cv = static_cast<std::vector<uint8_t>>(v);
-  uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
+  uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
     cxx_test_suite_set_correct();
   }
 }
 
 void c_take_vec_shared(const rust::Vec<Shared> &v) {
-  auto cv = static_cast<std::vector<Shared>>(v);
   uint32_t sum = 0;
-  for (auto i : cv) {
+  for (auto i : v) {
     sum += i.z;
   }
   if (sum == 2021) {

From 63da4d37b96995083a23ec710f3641a51cc312ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 425/2232] Emit unique_ptr<vector<>> as part of write_vector


---

diff --git a/gen/write.rs b/gen/write.rs
index f67057b..f456e18 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -923,11 +923,6 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         Atom::from(ident).is_none()
     }
 
-    fn allow_vector(ident: &Ident) -> bool {
-        // Note: built-in types such as u8 are already defined in cxx.cc
-        Atom::from(ident).is_none()
-    }
-
     out.begin_block("extern \"C\"");
     for ty in types {
         if let Type::RustBox(ty) = ty {
@@ -944,21 +939,14 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, &ptr.inner, types);
-                }
-            } else if let Type::CxxVector(ptr1) = &ptr.inner {
-                if let Type::Ident(inner) = &ptr1.inner {
-                    if allow_vector(inner) {
-                        out.next_section();
-                        write_unique_ptr(out, &ptr.inner, types);
-                    }
+                    write_unique_ptr(out, inner, types);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if allow_vector(inner) {
+                if Atom::from(inner).is_none() {
                     out.next_section();
-                    write_vector(out, inner);
+                    write_vector(out, ty, inner, types);
                 }
             }
         }
@@ -1088,13 +1076,29 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+    let ty = Type::Ident(ident.clone());
+    let instance = to_mangled(&out.namespace, &ty);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+
+    write_unique_ptr_common(out, &ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+}
+
+// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
+fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.utility = true;
     let inner = to_typename(&out.namespace, ty);
     let instance = to_mangled(&out.namespace, ty);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    let can_construct_from_value = match ty {
+        Type::Ident(ident) => types.structs.contains_key(ident),
+        _ => false,
+    };
+
     writeln!(
         out,
         "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -1112,21 +1116,18 @@ fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    match ty {
-        Type::Ident(ident) if types.structs.contains_key(ident) => {
-            writeln!(
+    if can_construct_from_value {
+        writeln!(
             out,
             "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
-            writeln!(
-                out,
-                "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-                inner, inner,
-            );
-            writeln!(out, "}}");
-        }
-        _ => (),
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
     }
     writeln!(
         out,
@@ -1156,30 +1157,15 @@ fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(out, "  ptr->~unique_ptr();");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
 }
 
-fn write_vector(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    // Do not apply namespace to built-in type
-    let is_user_type = Atom::from(ident).is_none();
-    if is_user_type {
-        for name in &out.namespace {
-            inner += name;
-            inner += "::";
-        }
-    }
-    let mut instance = inner.clone();
-    if let Some(ti) = Atom::from(ident) {
-        inner += ti.to_cxx();
-    } else {
-        inner += &ident.to_string();
-    };
-    instance += &ident.to_string();
-    let instance = instance.replace("::", "$");
+fn write_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_vector_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
     writeln!(
         out,
         "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
@@ -1201,5 +1187,8 @@ fn write_vector(out: &mut OutFile, ident: &Ident) {
     );
     writeln!(out, "  s.push_back(item);");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
+
+    write_unique_ptr_common(out, vector_ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
 }

From cd08c440ce1b2e3daff4dcc748ab15835ae2a4ad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 426/2232] Pare down to_typename to match usage


---

diff --git a/gen/write.rs b/gen/write.rs
index f456e18..19762cc 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -889,32 +889,21 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
 fn to_typename(namespace: &Namespace, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
-            let mut inner = String::new();
-            // Do not apply namespace to built-in type
-            let is_user_type = Atom::from(ident).is_none();
-            if is_user_type {
-                for name in namespace {
-                    inner += name;
-                    inner += "::";
-                }
+            let mut path = String::new();
+            for name in namespace {
+                path += name;
+                path += "::";
             }
-            if let Some(ti) = Atom::from(ident) {
-                inner += ti.to_cxx();
-            } else {
-                inner += &ident.to_string();
-            };
-            inner
-        }
-        Type::RustBox(ptr) => format!("rust_box<{}>", to_typename(namespace, &ptr.inner)),
-        Type::RustVec(ptr) => format!("rust_vec<{}>", to_typename(namespace, &ptr.inner)),
-        Type::UniquePtr(ptr) => {
-            format!("::std::unique_ptr<{}>", to_typename(namespace, &ptr.inner))
+            path += &ident.to_string();
+            path
         }
         Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
-        _ => unimplemented!(),
+        _ => unreachable!(),
     }
 }
 

From 029f1d6a2efeffb4cef169620a14b17ac80b64c6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 427/2232] Move C++-specific type printing back into C++ generator


---

diff --git a/gen/write.rs b/gen/write.rs
index 19762cc..c21cda1 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -810,7 +810,21 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(a) => write!(out, "{}", a.to_cxx()),
+            Some(Bool) => write!(out, "bool"),
+            Some(U8) => write!(out, "uint8_t"),
+            Some(U16) => write!(out, "uint16_t"),
+            Some(U32) => write!(out, "uint32_t"),
+            Some(U64) => write!(out, "uint64_t"),
+            Some(Usize) => write!(out, "size_t"),
+            Some(I8) => write!(out, "int8_t"),
+            Some(I16) => write!(out, "int16_t"),
+            Some(I32) => write!(out, "int32_t"),
+            Some(I64) => write!(out, "int64_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
+            Some(CxxString) => write!(out, "::std::string"),
+            Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
diff --git a/syntax/atom.rs b/syntax/atom.rs
index c68b3fe..c94abe2 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -43,27 +43,6 @@ impl Atom {
         }
     }
 
-    pub fn to_cxx(&self) -> &'static str {
-        use self::Atom::*;
-        match self {
-            Bool => "bool",
-            U8 => "uint8_t",
-            U16 => "uint16_t",
-            U32 => "uint32_t",
-            U64 => "uint64_t",
-            Usize => "size_t",
-            I8 => "int8_t",
-            I16 => "int16_t",
-            I32 => "int32_t",
-            I64 => "int64_t",
-            Isize => "::rust::isize",
-            F32 => "float",
-            F64 => "double",
-            CxxString => "::std::string",
-            RustString => "::rust::String",
-        }
-    }
-
     pub fn is_valid_vector_target(&self) -> bool {
         use self::Atom::*;
         *self == U8

From ce82c99f951607fc5ec5f22a841be6b14690fac8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 428/2232] Remove redundant semicolons from vector ops in cxx.cc


---

diff --git a/src/cxx.cc b/src/cxx.cc
index aacea9c..4351eda 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -237,16 +237,16 @@ void cxxbridge02$unique_ptr$std$string$drop(
   }
 
 extern "C" {
-STD_VECTOR_OPS(u8, uint8_t);
-STD_VECTOR_OPS(u16, uint16_t);
-STD_VECTOR_OPS(u32, uint32_t);
-STD_VECTOR_OPS(u64, uint64_t);
-STD_VECTOR_OPS(usize, size_t);
-STD_VECTOR_OPS(i8, int8_t);
-STD_VECTOR_OPS(i16, int16_t);
-STD_VECTOR_OPS(i32, int32_t);
-STD_VECTOR_OPS(i64, int64_t);
-STD_VECTOR_OPS(isize, rust::isize);
-STD_VECTOR_OPS(f32, float);
-STD_VECTOR_OPS(f64, double);
+STD_VECTOR_OPS(u8, uint8_t)
+STD_VECTOR_OPS(u16, uint16_t)
+STD_VECTOR_OPS(u32, uint32_t)
+STD_VECTOR_OPS(u64, uint64_t)
+STD_VECTOR_OPS(usize, size_t)
+STD_VECTOR_OPS(i8, int8_t)
+STD_VECTOR_OPS(i16, int16_t)
+STD_VECTOR_OPS(i32, int32_t)
+STD_VECTOR_OPS(i64, int64_t)
+STD_VECTOR_OPS(isize, rust::isize)
+STD_VECTOR_OPS(f32, float)
+STD_VECTOR_OPS(f64, double)
 } // extern "C"

From 6787be69587b3443bf54fbf46d47b4f98cff9852 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:15 +0000
Subject: [PATCH 429/2232] Move primitive Vec C++ shims into cxx crate


---

diff --git a/gen/write.rs b/gen/write.rs
index c21cda1..94de4fb 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -934,9 +934,11 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 write_rust_box_extern(out, inner);
             }
         } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(_) = &ty.inner {
-                out.next_section();
-                write_rust_vec_extern(out, &ty.inner);
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_rust_vec_extern(out, inner);
+                }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
@@ -964,8 +966,10 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 write_rust_box_impl(out, inner);
             }
         } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(_) = &ty.inner {
-                write_rust_vec_impl(out, &ty.inner);
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    write_rust_vec_impl(out, inner);
+                }
             }
         }
     }
@@ -997,9 +1001,10 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
 
     writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
@@ -1046,9 +1051,10 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
diff --git a/src/cxx.cc b/src/cxx.cc
index 4351eda..63b2166 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -236,17 +236,54 @@ void cxxbridge02$unique_ptr$std$string$drop(
     ptr->~unique_ptr();                                                        \
   }
 
+#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
+  void cxxbridge02$rust_vec$##RUST_TYPE##$drop(                                \
+      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
+  size_t cxxbridge02$rust_vec$##RUST_TYPE##$len(                               \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  const CXX_TYPE *cxxbridge02$rust_vec$##RUST_TYPE##$data(                     \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  size_t cxxbridge02$rust_vec$##RUST_TYPE##$stride() noexcept;
+
+#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
+  template <>                                                                  \
+  void rust::Vec<CXX_TYPE>::drop() noexcept {                                  \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$drop(this);                      \
+  }                                                                            \
+  template <>                                                                  \
+  size_t rust::Vec<CXX_TYPE>::size() const noexcept {                          \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$len(this);                       \
+  }                                                                            \
+  template <>                                                                  \
+  const CXX_TYPE *rust::Vec<CXX_TYPE>::data() const noexcept {                 \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$data(this);                      \
+  }                                                                            \
+  template <>                                                                  \
+  size_t rust::Vec<CXX_TYPE>::stride() noexcept {                              \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$stride();                        \
+  }
+
+// Usize and isize are the same type as one of the below.
+#define FOR_EACH_SIZED_PRIMITIVE(MACRO)                                        \
+  MACRO(u8, uint8_t)                                                           \
+  MACRO(u16, uint16_t)                                                         \
+  MACRO(u32, uint32_t)                                                         \
+  MACRO(u64, uint64_t)                                                         \
+  MACRO(i8, int8_t)                                                            \
+  MACRO(i16, int16_t)                                                          \
+  MACRO(i32, int32_t)                                                          \
+  MACRO(i64, int64_t)                                                          \
+  MACRO(f32, float)                                                            \
+  MACRO(f64, double)
+
+#define FOR_EACH_PRIMITIVE(MACRO)                                              \
+  FOR_EACH_SIZED_PRIMITIVE(MACRO)                                              \
+  MACRO(usize, size_t)                                                         \
+  MACRO(isize, rust::isize)
+
 extern "C" {
-STD_VECTOR_OPS(u8, uint8_t)
-STD_VECTOR_OPS(u16, uint16_t)
-STD_VECTOR_OPS(u32, uint32_t)
-STD_VECTOR_OPS(u64, uint64_t)
-STD_VECTOR_OPS(usize, size_t)
-STD_VECTOR_OPS(i8, int8_t)
-STD_VECTOR_OPS(i16, int16_t)
-STD_VECTOR_OPS(i32, int32_t)
-STD_VECTOR_OPS(i64, int64_t)
-STD_VECTOR_OPS(isize, rust::isize)
-STD_VECTOR_OPS(f32, float)
-STD_VECTOR_OPS(f64, double)
+FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
+FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
 } // extern "C"
+
+FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)

From 92105da4913bbf91eb28fa54c7d2c993d72f2ff8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 430/2232] Clarify name of C++ codegen for C++ vector


---

diff --git a/gen/write.rs b/gen/write.rs
index 94de4fb..5898654 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -951,7 +951,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(inner).is_none() {
                     out.next_section();
-                    write_vector(out, ty, inner, types);
+                    write_cxx_vector(out, ty, inner, types);
                 }
             }
         }
@@ -1168,7 +1168,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     writeln!(out, "}}");
 }
 
-fn write_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
     let element = Type::Ident(element.clone());
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);

From a006bca89140585c98c952091e4efbc78098ae51 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 431/2232] Move primitive Vec Rust shims into cxx crate


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 7503f3a..9e0ea9a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -56,7 +56,9 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+                if Atom::from(ident).is_none() {
+                    hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+                }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 32db8cc..4ca17ca 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,4 +1,5 @@
 use std::mem;
+use std::ptr;
 
 #[repr(C)]
 pub struct RustVec<T> {
@@ -35,5 +36,47 @@ impl<T> RustVec<T> {
     }
 }
 
+macro_rules! rust_vec_shims_for_primitive {
+    ($ty:ident) => {
+        const _: () = {
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$drop")]
+                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
+                    ptr::drop_in_place(this);
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$len")]
+                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
+                    (*this).len()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$data")]
+                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
+                    (*this).as_ptr()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$stride")]
+                unsafe extern "C" fn __stride() -> usize {
+                    mem::size_of::<$ty>()
+                }
+            }
+        };
+    };
+}
+
+rust_vec_shims_for_primitive!(u8);
+rust_vec_shims_for_primitive!(u16);
+rust_vec_shims_for_primitive!(u32);
+rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(i8);
+rust_vec_shims_for_primitive!(i16);
+rust_vec_shims_for_primitive!(i32);
+rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(f32);
+rust_vec_shims_for_primitive!(f64);
+
 const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<i32>>());
 const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<i32>>());

From f044663b2a6e91747a4a127c09d76670bf1455f2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 432/2232] Emit const assertions for every vector element type


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d9e8892..8294044 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -136,6 +136,8 @@ pub unsafe trait VectorElement: Sized {
 
 macro_rules! impl_vector_element_for_primitive {
     ($ty:ident) => {
+        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
+
         unsafe impl VectorElement for $ty {
             const __NAME: &'static dyn Display = &stringify!($ty);
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
@@ -230,5 +232,3 @@ impl_vector_element_for_primitive!(i64);
 impl_vector_element_for_primitive!(isize);
 impl_vector_element_for_primitive!(f32);
 impl_vector_element_for_primitive!(f64);
-
-const_assert_eq!(1, mem::align_of::<CxxVector<usize>>());
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 4ca17ca..564851e 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -38,6 +38,9 @@ impl<T> RustVec<T> {
 
 macro_rules! rust_vec_shims_for_primitive {
     ($ty:ident) => {
+        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
+        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
+
         const _: () = {
             attr! {
                 #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$drop")]
@@ -77,6 +80,3 @@ rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
-
-const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<i32>>());
-const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<i32>>());

From 7ff1b8c1b5d03b9eab4c3ffbc13d2ff574d9ae49 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 433/2232] Move is_valid_vector_target into type checker


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index c94abe2..eeea831 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -42,22 +42,6 @@ impl Atom {
             _ => None,
         }
     }
-
-    pub fn is_valid_vector_target(&self) -> bool {
-        use self::Atom::*;
-        *self == U8
-            || *self == U16
-            || *self == U32
-            || *self == U64
-            || *self == Usize
-            || *self == I8
-            || *self == I16
-            || *self == I32
-            || *self == I64
-            || *self == Isize
-            || *self == F32
-            || *self == F64
-    }
 }
 
 impl PartialEq<Atom> for Ident {
diff --git a/syntax/check.rs b/syntax/check.rs
index cbfa91b..8d4b207 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -92,7 +92,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 fn check_type_vec(cx: &mut Check, ptr: &Ty1) {
     // Vec can contain either user-defined type or u8
     if let Type::Ident(ident) = &ptr.inner {
-        if Atom::from(ident).map(|a| a.is_valid_vector_target()) == Some(true) {
+        if Atom::from(ident).map(is_valid_vector_target) == Some(true) {
             return;
         } else if cx.types.cxx.contains(ident) {
             cx.error(ptr, error::VEC_CXX_TYPE.msg);
@@ -130,7 +130,7 @@ fn check_type_vector(cx: &mut Check, ptr: &Ty1) {
         match Atom::from(ident) {
             None => return,
             Some(atom) => {
-                if atom.is_valid_vector_target() {
+                if is_valid_vector_target(atom) {
                     return;
                 }
             }
@@ -299,6 +299,21 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
 }
 
+fn is_valid_vector_target(atom: Atom) -> bool {
+    atom == U8
+        || atom == U16
+        || atom == U32
+        || atom == U64
+        || atom == Usize
+        || atom == I8
+        || atom == I16
+        || atom == I32
+        || atom == I64
+        || atom == Isize
+        || atom == F32
+        || atom == F64
+}
+
 fn span_for_struct_error(strct: &Struct) -> TokenStream {
     let struct_token = strct.struct_token;
     let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());

From fff4c8a5d6709d47b4844805c7e15c1e751b8983 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 434/2232] Clarify vector checking function names


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 8d4b207..5f767c0 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,9 +29,9 @@ fn do_typecheck(cx: &mut Check) {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
-            Type::RustVec(ptr) => check_type_vec(cx, ptr),
+            Type::RustVec(ptr) => check_type_rust_vec(cx, ptr),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
-            Type::CxxVector(ptr) => check_type_vector(cx, ptr),
+            Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
@@ -89,7 +89,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported target type of Box");
 }
 
-fn check_type_vec(cx: &mut Check, ptr: &Ty1) {
+fn check_type_rust_vec(cx: &mut Check, ptr: &Ty1) {
     // Vec can contain either user-defined type or u8
     if let Type::Ident(ident) = &ptr.inner {
         if Atom::from(ident).map(is_valid_vector_target) == Some(true) {
@@ -121,7 +121,7 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
-fn check_type_vector(cx: &mut Check, ptr: &Ty1) {
+fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
             cx.error(ptr, "vector of a Rust type is not supported yet");

From 2410aff870e114e0095803c0d49d4c1029b5141c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 435/2232] Rename vector element checking function


Vectors have elements, not targets. Pointers have targets.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 5f767c0..b53d0a4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -92,7 +92,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 fn check_type_rust_vec(cx: &mut Check, ptr: &Ty1) {
     // Vec can contain either user-defined type or u8
     if let Type::Ident(ident) = &ptr.inner {
-        if Atom::from(ident).map(is_valid_vector_target) == Some(true) {
+        if Atom::from(ident).map(is_valid_vector_element) == Some(true) {
             return;
         } else if cx.types.cxx.contains(ident) {
             cx.error(ptr, error::VEC_CXX_TYPE.msg);
@@ -130,7 +130,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
         match Atom::from(ident) {
             None => return,
             Some(atom) => {
-                if is_valid_vector_target(atom) {
+                if is_valid_vector_element(atom) {
                     return;
                 }
             }
@@ -299,7 +299,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
 }
 
-fn is_valid_vector_target(atom: Atom) -> bool {
+fn is_valid_vector_element(atom: Atom) -> bool {
     atom == U8
         || atom == U16
         || atom == U32

From 76a8424864b3211e3edfa93d1b2bf772e66f07b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 436/2232] Express is_valid_vector_element more compactly


---

diff --git a/syntax/check.rs b/syntax/check.rs
index b53d0a4..286dbae 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -300,18 +300,10 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
 }
 
 fn is_valid_vector_element(atom: Atom) -> bool {
-    atom == U8
-        || atom == U16
-        || atom == U32
-        || atom == U64
-        || atom == Usize
-        || atom == I8
-        || atom == I16
-        || atom == I32
-        || atom == I64
-        || atom == Isize
-        || atom == F32
-        || atom == F64
+    match atom {
+        U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 => true,
+        Bool | CxxString | RustString => false,
+    }
 }
 
 fn span_for_struct_error(strct: &Struct) -> TokenStream {

From c6d891ece2a3568acf9f2a081272427d8836d190 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:16 +0000
Subject: [PATCH 437/2232] Fix Vec type checking


The previous logic incorrectly accepted Atoms outside the intended set,
and also emitted duplicate errors for opaque C++ types.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 286dbae..9683224 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,7 +29,7 @@ fn do_typecheck(cx: &mut Check) {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
-            Type::RustVec(ptr) => check_type_rust_vec(cx, ptr),
+            Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
@@ -89,19 +89,21 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported target type of Box");
 }
 
-fn check_type_rust_vec(cx: &mut Check, ptr: &Ty1) {
-    // Vec can contain either user-defined type or u8
-    if let Type::Ident(ident) = &ptr.inner {
-        if Atom::from(ident).map(is_valid_vector_element) == Some(true) {
-            return;
-        } else if cx.types.cxx.contains(ident) {
-            cx.error(ptr, error::VEC_CXX_TYPE.msg);
-        } else {
+fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
+    if let Type::Ident(ident) = &ty.inner {
+        if cx.types.cxx.contains(ident) {
+            cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
+
+        match Atom::from(ident) {
+            Some(atom) if is_valid_vector_element(atom) => return,
+            None => return,
+            _ => {}
+        }
     }
 
-    cx.error(ptr, "unsupported target type of Vec");
+    cx.error(ty, "unsupported element type of Vec");
 }
 
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
diff --git a/syntax/error.rs b/syntax/error.rs
index 103a54f..f52d651 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -15,7 +15,6 @@ impl Display for Error {
 
 pub static ERRORS: &[Error] = &[
     BOX_CXX_TYPE,
-    VEC_CXX_TYPE,
     CXXBRIDGE_RESERVED,
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
@@ -30,12 +29,6 @@ pub static BOX_CXX_TYPE: Error = Error {
     note: Some("hint: use UniquePtr<>"),
 };
 
-pub static VEC_CXX_TYPE: Error = Error {
-    msg: "Vec of a C++ type is not supported yet",
-    label: None,
-    note: Some("hint: use UniquePtr<>"),
-};
-
 pub static CXXBRIDGE_RESERVED: Error = Error {
     msg: "identifiers starting with cxxbridge are reserved",
     label: Some("reserved identifier"),

From c0faaf6cda0e00f831a681d6b1f2bdd1f4599e9c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 438/2232] Update cxx vector check to match rust vec check


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 9683224..090a9ae 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -126,18 +126,19 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
-            cx.error(ptr, "vector of a Rust type is not supported yet");
+            cx.error(
+                ptr,
+                "C++ vector containing a Rust type is not supported yet",
+            );
         }
 
         match Atom::from(ident) {
+            Some(atom) if is_valid_vector_element(atom) => return,
             None => return,
-            Some(atom) => {
-                if is_valid_vector_element(atom) {
-                    return;
-                }
-            }
+            _ => {}
         }
     }
+
     cx.error(ptr, "unsupported vector target type");
 }
 

From 6bd63de58e2ee6b729bc3863e1406b197c9a4980 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 439/2232] Inline vector element check


These will need to diverge shortly; in particular we'd like to support
Rust vectors containing Rust strings and C++ vectors containing C++
strings.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 090a9ae..fd5ed67 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -97,9 +97,10 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
         }
 
         match Atom::from(ident) {
-            Some(atom) if is_valid_vector_element(atom) => return,
-            None => return,
-            _ => {}
+            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
+            Some(Bool) | Some(RustString) => { /* todo */ }
+            Some(CxxString) => {}
         }
     }
 
@@ -133,9 +134,10 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
         }
 
         match Atom::from(ident) {
-            Some(atom) if is_valid_vector_element(atom) => return,
-            None => return,
-            _ => {}
+            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
+            Some(CxxString) => { /* todo */ }
+            Some(Bool) | Some(RustString) => {}
         }
     }
 
@@ -302,13 +304,6 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
 }
 
-fn is_valid_vector_element(atom: Atom) -> bool {
-    match atom {
-        U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize | F32 | F64 => true,
-        Bool | CxxString | RustString => false,
-    }
-}
-
 fn span_for_struct_error(strct: &Struct) -> TokenStream {
     let struct_token = strct.struct_token;
     let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());

From 83a7ec99014b7bdce2ea1218e97ddf1b9f128855 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 440/2232] Remove unnecessary use of to_mangled from Rust generator


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9e0ea9a..e3ab530 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,4 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -7,7 +6,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, spanned::Spanned, Error, ItemMod, Result, Token};
+use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -57,7 +56,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
                 if Atom::from(ident).is_none() {
-                    hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+                    hidden.extend(expand_rust_vec(namespace, ident));
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
@@ -536,42 +535,40 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
-    let inner = ty;
-    let mangled = to_mangled(namespace, ty) + "$";
-    let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
+fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
+    let link_prefix = format!("cxxbridge02$rust_vec${}{}$", namespace, elem);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", ident);
+    let local_prefix = format_ident!("{}__vec_", elem);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
     let local_stride = format_ident!("{}stride", local_prefix);
 
-    let span = ty.span();
+    let span = elem.span();
     quote_spanned! {span=>
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#inner>) {
+        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
             ::std::ptr::drop_in_place(this);
         }
         #[doc(hidden)]
         #[export_name = #link_len]
-        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#inner>) -> usize {
+        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
             (*this).len()
         }
         #[doc(hidden)]
         #[export_name = #link_data]
-        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#inner>) -> *const #inner {
+        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
             (*this).as_ptr()
         }
         #[doc(hidden)]
         #[export_name = #link_stride]
         unsafe extern "C" fn #local_stride() -> usize {
-            ::std::mem::size_of::<#inner>()
+            ::std::mem::size_of::<#elem>()
         }
     }
 }

From bae50eff4ee306fa22c734e20af4866a974316e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 441/2232] Move C++-only to_mangled function to C++ generator


---

diff --git a/gen/write.rs b/gen/write.rs
index 5898654..0eabca4 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,7 +1,6 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::to_mangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
@@ -921,6 +920,29 @@ fn to_typename(namespace: &Namespace, ty: &Type) -> String {
     }
 }
 
+fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut instance = String::new();
+            // Do not apply namespace to built-in type
+            let is_user_type = Atom::from(ident).is_none();
+            if is_user_type {
+                for name in namespace {
+                    instance += name;
+                    instance += "$";
+                }
+            }
+            instance += &ident.to_string();
+            instance
+        }
+        Type::RustBox(ptr) => format!("rust_box${}", to_mangled(namespace, &ptr.inner)),
+        Type::RustVec(ptr) => format!("rust_vec${}", to_mangled(namespace, &ptr.inner)),
+        Type::UniquePtr(ptr) => format!("std$unique_ptr${}", to_mangled(namespace, &ptr.inner)),
+        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        _ => unimplemented!(),
+    }
+}
+
 fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     fn allow_unique_ptr(ident: &Ident) -> bool {
         Atom::from(ident).is_none()
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
deleted file mode 100644
index f52aa43..0000000
--- a/syntax/mangled.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{Atom, Type};
-
-pub fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(ident) => {
-            let mut instance = String::new();
-            // Do not apply namespace to built-in type
-            let is_user_type = Atom::from(ident).is_none();
-            if is_user_type {
-                for name in namespace {
-                    instance += name;
-                    instance += "$";
-                }
-            }
-            instance += &ident.to_string();
-            instance
-        }
-        Type::RustBox(ptr) => format!("rust_box${}", to_mangled(namespace, &ptr.inner)),
-        Type::RustVec(ptr) => format!("rust_vec${}", to_mangled(namespace, &ptr.inner)),
-        Type::UniquePtr(ptr) => format!("std$unique_ptr${}", to_mangled(namespace, &ptr.inner)),
-        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
-        _ => unimplemented!(),
-    }
-}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index d5b90f0..a4b0ac4 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -8,7 +8,6 @@ pub mod error;
 pub mod ident;
 mod impls;
 pub mod mangle;
-pub mod mangled;
 pub mod namespace;
 mod parse;
 pub mod set;

From acdf20ae87f2185869991db815b8e33a71903e49 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 442/2232] Simplify to_mangled to match usage


---

diff --git a/gen/write.rs b/gen/write.rs
index 0eabca4..8fc698c 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -920,26 +920,13 @@ fn to_typename(namespace: &Namespace, ty: &Type) -> String {
     }
 }
 
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
 fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
     match ty {
-        Type::Ident(ident) => {
-            let mut instance = String::new();
-            // Do not apply namespace to built-in type
-            let is_user_type = Atom::from(ident).is_none();
-            if is_user_type {
-                for name in namespace {
-                    instance += name;
-                    instance += "$";
-                }
-            }
-            instance += &ident.to_string();
-            instance
-        }
-        Type::RustBox(ptr) => format!("rust_box${}", to_mangled(namespace, &ptr.inner)),
-        Type::RustVec(ptr) => format!("rust_vec${}", to_mangled(namespace, &ptr.inner)),
-        Type::UniquePtr(ptr) => format!("std$unique_ptr${}", to_mangled(namespace, &ptr.inner)),
+        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
         Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
-        _ => unimplemented!(),
+        _ => unreachable!(),
     }
 }
 

From 9b304204b7c11f814d90ad2318e49ce7886537e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 443/2232] Use more appropriate name for vector arguments in tests


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0d904fc..a16775b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -41,9 +41,9 @@ pub mod ffi {
         fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
-        fn c_take_unique_ptr_vector_u8(s: UniquePtr<CxxVector<u8>>);
-        fn c_take_unique_ptr_vector_f64(s: UniquePtr<CxxVector<f64>>);
-        fn c_take_unique_ptr_vector_shared(s: UniquePtr<CxxVector<Shared>>);
+        fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
+        fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
         fn c_take_vec_u8(v: &Vec<u8>);
         fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);

From 1bcc9fe2e572da51f1e2ac2e5cda14ac971e6bea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 444/2232] Test returning opaque types in CxxVector from C to Rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index a16775b..d6a94e4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -30,6 +30,7 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
         fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
+        fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 502be05..372641c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -83,6 +83,10 @@ std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
   return vec;
 }
 
+std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque() {
+  return std::unique_ptr<std::vector<C>>(new std::vector<C>());
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index e1e163d..ed07ce6 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -32,6 +32,7 @@ std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
+std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);

From 2244d1f553e2d1c6faa5500d9c11af0cf262347e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:17 +0000
Subject: [PATCH 445/2232] Test passing CxxVector by reference from Rust to C


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d6a94e4..750b30e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -45,6 +45,7 @@ pub mod ffi {
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
         fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
         fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
+        fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_vec_u8(v: &Vec<u8>);
         fn c_take_vec_shared(v: &Vec<Shared>);
         fn c_take_callback(callback: fn(String) -> usize);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 372641c..04f5168 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -166,6 +166,12 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   }
 }
 
+void c_take_ref_vector(const std::vector<uint8_t> &v) {
+  if (v.size() == 4) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_vec_u8(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index ed07ce6..2c7428d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -47,6 +47,7 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
+void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_vec_u8(const rust::Vec<uint8_t> &v);
 void c_take_vec_shared(const rust::Vec<Shared> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
diff --git a/tests/test.rs b/tests/test.rs
index 1d903f0..771fe9b 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -91,6 +91,7 @@ fn test_c_take() {
     check!(ffi::c_take_unique_ptr_vector_shared(
         ffi::c_return_unique_ptr_vector_shared()
     ));
+    check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
     check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
     check!(ffi::c_take_vec_shared(&vec![
         ffi::Shared { z: 1010 },

From de5340ec856ffa78f80dcf85831135de5350084b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 446/2232] Test returning CxxVector by reference from C to Rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 750b30e..4a6ec81 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -31,6 +31,7 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
+        fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 04f5168..8503ac7 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -28,6 +28,8 @@ size_t C::set2(size_t n) {
   return this->n;
 }
 
+const std::vector<uint8_t> &C::get_v() const { return this->v; }
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -87,6 +89,10 @@ std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque() {
   return std::unique_ptr<std::vector<C>>(new std::vector<C>());
 }
 
+const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
+  return c.get_v();
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 2c7428d..0e9081a 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -15,9 +15,11 @@ public:
   size_t set(size_t n);
   size_t get2() const;
   size_t set2(size_t n);
+  const std::vector<uint8_t> &get_v() const;
 
 private:
   size_t n;
+  std::vector<uint8_t> v;
 };
 
 size_t c_return_primitive();
@@ -33,6 +35,7 @@ std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
+const std::vector<uint8_t> &c_return_ref_vector(const C &c);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);

From 99c93d864c55faecfa4b1a3bbbc27dceb8a0aaca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 447/2232] Add vector types to reserved names list


---

diff --git a/syntax/check.rs b/syntax/check.rs
index fd5ed67..4f52cb6 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -290,7 +290,12 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
 }
 
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
-    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
+    if ident == "Box"
+        || ident == "UniquePtr"
+        || ident == "Vec"
+        || ident == "CxxVector"
+        || Atom::from(ident).is_some()
+    {
         cx.error(ident, "reserved name");
     }
 }

From 51cc8ee0618e262422ee547f5f5150391e9cc3cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 448/2232] Fix module path of Vec in generated Rust code


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 2962a2b..13cbfcf 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -35,9 +35,12 @@ impl ToTokens for Var {
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if let "UniquePtr" | "RustVec" | "CxxVector" = self.name.to_string().as_str() {
-            let span = self.name.span();
+        let span = self.name.span();
+        let name = self.name.to_string();
+        if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
+        } else if name == "Vec" {
+            tokens.extend(quote_spanned!(span=> ::std::vec::));
         }
         self.name.to_tokens(tokens);
         self.langle.to_tokens(tokens);

From e70303c68e2d95e6c6411b6f80ee57212d99081a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 449/2232] Disallow passing CxxVector by move


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 4f52cb6..b61570c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -303,7 +303,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
-        Type::Slice(_) | Type::Void(_) => return true,
+        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)

From fa85fce8534636daaa1f86c182711436945b2626 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 450/2232] Clarify mentions of C++ vector in error messages


---

diff --git a/syntax/check.rs b/syntax/check.rs
index b61570c..0c75de8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -361,7 +361,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
-        Type::CxxVector(_) => "vector".to_owned(),
+        Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),

From b41e74c152d6debf883541a94fb9f29e71e43fec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 451/2232] Test returning Vec by value from C to Rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4a6ec81..0965e52 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -32,6 +32,7 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
+        fn c_return_rust_vec() -> Vec<u8>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8503ac7..7867bf0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -93,6 +93,10 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
   return c.get_v();
 }
 
+rust::Vec<uint8_t> c_return_rust_vec() {
+  throw std::runtime_error("unimplemented");
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0e9081a..9a067d2 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -36,6 +36,7 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
+rust::Vec<uint8_t> c_return_rust_vec();
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);

From e6d5021522cb675897afdf627f7cc25b3fea471e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 452/2232] Fix expansion of Rust Vec in extern signatures


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e3ab530..cda77db 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -746,7 +746,10 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
         }
-        Type::RustVec(ty) => quote!(::cxx::private::RustVec<#ty>),
+        Type::RustVec(ty) => {
+            let elem = expand_extern_type(&ty.inner);
+            quote!(::cxx::private::RustVec<#elem>)
+        }
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
             Type::RustVec(ty) => {

From 03dca701619a0d4b2018eba6afaf0aa245cec077 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:18 +0000
Subject: [PATCH 453/2232] Fix Vec returns by value


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index cda77db..35603c9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -296,6 +296,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
+            Type::RustVec(_) => Some(quote!(#call.into_vec())),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
diff --git a/syntax/types.rs b/syntax/types.rs
index 2ef1e1e..f3aaa16 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -96,6 +96,7 @@ impl<'a> Types<'a> {
                     Atom::from(ident) == Some(RustString)
                 }
             }
+            Type::RustVec(_) => true,
             _ => false,
         }
     }

From 8b9d176ea73a5ceb1db42c8b2e5660ccafc7f685 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 454/2232] Fix and test fallible return of Vec from C to Rust


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 35603c9..d27c15c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -281,6 +281,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
+            Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0965e52..6e636d8 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -61,6 +61,7 @@ pub mod ffi {
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
+        fn c_try_return_rust_vec() -> Result<Vec<u8>>;
 
         fn get(self: &C) -> usize;
         fn set(self: &mut C, n: usize) -> usize;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7867bf0..8ea3d06 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -223,6 +223,10 @@ std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
   return c_return_unique_ptr_string();
 }
 
+rust::Vec<uint8_t> c_try_return_rust_vec() {
+  throw std::runtime_error("unimplemented");
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 9a067d2..22fed58 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -65,5 +65,6 @@ rust::Str c_try_return_str(rust::Str);
 rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
+rust::Vec<uint8_t> c_try_return_rust_vec();
 
 } // namespace tests

From 7798969827735b267951e594a1d1b4ac4667e31f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 455/2232] Fix and test returning Vec by reference from C to Rust


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d27c15c..e7eece0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -287,6 +287,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 Type::Ident(ident) if ident == RustString => {
                     Some(quote!(#call.map(|r| r.as_string())))
                 }
+                Type::RustVec(_) => Some(quote!(#call.map(|r| r.as_vec()))),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
@@ -301,6 +302,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
+                Type::RustVec(_) => Some(quote!(#call.as_vec())),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 6e636d8..d66bcc0 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -33,6 +33,7 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
         fn c_return_rust_vec() -> Vec<u8>;
+        fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -62,6 +63,7 @@ pub mod ffi {
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
+        fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
         fn set(self: &mut C, n: usize) -> usize;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8ea3d06..805e9b9 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -97,6 +97,11 @@ rust::Vec<uint8_t> c_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
 
+const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -227,6 +232,11 @@ rust::Vec<uint8_t> c_try_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
 
+const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 22fed58..81125f8 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -37,6 +37,7 @@ std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
+const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -66,5 +67,6 @@ rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();
+const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
 } // namespace tests

From d2ce8a997b65aa7b733e4e026b6a90963374a46d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 456/2232] Fix and test passing Vec by value from Rust to C


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e7eece0..e0f3cc7 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -207,7 +207,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
-            Type::RustVec(_) => quote!(::cxx::private::RustVec::from(#var)),
+            Type::RustVec(_) => quote!(#var.as_mut_ptr() as *mut ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d66bcc0..fca9808 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -49,8 +49,9 @@ pub mod ffi {
         fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
         fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
         fn c_take_ref_vector(v: &CxxVector<u8>);
-        fn c_take_vec_u8(v: &Vec<u8>);
-        fn c_take_vec_shared(v: &Vec<Shared>);
+        fn c_take_rust_vec(v: Vec<u8>);
+        fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 805e9b9..c0b5888 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -187,14 +187,9 @@ void c_take_ref_vector(const std::vector<uint8_t> &v) {
   }
 }
 
-void c_take_vec_u8(const rust::Vec<uint8_t> &v) {
-  uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
-  if (sum == 200) {
-    cxx_test_suite_set_correct();
-  }
-}
+void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
 
-void c_take_vec_shared(const rust::Vec<Shared> &v) {
+void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   uint32_t sum = 0;
   for (auto i : v) {
     sum += i.z;
@@ -204,6 +199,13 @@ void c_take_vec_shared(const rust::Vec<Shared> &v) {
   }
 }
 
+void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
+  uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
+  if (sum == 200) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 81125f8..1d617ab 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -53,8 +53,9 @@ void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
-void c_take_vec_u8(const rust::Vec<uint8_t> &v);
-void c_take_vec_shared(const rust::Vec<Shared> &v);
+void c_take_rust_vec(rust::Vec<uint8_t> v);
+void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
diff --git a/tests/test.rs b/tests/test.rs
index 771fe9b..07c23bd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -92,11 +92,14 @@ fn test_c_take() {
         ffi::c_return_unique_ptr_vector_shared()
     ));
     check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
-    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
-    check!(ffi::c_take_vec_shared(&vec![
+    check!(ffi::c_take_rust_vec([86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
+    check!(ffi::c_take_rust_vec_shared(vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
     ]));
+    check!(ffi::c_take_ref_rust_vec(
+        &[86_u8, 75_u8, 30_u8, 9_u8].to_vec()
+    ));
 }
 
 #[test]

From 313b10ed1e9ed78cfaf36f767f05653f6c11fc54 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 457/2232] Add const bitcopy constructor for Vec


---

diff --git a/gen/write.rs b/gen/write.rs
index 8fc698c..ccd6c2f 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -186,7 +186,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                     needs_trycatch = true;
                 }
                 for arg in &efn.args {
-                    if arg.ty == RustString {
+                    let bitcopy = match arg.ty {
+                        Type::RustVec(_) => true,
+                        _ => arg.ty == RustString,
+                    };
+                    if bitcopy {
                         needs_unsafe_bitcopy = true;
                         break;
                     }
@@ -389,6 +393,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         if arg.ty == RustString {
             write!(out, "const ");
+        } else if let Type::RustVec(_) = arg.ty {
+            write!(out, "const ");
         }
         write_extern_arg(out, arg, types);
     }
@@ -467,6 +473,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 "::rust::String(::rust::unsafe_bitcopy, *{})",
                 arg.ident,
             );
+        } else if let Type::RustVec(_) = arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
diff --git a/include/cxx.h b/include/cxx.h
index e16d9e0..3dc1c4d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,7 +15,13 @@
 namespace rust {
 inline namespace cxxbridge02 {
 
-struct unsafe_bitcopy_t;
+#ifndef CXXBRIDGE02_RUST_BITCOPY
+#define CXXBRIDGE02_RUST_BITCOPY
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+#endif // CXXBRIDGE02_RUST_BITCOPY
 
 #ifndef CXXBRIDGE02_RUST_STRING
 #define CXXBRIDGE02_RUST_STRING
@@ -249,6 +255,9 @@ public:
     return it;
   }
 
+  // Internal API only intended for the cxxbridge code generator.
+  Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+
 private:
   static size_t stride() noexcept;
   void drop() noexcept;
@@ -316,14 +325,6 @@ using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
 
-#ifndef CXXBRIDGE02_RUST_BITCOPY
-#define CXXBRIDGE02_RUST_BITCOPY
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE02_RUST_BITCOPY
-
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e0f3cc7..af404d0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -146,6 +146,8 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ty = expand_extern_type(&arg.ty);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
+        } else if let Type::RustVec(_) = arg.ty {
+            quote!(#ident: *const #ty)
         } else if let Type::Fn(_) = arg.ty {
             quote!(#ident: ::cxx::private::FatFunction)
         } else if types.needs_indirect_abi(&arg.ty) {
@@ -207,7 +209,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
-            Type::RustVec(_) => quote!(#var.as_mut_ptr() as *mut ::cxx::private::RustVec<_>),
+            Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))

From f97c2d51ed6a6f3dbfb26eedba51912153e41111 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 458/2232] Add construction and assignment for rust::Vec


---

diff --git a/gen/write.rs b/gen/write.rs
index ccd6c2f..cdbfc75 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1028,6 +1028,11 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(
         out,
+        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
@@ -1075,6 +1080,11 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     let instance = to_mangled(&out.namespace, &element);
 
     writeln!(out, "template <>");
+    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
diff --git a/include/cxx.h b/include/cxx.h
index 3dc1c4d..c02d3d9 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -213,8 +213,22 @@ class Vec final {
 public:
   using value_type = T;
 
+  Vec() noexcept;
+  Vec(Vec &&other) noexcept {
+    this->repr = other.repr;
+    new (&other) Vec();
+  }
   ~Vec() noexcept { this->drop(); }
 
+  Vec &operator=(Vec &&other) noexcept {
+    if (this != &other) {
+      this->drop();
+      this->repr = other.repr;
+      new (&other) Vec();
+    }
+    return *this;
+  }
+
   size_t size() const noexcept;
   bool empty() const noexcept { return size() == 0; }
   const T *data() const noexcept;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index af404d0..2c8cc87 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -543,12 +543,14 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 
 fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let link_prefix = format!("cxxbridge02$rust_vec${}{}$", namespace, elem);
+    let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem);
+    let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
@@ -557,6 +559,11 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let span = elem.span();
     quote_spanned! {span=>
         #[doc(hidden)]
+        #[export_name = #link_new]
+        unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
+            ::std::ptr::write(this, ::cxx::private::RustVec::new());
+        }
+        #[doc(hidden)]
         #[export_name = #link_drop]
         unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
             ::std::ptr::drop_in_place(this);
diff --git a/src/cxx.cc b/src/cxx.cc
index 63b2166..7465f56 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -237,6 +237,8 @@ void cxxbridge02$unique_ptr$std$string$drop(
   }
 
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
+  void cxxbridge02$rust_vec$##RUST_TYPE##$new(                                 \
+      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
   void cxxbridge02$rust_vec$##RUST_TYPE##$drop(                                \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
   size_t cxxbridge02$rust_vec$##RUST_TYPE##$len(                               \
@@ -247,6 +249,10 @@ void cxxbridge02$unique_ptr$std$string$drop(
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
+  rust::Vec<CXX_TYPE>::Vec() noexcept {                                        \
+    cxxbridge02$rust_vec$##RUST_TYPE##$new(this);                              \
+  }                                                                            \
+  template <>                                                                  \
   void rust::Vec<CXX_TYPE>::drop() noexcept {                                  \
     return cxxbridge02$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 564851e..d5de489 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -7,6 +7,10 @@ pub struct RustVec<T> {
 }
 
 impl<T> RustVec<T> {
+    pub fn new() -> Self {
+        RustVec { repr: Vec::new() }
+    }
+
     pub fn from(v: Vec<T>) -> Self {
         RustVec { repr: v }
     }
@@ -43,6 +47,12 @@ macro_rules! rust_vec_shims_for_primitive {
 
         const _: () = {
             attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$new")]
+                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
+                    ptr::write(this, RustVec::new());
+                }
+            }
+            attr! {
                 #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);

From 83c69e92f73940237caa70572903b836943ef312 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:02:19 +0000
Subject: [PATCH 459/2232] Test Rust Vec in Rust signatures


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2c8cc87..be58cbd 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -427,9 +427,11 @@ fn expand_rust_function_shim_impl(
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
+            Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i == RustString => quote!(#ident.as_string()),
+                Type::RustVec(_) => quote!(#ident.as_vec()),
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -460,11 +462,13 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustString::from(#call)))
             }
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
+            Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     Some(quote!(::cxx::private::RustString::from_ref(#call)))
                 }
+                Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fca9808..d2c860e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -84,6 +84,8 @@ pub mod ffi {
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
+        fn r_return_rust_vec() -> Vec<u8>;
+        fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -95,6 +97,8 @@ pub mod ffi {
         fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn r_take_rust_vec(v: Vec<u8>);
+        fn r_take_ref_rust_vec(v: &Vec<u8>);
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
@@ -171,6 +175,15 @@ fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
     unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
 }
 
+fn r_return_rust_vec() -> Vec<u8> {
+    Vec::new()
+}
+
+fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
+    let _ = shared;
+    unimplemented!()
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
@@ -212,6 +225,14 @@ fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
 
+fn r_take_rust_vec(v: Vec<u8>) {
+    let _ = v;
+}
+
+fn r_take_ref_rust_vec(v: &Vec<u8>) {
+    let _ = v;
+}
+
 fn r_try_return_void() -> Result<(), Error> {
     Ok(())
 }

From 1768d8fd07b39a1ee970efe5bde49a1d72fb5669 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:15:14 +0000
Subject: [PATCH 460/2232] Specialize only within the same namespace


Without this, on some compilers:

    src/cxx.cc:252:30: error: specialization of ‘template<class T> rust::cxxbridge02::Vec<T>::Vec()’ in different namespace [-fpermissive]
       rust::Vec<CXX_TYPE>::Vec() noexcept {
                                  ^
    src/cxx.cc:274:3: note: in expansion of macro ‘RUST_VEC_OPS’
       MACRO(u8, uint8_t)
       ^
    src/cxx.cc:295:1: note: in expansion of macro ‘FOR_EACH_SIZED_PRIMITIVE’
     FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
     ^
    In file included from src/cxx.cc:1:0:
    include/cxx.h:216:3: error:   from definition of ‘template<class T> rust::cxxbridge02::Vec<T>::Vec()’ [-fpermissive]
       Vec() noexcept;
       ^

---

diff --git a/src/cxx.cc b/src/cxx.cc
index 7465f56..0ead3f0 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -249,23 +249,23 @@ void cxxbridge02$unique_ptr$std$string$drop(
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
-  rust::Vec<CXX_TYPE>::Vec() noexcept {                                        \
+  Vec<CXX_TYPE>::Vec() noexcept {                                              \
     cxxbridge02$rust_vec$##RUST_TYPE##$new(this);                              \
   }                                                                            \
   template <>                                                                  \
-  void rust::Vec<CXX_TYPE>::drop() noexcept {                                  \
+  void Vec<CXX_TYPE>::drop() noexcept {                                        \
     return cxxbridge02$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
   template <>                                                                  \
-  size_t rust::Vec<CXX_TYPE>::size() const noexcept {                          \
+  size_t Vec<CXX_TYPE>::size() const noexcept {                                \
     return cxxbridge02$rust_vec$##RUST_TYPE##$len(this);                       \
   }                                                                            \
   template <>                                                                  \
-  const CXX_TYPE *rust::Vec<CXX_TYPE>::data() const noexcept {                 \
+  const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
     return cxxbridge02$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
-  size_t rust::Vec<CXX_TYPE>::stride() noexcept {                              \
+  size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
     return cxxbridge02$rust_vec$##RUST_TYPE##$stride();                        \
   }
 
@@ -292,4 +292,8 @@ FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
 FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
 } // extern "C"
 
+namespace rust {
+inline namespace cxxbridge02 {
 FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
+} // namespace cxxbridge02
+} // namespace rust

From 47ee894a66a4203ce2497eff1c4f4943c2d21a4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 01:26:54 +0000
Subject: [PATCH 461/2232] Merge pull request #148 from dtolnay/vec


Vector fixes
---

diff --git a/README.md b/README.md
index a8f4093..f967762 100644
--- a/README.md
+++ b/README.md
@@ -303,6 +303,8 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
@@ -317,11 +319,9 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index 4940834..cd447ea 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -15,35 +15,7 @@ std::unique_ptr<ThingC> make_demo(rust::Str appname) {
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
 
-std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state) {
-  print_r(*state.y);
-  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  for (uint8_t i = 0; i < 10; i++) {
-    vec->push_back(i * i);
-  }
-  return vec;
-}
-
-JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec) {
-  JsonBlob retval;
-
-  std::cout << "incoming vec length is " << vec.size() << "\n";
-  auto vec_copy = static_cast<std::vector<uint8_t>>(vec);
-  std::cout << "vec_copy length is " << vec_copy.size() << "\n";
-  std::cout << "vec_copy[0] is " << (int)vec_copy[0] << "\n";
-
-  auto blob = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  for (uint8_t i = 0; i < 10; i++) {
-    blob->push_back(i * 2);
-  }
-
-  auto json = std::unique_ptr<std::string>(new std::string("{\"demo\": 23}"));
-
-  retval.json = std::move(json);
-  retval.blob = std::move(blob);
-
-  return retval;
-}
+void do_thing(SharedThing state) { print_r(*state.y); }
 
 } // namespace example
 } // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
index 2c9f1c0..fafc474 100644
--- a/demo-cxx/demo.h
+++ b/demo-cxx/demo.h
@@ -15,12 +15,10 @@ public:
 };
 
 struct SharedThing;
-struct JsonBlob;
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname);
 const std::string &get_name(const ThingC &thing);
-std::unique_ptr<std::vector<uint8_t>> do_thing(SharedThing state);
-JsonBlob get_jb(const ::rust::Vec<uint8_t> &vec);
+void do_thing(SharedThing state);
 
 } // namespace example
 } // namespace org
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
index 8bf9926..66dfc79 100644
--- a/demo-rs/src/main.rs
+++ b/demo-rs/src/main.rs
@@ -6,19 +6,13 @@ mod ffi {
         x: UniquePtr<ThingC>,
     }
 
-    struct JsonBlob {
-        json: UniquePtr<CxxString>,
-        blob: UniquePtr<Vector<u8>>,
-    }
-
     extern "C" {
         include!("demo-cxx/demo.h");
 
         type ThingC;
         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
         fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing) -> UniquePtr<Vector<u8>>;
-        fn get_jb(v: &Vec<u8>) -> JsonBlob;
+        fn do_thing(state: SharedThing);
     }
 
     extern "Rust" {
@@ -37,24 +31,9 @@ fn main() {
     let x = ffi::make_demo("demo of cxx::bridge");
     println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
 
-    let vec = ffi::do_thing(ffi::SharedThing {
+    ffi::do_thing(ffi::SharedThing {
         z: 222,
         y: Box::new(ThingR(333)),
         x,
     });
-
-    println!("vec length = {}", vec.as_ref().unwrap().size());
-    for (i, v) in vec.as_ref().unwrap().into_iter().enumerate() {
-        println!("vec[{}] = {}", i, v);
-    }
-
-    let mut rv: Vec<u8> = Vec::new();
-    for _ in 0..1000 {
-        rv.push(33);
-    }
-    let jb = ffi::get_jb(&rv);
-    println!("json: {}", jb.json.as_ref().unwrap());
-    for (i, v) in jb.blob.as_ref().unwrap().into_iter().enumerate() {
-        println!("jb.blob[{}] = {}", i, v);
-    }
 }
diff --git a/gen/include.rs b/gen/include.rs
index 077d03e..129a8e6 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -36,9 +36,9 @@ pub struct Includes {
     pub exception: bool,
     pub memory: bool,
     pub string: bool,
-    pub vector: bool,
     pub type_traits: bool,
     pub utility: bool,
+    pub vector: bool,
     pub base_tsd: bool,
 }
 
@@ -90,6 +90,9 @@ impl Display for Includes {
         if self.utility {
             writeln!(f, "#include <utility>")?;
         }
+        if self.vector {
+            writeln!(f, "#include <vector>")?;
+        }
         if self.base_tsd {
             writeln!(f, "#if defined(_WIN32)")?;
             writeln!(f, "#include <BaseTsd.h>")?;
diff --git a/gen/write.rs b/gen/write.rs
index 8a60f17..cdbfc75 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1,10 +1,8 @@
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::ToTypename;
 use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -125,7 +123,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
-            Type::Vector(_) => out.include.vector = true,
+            Type::CxxVector(_) => out.include.vector = true,
             Type::SliceRefU8(_) => out.include.cstdint = true,
             _ => {}
         }
@@ -147,6 +145,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_box = true;
             }
             Type::RustVec(_) => {
+                out.include.array = true;
                 out.include.type_traits = true;
                 needs_rust_vec = true;
             }
@@ -187,7 +186,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                     needs_trycatch = true;
                 }
                 for arg in &efn.args {
-                    if arg.ty == RustString {
+                    let bitcopy = match arg.ty {
+                        Type::RustVec(_) => true,
+                        _ => arg.ty == RustString,
+                    };
+                    if bitcopy {
                         needs_unsafe_bitcopy = true;
                         break;
                     }
@@ -390,6 +393,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         }
         if arg.ty == RustString {
             write!(out, "const ");
+        } else if let Type::RustVec(_) = arg.ty {
+            write!(out, "const ");
         }
         write_extern_arg(out, arg, types);
     }
@@ -468,6 +473,9 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
                 "::rust::String(::rust::unsafe_bitcopy, *{})",
                 arg.ident,
             );
+        } else if let Type::RustVec(_) = arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -479,7 +487,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Vector(_)) => write!(
+        Some(Type::CxxVector(_)) => write!(
             out,
             " /* Use RVO to convert to r-value and move construct */"
         ),
@@ -793,7 +801,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) => {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
@@ -810,7 +818,21 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(a) => write!(out, "{}", a.to_cxx()),
+            Some(Bool) => write!(out, "bool"),
+            Some(U8) => write!(out, "uint8_t"),
+            Some(U16) => write!(out, "uint16_t"),
+            Some(U32) => write!(out, "uint32_t"),
+            Some(U64) => write!(out, "uint64_t"),
+            Some(Usize) => write!(out, "size_t"),
+            Some(I8) => write!(out, "int8_t"),
+            Some(I16) => write!(out, "int16_t"),
+            Some(I32) => write!(out, "int32_t"),
+            Some(I64) => write!(out, "int64_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
+            Some(CxxString) => write!(out, "::std::string"),
+            Some(RustString) => write!(out, "::rust::String"),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
@@ -828,7 +850,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
-        Type::Vector(ty) => {
+        Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
             write!(out, ">");
@@ -880,7 +902,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::Str(_)
-        | Type::Vector(_)
+        | Type::CxxVector(_)
         | Type::RustVec(_)
         | Type::SliceRefU8(_)
         | Type::Fn(_) => write!(out, " "),
@@ -889,13 +911,36 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
-fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
-    fn allow_unique_ptr(ident: &Ident) -> bool {
-        Atom::from(ident).is_none()
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut path = String::new();
+            for name in namespace {
+                path += name;
+                path += "::";
+            }
+            path += &ident.to_string();
+            path
+        }
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        _ => unreachable!(),
+    }
+}
+
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
+        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        _ => unreachable!(),
     }
+}
 
-    fn allow_vector(ident: &Ident) -> bool {
-        // Note: built-in types such as u8 are already defined in cxx.cc
+fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
+    fn allow_unique_ptr(ident: &Ident) -> bool {
         Atom::from(ident).is_none()
     }
 
@@ -907,29 +952,24 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 write_rust_box_extern(out, inner);
             }
         } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(_) = &ty.inner {
-                out.next_section();
-                write_rust_vec_extern(out, &ty.inner);
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_rust_vec_extern(out, inner);
+                }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if allow_unique_ptr(inner) {
                     out.next_section();
-                    write_unique_ptr(out, &ptr.inner, types);
-                }
-            } else if let Type::Vector(ptr1) = &ptr.inner {
-                if let Type::Ident(inner) = &ptr1.inner {
-                    if allow_vector(inner) {
-                        out.next_section();
-                        write_unique_ptr(out, &ptr.inner, types);
-                    }
+                    write_unique_ptr(out, inner, types);
                 }
             }
-        } else if let Type::Vector(ptr) = ty {
+        } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if allow_vector(inner) {
+                if Atom::from(inner).is_none() {
                     out.next_section();
-                    write_vector(out, inner);
+                    write_cxx_vector(out, ty, inner, types);
                 }
             }
         }
@@ -944,8 +984,10 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
                 write_rust_box_impl(out, inner);
             }
         } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(_) = &ty.inner {
-                write_rust_vec_impl(out, &ty.inner);
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    write_rust_vec_impl(out, inner);
+                }
             }
         }
     }
@@ -977,28 +1019,38 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, ty: &Type) {
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
 
     writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$vector_from(const ::rust::Vec<{}> *ptr, const std::vector<{}> &vector) noexcept;",
-        instance, inner, inner
+        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
     );
     writeln!(
         out,
         "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
+    writeln!(
+        out,
+        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        inner, instance,
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
+        instance,
+    );
     writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
 }
 
@@ -1022,17 +1074,22 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "template <>");
+    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
+    writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
         "  return cxxbridge02$rust_vec${}$drop(this);",
-        instance
+        instance,
     );
     writeln!(out, "}}");
 
@@ -1042,27 +1099,43 @@ fn write_rust_vec_impl(out: &mut OutFile, ty: &Type) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(
         out,
-        "Vec<{}>::operator std::vector<{}>() const noexcept {{",
-        inner, inner
-    );
-    writeln!(
-        out,
-        "  std::vector<{}> v; v.reserve(this->size()); cxxbridge02$rust_vec${}$vector_from(this, v); return v;",
-        inner, instance,
+        "  return cxxbridge02$rust_vec${}$data(this);",
+        instance,
     );
     writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
+    writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
-    out.include.utility = true;
-    let namespace = out.namespace.iter().cloned().collect::<Vec<String>>();
-    let inner = ty.to_typename(&namespace);
-    let instance = ty.to_mangled(&namespace);
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+    let ty = Type::Ident(ident.clone());
+    let instance = to_mangled(&out.namespace, &ty);
 
     writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+
+    write_unique_ptr_common(out, &ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+}
+
+// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
+fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.utility = true;
+    let inner = to_typename(&out.namespace, ty);
+    let instance = to_mangled(&out.namespace, ty);
+
+    let can_construct_from_value = match ty {
+        Type::Ident(ident) => types.structs.contains_key(ident),
+        _ => false,
+    };
+
     writeln!(
         out,
         "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -1080,21 +1153,18 @@ fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
-    match ty {
-        Type::Ident(ident) if types.structs.contains_key(ident) => {
-            writeln!(
+    if can_construct_from_value {
+        writeln!(
             out,
             "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
-            writeln!(
-                out,
-                "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-                inner, inner,
-            );
-            writeln!(out, "}}");
-        }
-        _ => (),
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
     }
     writeln!(
         out,
@@ -1124,52 +1194,38 @@ fn write_unique_ptr(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(out, "  ptr->~unique_ptr();");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
 }
 
-fn write_vector(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    // Do not apply namespace to built-in type
-    let is_user_type = Atom::from(ident).is_none();
-    if is_user_type {
-        for name in &out.namespace {
-            inner += name;
-            inner += "::";
-        }
-    }
-    let mut instance = inner.clone();
-    if let Some(ti) = Atom::from(ident) {
-        inner += ti.to_cxx();
-    } else {
-        inner += &ident.to_string();
-    };
-    instance += &ident.to_string();
-    let instance = instance.replace("::", "$");
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_vector_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_vector_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge02$std$vector${}$length(const std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
-
     writeln!(
         out,
-        "void cxxbridge02$std$vector${}$push_back(std::vector<{}> &s, const {} &item) noexcept {{",
-        instance, inner, inner
+        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
     );
-    writeln!(out, "  s.push_back(item);");
+    writeln!(out, "  return s[pos];");
     writeln!(out, "}}");
-
     writeln!(
         out,
-        "const {} *cxxbridge02$std$vector${}$get_unchecked(const std::vector<{}> &s, size_t pos) noexcept {{",
-        inner, instance, inner,
+        "void cxxbridge02$std$vector${}$push_back(::std::vector<{}> &s, const {} &item) noexcept {{",
+        instance, inner, inner
     );
-    writeln!(out, "  return &s[pos];");
+    writeln!(out, "  s.push_back(item);");
     writeln!(out, "}}");
-    writeln!(out, "#endif // CXXBRIDGE02_vector_{}", instance);
+
+    write_unique_ptr_common(out, vector_ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index 8f03cbb..c02d3d9 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,7 +15,13 @@
 namespace rust {
 inline namespace cxxbridge02 {
 
-struct unsafe_bitcopy_t;
+#ifndef CXXBRIDGE02_RUST_BITCOPY
+#define CXXBRIDGE02_RUST_BITCOPY
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+#endif // CXXBRIDGE02_RUST_BITCOPY
 
 #ifndef CXXBRIDGE02_RUST_STRING
 #define CXXBRIDGE02_RUST_STRING
@@ -84,27 +90,6 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_STR
 
-#ifndef CXXBRIDGE02_RUST_VEC
-#define CXXBRIDGE02_RUST_VEC
-template <typename T>
-class Vec final {
-public:
-  size_t size() const noexcept;
-  explicit operator std::vector<T>() const noexcept;
-
-private:
-  Vec() noexcept;
-  Vec(const Vec &other) noexcept;
-  Vec &operator=(Vec other) noexcept;
-  void drop() noexcept;
-
-  // Repr
-  const T *ptr;
-  size_t len;
-  size_t capacity;
-};
-#endif // CXXBRIDGE02_RUST_VEC
-
 #ifndef CXXBRIDGE02_RUST_SLICE
 #define CXXBRIDGE02_RUST_SLICE
 template <typename T>
@@ -221,6 +206,81 @@ private:
 };
 #endif // CXXBRIDGE02_RUST_BOX
 
+#ifndef CXXBRIDGE02_RUST_VEC
+#define CXXBRIDGE02_RUST_VEC
+template <typename T>
+class Vec final {
+public:
+  using value_type = T;
+
+  Vec() noexcept;
+  Vec(Vec &&other) noexcept {
+    this->repr = other.repr;
+    new (&other) Vec();
+  }
+  ~Vec() noexcept { this->drop(); }
+
+  Vec &operator=(Vec &&other) noexcept {
+    if (this != &other) {
+      this->drop();
+      this->repr = other.repr;
+      new (&other) Vec();
+    }
+    return *this;
+  }
+
+  size_t size() const noexcept;
+  bool empty() const noexcept { return size() == 0; }
+  const T *data() const noexcept;
+
+  class const_iterator {
+  public:
+    using value_type = typename std::add_const<T>::type;
+    using reference = typename std::add_lvalue_reference<
+        typename std::add_const<T>::type>::type;
+
+    const T &operator*() const { return *static_cast<const T *>(this->pos); }
+    const_iterator &operator++() {
+      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+      return *this;
+    }
+    bool operator==(const const_iterator &other) const {
+      return this->pos == other.pos;
+    }
+    bool operator!=(const const_iterator &other) const {
+      return this->pos != other.pos;
+    }
+
+  private:
+    friend class Vec;
+    const void *pos;
+    size_t stride;
+  };
+
+  const_iterator begin() const noexcept {
+    const_iterator it;
+    it.pos = this->data();
+    it.stride = this->stride();
+    return it;
+  }
+  const_iterator end() const noexcept {
+    const_iterator it = this->begin();
+    it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+    return it;
+  }
+
+  // Internal API only intended for the cxxbridge code generator.
+  Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+
+private:
+  static size_t stride() noexcept;
+  void drop() noexcept;
+
+  // Size and alignment statically verified by rust_vec.rs.
+  std::array<uintptr_t, 3> repr;
+};
+#endif // CXXBRIDGE02_RUST_VEC
+
 #ifndef CXXBRIDGE02_RUST_FN
 #define CXXBRIDGE02_RUST_FN
 template <typename Signature, bool Throws = false>
@@ -279,14 +339,6 @@ using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
 
-#ifndef CXXBRIDGE02_RUST_BITCOPY
-#define CXXBRIDGE02_RUST_BITCOPY
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE02_RUST_BITCOPY
-
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 95a6f1a..be58cbd 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,14 +1,12 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::mangled::ToMangled;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::typename::ToTypename;
 use crate::syntax::{
     self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, spanned::Spanned, Error, ItemMod, Result, Token};
+use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let ident = &ffi.ident;
@@ -23,38 +21,6 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
-    // "Header" to define newtypes locally so we can implement
-    // traits on them.
-    expanded.extend(quote! {
-        pub struct Vector<T>(pub ::cxx::RealVector<T>);
-        impl<T: cxx::private::VectorTarget<T>> Vector<T> {
-            pub fn size(&self) -> usize {
-                self.0.size()
-            }
-            pub fn get(&self, pos: usize) -> Option<&T> {
-                self.0.get(pos)
-            }
-            pub fn get_unchecked(&self, pos: usize) -> &T {
-                self.0.get_unchecked(pos)
-            }
-            pub fn is_empty(&self) -> bool {
-                self.0.is_empty()
-            }
-            pub fn push_back(&mut self, item: &T) {
-                self.0.push_back(item)
-            }
-        }
-        impl<'a, T: cxx::private::VectorTarget<T>> IntoIterator for &'a Vector<T> {
-            type Item = &'a T;
-            type IntoIter = <&'a ::cxx::RealVector<T> as IntoIterator>::IntoIter;
-
-            fn into_iter(self) -> Self::IntoIter {
-                self.0.into_iter()
-            }
-        }
-        unsafe impl<T> Send for Vector<T> where T: Send + cxx::private::VectorTarget<T> {}
-    });
-
     for api in &apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
@@ -89,32 +55,23 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                hidden.extend(expand_rust_vec(namespace, &ty.inner, ident));
+                if Atom::from(ident).is_none() {
+                    hidden.extend(expand_rust_vec(namespace, ident));
+                }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
-                }
-            } else if let Type::Vector(_) = &ptr.inner {
-                // Generate code for unique_ptr<vector<T>> if T is not an atom
-                // or if T is a primitive.
-                // Code for primitives is already generated
-                match Atom::from(ident) {
-                    None => expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types)),
-                    Some(atom) => {
-                        if atom.is_valid_vector_target() {
-                            expanded.extend(expand_unique_ptr(namespace, &ptr.inner, types));
-                        }
-                    }
+                    expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
-        } else if let Type::Vector(ptr) = ty {
+        } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none() {
-                    // Generate code for Vector<T> if T is not an atom
-                    // Code for atoms is already generated
-                    expanded.extend(expand_vector(namespace, &ptr.inner));
+                    // Generate impl for CxxVector<T> if T is a struct or opaque
+                    // C++ type. Impl for primitives is already provided by cxx
+                    // crate.
+                    expanded.extend(expand_cxx_vector(namespace, ident));
                 }
             }
         }
@@ -189,6 +146,8 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ty = expand_extern_type(&arg.ty);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
+        } else if let Type::RustVec(_) = arg.ty {
+            quote!(#ident: *const #ty)
         } else if let Type::Fn(_) = arg.ty {
             quote!(#ident: ::cxx::private::FatFunction)
         } else if types.needs_indirect_abi(&arg.ty) {
@@ -250,12 +209,12 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
-            Type::RustVec(_) => quote!(::cxx::RustVec::from(#var)),
+            Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     quote!(::cxx::private::RustString::from_ref(#var))
                 }
-                Type::RustVec(_) => quote!(::cxx::RustVec::from_ref(#var)),
+                Type::RustVec(_) => quote!(::cxx::private::RustVec::from_ref(#var)),
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -324,11 +283,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
+            Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     Some(quote!(#call.map(|r| r.as_string())))
                 }
+                Type::RustVec(_) => Some(quote!(#call.map(|r| r.as_vec()))),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
@@ -339,9 +300,11 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
+            Type::RustVec(_) => Some(quote!(#call.into_vec())),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
+                Type::RustVec(_) => Some(quote!(#call.as_vec())),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
@@ -464,9 +427,11 @@ fn expand_rust_function_shim_impl(
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
+            Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i == RustString => quote!(#ident.as_string()),
+                Type::RustVec(_) => quote!(#ident.as_vec()),
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -497,11 +462,13 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustString::from(#call)))
             }
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
+            Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => {
                     Some(quote!(::cxx::private::RustString::from_ref(#call)))
                 }
+                Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
@@ -578,42 +545,54 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(namespace: &Namespace, ty: &Type, ident: &Ident) -> TokenStream {
-    let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
-    let link_prefix = format!("cxxbridge02$rust_vec${}", mangled);
+fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
+    let link_prefix = format!("cxxbridge02$rust_vec${}{}$", namespace, elem);
+    let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
-    let link_vector_from = format!("{}vector_from", link_prefix);
     let link_len = format!("{}len", link_prefix);
+    let link_data = format!("{}data", link_prefix);
+    let link_stride = format!("{}stride", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", ident);
+    let local_prefix = format_ident!("{}__vec_", elem);
+    let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
-    let local_vector_from = format_ident!("{}vector_from", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
+    let local_data = format_ident!("{}data", local_prefix);
+    let local_stride = format_ident!("{}stride", local_prefix);
 
-    let span = ty.span();
+    let span = elem.span();
     quote_spanned! {span=>
         #[doc(hidden)]
-        #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::cxx::RustVec<#inner>) {
-            std::ptr::drop_in_place(this);
+        #[export_name = #link_new]
+        unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
+            ::std::ptr::write(this, ::cxx::private::RustVec::new());
         }
-        #[export_name = #link_vector_from]
-        unsafe extern "C" fn #local_vector_from(this: *mut ::cxx::RustVec<#inner>, vector: *mut ::cxx::RealVector<#inner>) {
-            this.as_ref().unwrap().into_vector(vector.as_mut().unwrap());
+        #[doc(hidden)]
+        #[export_name = #link_drop]
+        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
+            ::std::ptr::drop_in_place(this);
         }
+        #[doc(hidden)]
         #[export_name = #link_len]
-        unsafe extern "C" fn #local_len(this: *const ::cxx::RustVec<#inner>) -> usize {
-            this.as_ref().unwrap().len()
+        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+            (*this).len()
+        }
+        #[doc(hidden)]
+        #[export_name = #link_data]
+        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
+            (*this).as_ptr()
+        }
+        #[doc(hidden)]
+        #[export_name = #link_stride]
+        unsafe extern "C" fn #local_stride() -> usize {
+            ::std::mem::size_of::<#elem>()
         }
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenStream {
-    let name = ty.to_typename(&namespace.segments);
-    let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
-    let prefix = format!("cxxbridge02$unique_ptr${}", mangled);
+fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
+    let name = ident.to_string();
+    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -621,8 +600,8 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = match ty {
-        Type::Ident(ident) if types.structs.contains_key(ident) => Some(quote! {
+    let new_method = if types.structs.contains_key(ident) {
+        Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
@@ -632,13 +611,14 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
                 unsafe { __new(&mut repr, &mut value) }
                 repr
             }
-        }),
-        _ => None,
+        })
+    } else {
+        None
     };
 
     quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #inner {
-            const __NAME: &'static str = #name;
+        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -652,7 +632,7 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
-                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #inner);
+                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #ident);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __raw(&mut repr, raw);
@@ -661,14 +641,14 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #inner;
+                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #ident;
                 }
                 __get(&repr)
             }
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
-                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #inner;
+                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #ident;
                 }
                 __release(&mut repr)
             }
@@ -683,85 +663,81 @@ fn expand_unique_ptr(namespace: &Namespace, ty: &Type, types: &Types) -> TokenSt
     }
 }
 
-fn expand_vector(namespace: &Namespace, ty: &Type) -> TokenStream {
-    let inner = ty;
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
-    let prefix = format!("cxxbridge02$std$vector${}", mangled);
-    let link_length = format!("{}length", prefix);
+fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
+    let name = elem.to_string();
+    let prefix = format!("cxxbridge02$std$vector${}{}$", namespace, elem);
+    let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let link_push_back = format!("{}push_back", prefix);
+    let unique_ptr_prefix = format!("cxxbridge02$unique_ptr$std$vector${}{}$", namespace, elem);
+    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);
+    let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
+    let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
     quote! {
-        impl ::cxx::private::VectorTarget<#inner> for #inner {
-            fn get_unchecked(v: &::cxx::RealVector<#inner>, pos: usize) -> &#inner {
+        unsafe impl ::cxx::private::VectorElement for #elem {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
-                    #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::RealVector<#inner>, _: usize) -> &#inner;
+                    #[link_name = #link_size]
+                    fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
                 }
-                unsafe {
-                    __get_unchecked(v, pos)
+                unsafe { __vector_size(v) }
+            }
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> &Self {
+                extern "C" {
+                    #[link_name = #link_get_unchecked]
+                    fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
                 }
+                &*__get_unchecked(v, pos)
             }
-            fn vector_length(v: &::cxx::RealVector<#inner>) -> usize {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_length]
-                        fn __vector_length(_: &::cxx::RealVector<#inner>) -> usize;
-                    }
-                    __vector_length(v)
+            fn __push_back(v: &::cxx::CxxVector<Self>, item: &Self) {
+                extern "C" {
+                    #[link_name = #link_push_back]
+                    fn __push_back(_: &::cxx::CxxVector<#elem>, _: &#elem);
                 }
+                unsafe { __push_back(v, item) }
             }
-            fn push_back(v: &::cxx::RealVector<#inner>, item: &#inner) {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_push_back]
-                        fn __push_back(_: &::cxx::RealVector<#inner>, _: &#inner) -> usize;
-                    }
-                    __push_back(v, item);
+            fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_null]
+                    fn __unique_ptr_null(this: *mut *mut ::std::ffi::c_void);
                 }
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                unsafe { __unique_ptr_null(&mut repr) }
+                repr
             }
-        }
-    }
-}
-
-pub fn expand_vector_builtin(ident: Ident) -> TokenStream {
-    let ty = Type::Ident(ident);
-    let inner = &ty;
-    let namespace = Namespace { segments: vec![] };
-    let mangled = ty.to_mangled(&namespace.segments) + "$";
-    let prefix = format!("cxxbridge02$std$vector${}", mangled);
-    let link_length = format!("{}length", prefix);
-    let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let link_push_back = format!("{}push_back", prefix);
-
-    quote! {
-        impl VectorTarget<#inner> for #inner {
-            fn get_unchecked(v: &RealVector<#inner>, pos: usize) -> &#inner {
+            unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
                 extern "C" {
-                    #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &RealVector<#inner>, _: usize) -> &#inner;
+                    #[link_name = #link_unique_ptr_raw]
+                    fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
                 }
-                unsafe {
-                    __get_unchecked(v, pos)
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                __unique_ptr_raw(&mut repr, raw);
+                repr
+            }
+            unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_get]
+                    fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
                 }
+                __unique_ptr_get(&repr)
             }
-            fn vector_length(v: &RealVector<#inner>) -> usize {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_length]
-                        fn __vector_length(_: &RealVector<#inner>) -> usize;
-                    }
-                    __vector_length(v)
+            unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_release]
+                    fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
                 }
+                __unique_ptr_release(&mut repr)
             }
-            fn push_back(v: &RealVector<#inner>, item: &#inner) {
-                unsafe {
-                    extern "C" {
-                        #[link_name = #link_push_back]
-                        fn __push_back(_: &RealVector<#inner>, _: &#inner) -> usize;
-                    }
-                    __push_back(v, item);
+            unsafe fn __unique_ptr_drop(mut repr: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_unique_ptr_drop]
+                    fn __unique_ptr_drop(this: *mut *mut ::std::ffi::c_void);
                 }
+                __unique_ptr_drop(&mut repr);
             }
         }
     }
@@ -787,12 +763,15 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
         }
-        Type::RustVec(ty) => quote!(::cxx::RustVec<#ty>),
+        Type::RustVec(ty) => {
+            let elem = expand_extern_type(&ty.inner);
+            quote!(::cxx::private::RustVec<#elem>)
+        }
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
             Type::RustVec(ty) => {
                 let inner = expand_extern_type(&ty.inner);
-                quote!(&::cxx::RustVec<#inner>)
+                quote!(&::cxx::private::RustVec<#inner>)
             }
             _ => quote!(#ty),
         },
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 87fe405..b56f58e 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -14,7 +14,7 @@ mod syntax;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, Ident, ItemMod};
+use syn::{parse_macro_input, ItemMod};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,9 +44,3 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
-
-#[proc_macro]
-pub fn vector_builtin(input: TokenStream) -> TokenStream {
-    let ident = parse_macro_input!(input as Ident);
-    expand::expand_vector_builtin(ident).into()
-}
diff --git a/src/concat.rs b/src/concat.rs
new file mode 100644
index 0000000..e67e50d
--- /dev/null
+++ b/src/concat.rs
@@ -0,0 +1,6 @@
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
diff --git a/src/cxx.cc b/src/cxx.cc
index a0e92ac..0ead3f0 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -200,65 +200,100 @@ void cxxbridge02$unique_ptr$std$string$drop(
 } // extern "C"
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  extern "C" {                                                                 \
-  size_t cxxbridge02$std$vector$##RUST_TYPE##$length(                          \
+  size_t cxxbridge02$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
-      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
-    s.push_back(item);                                                         \
-  }                                                                            \
   const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  static_assert(sizeof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==            \
-                    sizeof(void *),                                            \
-                "");                                                           \
-  static_assert(alignof(::std::unique_ptr<std::vector<CXX_TYPE>>) ==           \
-                    alignof(void *),                                           \
-                "");                                                           \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>();                       \
+  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
+      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
+    s.push_back(item);                                                         \
   }                                                                            \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$new(                    \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
-      std::vector<CXX_TYPE> *value) noexcept {                                 \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(                         \
-        new std::vector<CXX_TYPE>(::std::move(*value)));                       \
+  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
+    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                           \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
-    new (ptr)::std::unique_ptr<std::vector<CXX_TYPE>>(raw);                    \
+    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
-  const std::vector<CXX_TYPE> *                                                \
-      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
-          const ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {      \
+  const std::vector<CXX_TYPE>                                                  \
+      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
+          const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
-  std::vector<CXX_TYPE> *                                                      \
-      cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
-          ::std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {            \
+  std::vector<CXX_TYPE>                                                        \
+      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                \
+          std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
-      ::std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                \
+      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
+  }
+
+#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
+  void cxxbridge02$rust_vec$##RUST_TYPE##$new(                                 \
+      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
+  void cxxbridge02$rust_vec$##RUST_TYPE##$drop(                                \
+      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
+  size_t cxxbridge02$rust_vec$##RUST_TYPE##$len(                               \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  const CXX_TYPE *cxxbridge02$rust_vec$##RUST_TYPE##$data(                     \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  size_t cxxbridge02$rust_vec$##RUST_TYPE##$stride() noexcept;
+
+#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
+  template <>                                                                  \
+  Vec<CXX_TYPE>::Vec() noexcept {                                              \
+    cxxbridge02$rust_vec$##RUST_TYPE##$new(this);                              \
+  }                                                                            \
+  template <>                                                                  \
+  void Vec<CXX_TYPE>::drop() noexcept {                                        \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
-  } // extern "C"
-
-STD_VECTOR_OPS(u8, uint8_t);
-STD_VECTOR_OPS(u16, uint16_t);
-STD_VECTOR_OPS(u32, uint32_t);
-STD_VECTOR_OPS(u64, uint64_t);
-STD_VECTOR_OPS(usize, size_t);
-STD_VECTOR_OPS(i8, int8_t);
-STD_VECTOR_OPS(i16, int16_t);
-STD_VECTOR_OPS(i32, int32_t);
-STD_VECTOR_OPS(i64, int64_t);
-STD_VECTOR_OPS(isize, rust::isize);
-STD_VECTOR_OPS(f32, float);
-STD_VECTOR_OPS(f64, double);
+  template <>                                                                  \
+  size_t Vec<CXX_TYPE>::size() const noexcept {                                \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$len(this);                       \
+  }                                                                            \
+  template <>                                                                  \
+  const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$data(this);                      \
+  }                                                                            \
+  template <>                                                                  \
+  size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
+    return cxxbridge02$rust_vec$##RUST_TYPE##$stride();                        \
+  }
+
+// Usize and isize are the same type as one of the below.
+#define FOR_EACH_SIZED_PRIMITIVE(MACRO)                                        \
+  MACRO(u8, uint8_t)                                                           \
+  MACRO(u16, uint16_t)                                                         \
+  MACRO(u32, uint32_t)                                                         \
+  MACRO(u64, uint64_t)                                                         \
+  MACRO(i8, int8_t)                                                            \
+  MACRO(i16, int16_t)                                                          \
+  MACRO(i32, int32_t)                                                          \
+  MACRO(i64, int64_t)                                                          \
+  MACRO(f32, float)                                                            \
+  MACRO(f64, double)
+
+#define FOR_EACH_PRIMITIVE(MACRO)                                              \
+  FOR_EACH_SIZED_PRIMITIVE(MACRO)                                              \
+  MACRO(usize, size_t)                                                         \
+  MACRO(isize, rust::isize)
+
+extern "C" {
+FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
+FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
+} // extern "C"
+
+namespace rust {
+inline namespace cxxbridge02 {
+FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
+} // namespace cxxbridge02
+} // namespace rust
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
new file mode 100644
index 0000000..8294044
--- /dev/null
+++ b/src/cxx_vector.rs
@@ -0,0 +1,234 @@
+use std::ffi::c_void;
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+use std::mem;
+use std::ptr;
+
+/// Binding to C++ `std::vector<T, std::allocator<T>>`.
+///
+/// # Invariants
+///
+/// As an invariant of this API and the static analysis of the cxx::bridge
+/// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in
+/// Rust code we will only ever look at a vector behind a reference or smart
+/// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`.
+#[repr(C, packed)]
+pub struct CxxVector<T> {
+    _private: [T; 0],
+}
+
+impl<T> CxxVector<T>
+where
+    T: VectorElement,
+{
+    /// Returns the number of elements in the vector.
+    ///
+    /// Matches the behavior of C++ [std::vector\<T\>::size][size].
+    ///
+    /// [size]: https://en.cppreference.com/w/cpp/container/vector/size
+    pub fn len(&self) -> usize {
+        T::__vector_size(self)
+    }
+
+    /// Returns true if the vector contains no elements.
+    ///
+    /// Matches the behavior of C++ [std::vector\<T\>::empty][empty].
+    ///
+    /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Returns a reference to an element at the given position, or `None` if
+    /// out of bounds.
+    pub fn get(&self, pos: usize) -> Option<&T> {
+        if pos < self.len() {
+            Some(unsafe { T::__get_unchecked(self, pos) })
+        } else {
+            None
+        }
+    }
+
+    /// Returns a reference to an element without doing bounds checking.
+    ///
+    /// This is generally not recommended, use with caution! Calling this method
+    /// with an out-of-bounds index is undefined behavior even if the resulting
+    /// reference is not used.
+    ///
+    /// Matches the behavior of C++
+    /// [std::vector\<T\>::operator\[\]][operator_at].
+    ///
+    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
+    pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
+        T::__get_unchecked(self, pos)
+    }
+
+    /// Appends an element to the back of the vector.
+    pub fn push_back(&mut self, item: &T) {
+        T::__push_back(self, item);
+    }
+}
+
+pub struct Iter<'a, T> {
+    v: &'a CxxVector<T>,
+    index: usize,
+}
+
+impl<'a, T> IntoIterator for &'a CxxVector<T>
+where
+    T: VectorElement,
+{
+    type Item = &'a T;
+    type IntoIter = Iter<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Iter { v: self, index: 0 }
+    }
+}
+
+impl<'a, T> Iterator for Iter<'a, T>
+where
+    T: VectorElement,
+{
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.index = self.index + 1;
+        self.v.get(self.index - 1)
+    }
+}
+
+pub struct TypeName<T> {
+    element: PhantomData<T>,
+}
+
+impl<T> TypeName<T> {
+    pub const fn new() -> Self {
+        TypeName {
+            element: PhantomData,
+        }
+    }
+}
+
+impl<T> Display for TypeName<T>
+where
+    T: VectorElement,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        write!(formatter, "CxxVector<{}>", T::__NAME)
+    }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+#[doc(hidden)]
+pub unsafe trait VectorElement: Sized {
+    const __NAME: &'static dyn Display;
+    fn __vector_size(v: &CxxVector<Self>) -> usize;
+    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
+    fn __push_back(v: &CxxVector<Self>, item: &Self);
+    fn __unique_ptr_null() -> *mut c_void;
+    unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
+    unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
+    unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
+    unsafe fn __unique_ptr_drop(repr: *mut c_void);
+}
+
+macro_rules! impl_vector_element_for_primitive {
+    ($ty:ident) => {
+        const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
+
+        unsafe impl VectorElement for $ty {
+            const __NAME: &'static dyn Display = &stringify!($ty);
+            fn __vector_size(v: &CxxVector<$ty>) -> usize {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$size")]
+                        fn __vector_size(_: &CxxVector<$ty>) -> usize;
+                    }
+                }
+                unsafe { __vector_size(v) }
+            }
+            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$get_unchecked")]
+                        fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
+                    }
+                }
+                &*__get_unchecked(v, pos)
+            }
+            fn __push_back(v: &CxxVector<$ty>, item: &$ty) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$push_back")]
+                        fn __push_back(_: &CxxVector<$ty>, _: &$ty);
+                    }
+                }
+                unsafe { __push_back(v, item) }
+            }
+            fn __unique_ptr_null() -> *mut c_void {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        fn __unique_ptr_null(this: *mut *mut c_void);
+                    }
+                }
+                let mut repr = ptr::null_mut::<c_void>();
+                unsafe { __unique_ptr_null(&mut repr) }
+                repr
+            }
+            unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
+                    }
+                }
+                let mut repr = ptr::null_mut::<c_void>();
+                __unique_ptr_raw(&mut repr, raw);
+                repr
+            }
+            unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
+                    }
+                }
+                __unique_ptr_get(&repr)
+            }
+            unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
+                    }
+                }
+                __unique_ptr_release(&mut repr)
+            }
+            unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        fn __unique_ptr_drop(this: *mut *mut c_void);
+                    }
+                }
+                __unique_ptr_drop(&mut repr);
+            }
+        }
+    };
+}
+
+impl_vector_element_for_primitive!(u8);
+impl_vector_element_for_primitive!(u16);
+impl_vector_element_for_primitive!(u32);
+impl_vector_element_for_primitive!(u64);
+impl_vector_element_for_primitive!(usize);
+impl_vector_element_for_primitive!(i8);
+impl_vector_element_for_primitive!(i16);
+impl_vector_element_for_primitive!(i32);
+impl_vector_element_for_primitive!(i64);
+impl_vector_element_for_primitive!(isize);
+impl_vector_element_for_primitive!(f32);
+impl_vector_element_for_primitive!(f64);
diff --git a/src/lib.rs b/src/lib.rs
index e23be69..e4ef8f2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -311,6 +311,8 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>
@@ -325,11 +327,9 @@
 //!
 //! <table>
 //! <tr><th>name in Rust</th><th>name in C++</th></tr>
-//! <tr><td>Vec&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::vector&lt;T&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
@@ -358,8 +358,11 @@ extern crate link_cplusplus;
 
 #[macro_use]
 mod assert;
+#[macro_use]
+mod concat;
 
 mod cxx_string;
+mod cxx_vector;
 mod error;
 mod exception;
 mod function;
@@ -374,28 +377,26 @@ mod rust_vec;
 mod syntax;
 mod unique_ptr;
 mod unwind;
-mod vector;
 
 pub use crate::cxx_string::CxxString;
+pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
-pub use crate::rust_vec::RustVec;
 pub use crate::unique_ptr::UniquePtr;
-pub use crate::vector::RealVector;
-pub use crate::vector::VectorIntoIterator;
 pub use cxxbridge_macro::bridge;
 
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_vector::VectorElement;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
     pub use crate::rust_sliceu8::RustSliceU8;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
+    pub use crate::rust_vec::RustVec;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
-    pub use crate::vector::VectorTarget;
 }
 
 use crate::error::Result;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index a28570d..d5de489 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,18 +1,22 @@
-use crate::vector::RealVector;
-use crate::vector::VectorTarget;
+use std::mem;
+use std::ptr;
 
 #[repr(C)]
-pub struct RustVec<T: VectorTarget<T>> {
+pub struct RustVec<T> {
     repr: Vec<T>,
 }
 
-impl<T: VectorTarget<T>> RustVec<T> {
+impl<T> RustVec<T> {
+    pub fn new() -> Self {
+        RustVec { repr: Vec::new() }
+    }
+
     pub fn from(v: Vec<T>) -> Self {
         RustVec { repr: v }
     }
 
     pub fn from_ref(v: &Vec<T>) -> &Self {
-        unsafe { std::mem::transmute::<&Vec<T>, &RustVec<T>>(v) }
+        unsafe { &*(v as *const Vec<T> as *const RustVec<T>) }
     }
 
     pub fn into_vec(self) -> Vec<T> {
@@ -31,9 +35,58 @@ impl<T: VectorTarget<T>> RustVec<T> {
         self.repr.len()
     }
 
-    pub fn into_vector(&self, vec: &mut RealVector<T>) {
-        for item in &self.repr {
-            vec.push_back(item);
-        }
+    pub fn as_ptr(&self) -> *const T {
+        self.repr.as_ptr()
     }
 }
+
+macro_rules! rust_vec_shims_for_primitive {
+    ($ty:ident) => {
+        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
+        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
+
+        const _: () = {
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$new")]
+                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
+                    ptr::write(this, RustVec::new());
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$drop")]
+                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
+                    ptr::drop_in_place(this);
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$len")]
+                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
+                    (*this).len()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$data")]
+                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
+                    (*this).as_ptr()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$stride")]
+                unsafe extern "C" fn __stride() -> usize {
+                    mem::size_of::<$ty>()
+                }
+            }
+        };
+    };
+}
+
+rust_vec_shims_for_primitive!(u8);
+rust_vec_shims_for_primitive!(u16);
+rust_vec_shims_for_primitive!(u32);
+rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(i8);
+rust_vec_shims_for_primitive!(i16);
+rust_vec_shims_for_primitive!(i32);
+rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(f32);
+rust_vec_shims_for_primitive!(f64);
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index b50e870..98b4b7d 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,4 +1,5 @@
 use crate::cxx_string::CxxString;
+use crate::cxx_vector::{self, CxxVector, VectorElement};
 use std::ffi::c_void;
 use std::fmt::{self, Debug, Display};
 use std::marker::PhantomData;
@@ -149,7 +150,7 @@ where
 // codebase.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static str;
+    const __NAME: &'static dyn Display;
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
@@ -186,7 +187,7 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
-    const __NAME: &'static str = "CxxString";
+    const __NAME: &'static dyn Display = &"CxxString";
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe { unique_ptr_std_string_null(&mut repr) }
@@ -207,3 +208,25 @@ unsafe impl UniquePtrTarget for CxxString {
         unique_ptr_std_string_drop(&mut repr);
     }
 }
+
+unsafe impl<T> UniquePtrTarget for CxxVector<T>
+where
+    T: VectorElement + 'static,
+{
+    const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
+    fn __null() -> *mut c_void {
+        T::__unique_ptr_null()
+    }
+    unsafe fn __raw(raw: *mut Self) -> *mut c_void {
+        T::__unique_ptr_raw(raw)
+    }
+    unsafe fn __get(repr: *mut c_void) -> *const Self {
+        T::__unique_ptr_get(repr)
+    }
+    unsafe fn __release(repr: *mut c_void) -> *mut Self {
+        T::__unique_ptr_release(repr)
+    }
+    unsafe fn __drop(repr: *mut c_void) {
+        T::__unique_ptr_drop(repr);
+    }
+}
diff --git a/src/vector.rs b/src/vector.rs
deleted file mode 100644
index 805bdbb..0000000
--- a/src/vector.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-pub trait VectorTarget<T> {
-    fn get_unchecked(v: &RealVector<T>, pos: usize) -> &T
-    where
-        Self: Sized;
-    fn vector_length(v: &RealVector<T>) -> usize
-    where
-        Self: Sized;
-    fn push_back(v: &RealVector<T>, item: &T)
-    where
-        Self: Sized;
-}
-
-/// Binding to C++ `std::vector`.
-///
-/// # Invariants
-///
-/// As an invariant of this API and the static analysis of the cxx::bridge
-/// macro, in Rust code we can never obtain a `Vector` by value. C++'s vector
-/// requires a move constructor and may hold internal pointers, which is not
-/// compatible with Rust's move behavior. Instead in Rust code we will only ever
-/// look at a Vector through a reference or smart pointer, as in `&Vector`
-/// or `UniquePtr<Vector>`.
-#[repr(C)]
-pub struct RealVector<T> {
-    _private: [T; 0],
-}
-
-impl<T: VectorTarget<T>> RealVector<T> {
-    /// Returns the length of the vector in bytes.
-    pub fn size(&self) -> usize {
-        T::vector_length(self)
-    }
-
-    pub fn get_unchecked(&self, pos: usize) -> &T {
-        T::get_unchecked(self, pos)
-    }
-
-    /// Returns true if `self` has a length of zero bytes.
-    pub fn is_empty(&self) -> bool {
-        self.size() == 0
-    }
-
-    pub fn get(&self, pos: usize) -> Option<&T> {
-        if pos < self.size() {
-            Some(self.get_unchecked(pos))
-        } else {
-            None
-        }
-    }
-
-    pub fn push_back(&mut self, item: &T) {
-        T::push_back(self, item);
-    }
-}
-
-unsafe impl<T> Send for RealVector<T> where T: Send + VectorTarget<T> {}
-
-pub struct VectorIntoIterator<'a, T> {
-    v: &'a RealVector<T>,
-    index: usize,
-}
-
-impl<'a, T: VectorTarget<T>> IntoIterator for &'a RealVector<T> {
-    type Item = &'a T;
-    type IntoIter = VectorIntoIterator<'a, T>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        VectorIntoIterator { v: self, index: 0 }
-    }
-}
-
-impl<'a, T: VectorTarget<T>> Iterator for VectorIntoIterator<'a, T> {
-    type Item = &'a T;
-    fn next(&mut self) -> Option<Self::Item> {
-        self.index = self.index + 1;
-        self.v.get(self.index - 1)
-    }
-}
-
-cxxbridge_macro::vector_builtin!(u8);
-cxxbridge_macro::vector_builtin!(u16);
-cxxbridge_macro::vector_builtin!(u32);
-cxxbridge_macro::vector_builtin!(u64);
-cxxbridge_macro::vector_builtin!(usize);
-cxxbridge_macro::vector_builtin!(i8);
-cxxbridge_macro::vector_builtin!(i16);
-cxxbridge_macro::vector_builtin!(i32);
-cxxbridge_macro::vector_builtin!(i64);
-cxxbridge_macro::vector_builtin!(isize);
-cxxbridge_macro::vector_builtin!(f32);
-cxxbridge_macro::vector_builtin!(f64);
diff --git a/syntax/atom.rs b/syntax/atom.rs
index c68b3fe..eeea831 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -42,43 +42,6 @@ impl Atom {
             _ => None,
         }
     }
-
-    pub fn to_cxx(&self) -> &'static str {
-        use self::Atom::*;
-        match self {
-            Bool => "bool",
-            U8 => "uint8_t",
-            U16 => "uint16_t",
-            U32 => "uint32_t",
-            U64 => "uint64_t",
-            Usize => "size_t",
-            I8 => "int8_t",
-            I16 => "int16_t",
-            I32 => "int32_t",
-            I64 => "int64_t",
-            Isize => "::rust::isize",
-            F32 => "float",
-            F64 => "double",
-            CxxString => "::std::string",
-            RustString => "::rust::String",
-        }
-    }
-
-    pub fn is_valid_vector_target(&self) -> bool {
-        use self::Atom::*;
-        *self == U8
-            || *self == U16
-            || *self == U32
-            || *self == U64
-            || *self == Usize
-            || *self == I8
-            || *self == I16
-            || *self == I32
-            || *self == I64
-            || *self == Isize
-            || *self == F32
-            || *self == F64
-    }
 }
 
 impl PartialEq<Atom> for Ident {
diff --git a/syntax/check.rs b/syntax/check.rs
index 387f9a6..0c75de8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -29,9 +29,9 @@ fn do_typecheck(cx: &mut Check) {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
-            Type::RustVec(ptr) => check_type_vec(cx, ptr),
+            Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
-            Type::Vector(ptr) => check_type_vector(cx, ptr),
+            Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
             _ => {}
@@ -89,19 +89,22 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported target type of Box");
 }
 
-fn check_type_vec(cx: &mut Check, ptr: &Ty1) {
-    // Vec can contain either user-defined type or u8
-    if let Type::Ident(ident) = &ptr.inner {
-        if Atom::from(ident).map(|a| a.is_valid_vector_target()) == Some(true) {
-            return;
-        } else if cx.types.cxx.contains(ident) {
-            cx.error(ptr, error::VEC_CXX_TYPE.msg);
-        } else {
+fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
+    if let Type::Ident(ident) = &ty.inner {
+        if cx.types.cxx.contains(ident) {
+            cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
+
+        match Atom::from(ident) {
+            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
+            Some(Bool) | Some(RustString) => { /* todo */ }
+            Some(CxxString) => {}
+        }
     }
 
-    cx.error(ptr, "unsupported target type of Vec");
+    cx.error(ty, "unsupported element type of Vec");
 }
 
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
@@ -114,28 +117,30 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
             None | Some(CxxString) => return,
             _ => {}
         }
-    } else if let Type::Vector(_) = &ptr.inner {
+    } else if let Type::CxxVector(_) = &ptr.inner {
         return;
     }
 
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
-fn check_type_vector(cx: &mut Check, ptr: &Ty1) {
+fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(ident) {
-            cx.error(ptr, "vector of a Rust type is not supported yet");
+            cx.error(
+                ptr,
+                "C++ vector containing a Rust type is not supported yet",
+            );
         }
 
         match Atom::from(ident) {
-            None => return,
-            Some(atom) => {
-                if atom.is_valid_vector_target() {
-                    return;
-                }
-            }
+            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
+            Some(CxxString) => { /* todo */ }
+            Some(Bool) | Some(RustString) => {}
         }
     }
+
     cx.error(ptr, "unsupported vector target type");
 }
 
@@ -285,7 +290,12 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
 }
 
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
-    if ident == "Box" || ident == "UniquePtr" || Atom::from(ident).is_some() {
+    if ident == "Box"
+        || ident == "UniquePtr"
+        || ident == "Vec"
+        || ident == "CxxVector"
+        || Atom::from(ident).is_some()
+    {
         cx.error(ident, "reserved name");
     }
 }
@@ -293,7 +303,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
         Type::Ident(ident) => ident,
-        Type::Slice(_) | Type::Void(_) => return true,
+        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
     ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
@@ -351,7 +361,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
-        Type::Vector(_) => "vector".to_owned(),
+        Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
diff --git a/syntax/error.rs b/syntax/error.rs
index 103a54f..f52d651 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -15,7 +15,6 @@ impl Display for Error {
 
 pub static ERRORS: &[Error] = &[
     BOX_CXX_TYPE,
-    VEC_CXX_TYPE,
     CXXBRIDGE_RESERVED,
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
@@ -30,12 +29,6 @@ pub static BOX_CXX_TYPE: Error = Error {
     note: Some("hint: use UniquePtr<>"),
 };
 
-pub static VEC_CXX_TYPE: Error = Error {
-    msg: "Vec of a C++ type is not supported yet",
-    label: None,
-    note: Some("hint: use UniquePtr<>"),
-};
-
 pub static CXXBRIDGE_RESERVED: Error = Error {
     msg: "identifiers starting with cxxbridge are reserved",
     label: Some("reserved identifier"),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8e94f06..c34e3e5 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -27,7 +27,7 @@ impl Hash for Type {
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
-            Type::Vector(t) => t.hash(state),
+            Type::CxxVector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
@@ -47,7 +47,7 @@ impl PartialEq for Type {
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
-            (Type::Vector(lhs), Type::Vector(rhs)) => lhs == rhs,
+            (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
             (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
             (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
diff --git a/syntax/mangled.rs b/syntax/mangled.rs
deleted file mode 100644
index 56e8b73..0000000
--- a/syntax/mangled.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-use crate::syntax::{Atom, Type};
-
-pub trait ToMangled {
-    fn to_mangled(&self, namespace: &Vec<String>) -> String;
-}
-
-impl ToMangled for Type {
-    fn to_mangled(&self, namespace: &Vec<String>) -> String {
-        match self {
-            Type::Ident(ident) => {
-                let mut instance = String::new();
-                // Do not apply namespace to built-in type
-                let is_user_type = Atom::from(ident).is_none();
-                if is_user_type {
-                    for name in namespace {
-                        instance += name;
-                        instance += "$";
-                    }
-                }
-                instance += &ident.to_string();
-                instance
-            }
-            Type::RustBox(ptr) => format!("rust_box${}", ptr.inner.to_mangled(namespace)),
-            Type::RustVec(ptr) => format!("rust_vec${}", ptr.inner.to_mangled(namespace)),
-            Type::UniquePtr(ptr) => format!("std$unique_ptr${}", ptr.inner.to_mangled(namespace)),
-            Type::Vector(ptr) => format!("std$vector${}", ptr.inner.to_mangled(namespace)),
-            _ => unimplemented!(),
-        }
-    }
-}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4e0b908..a4b0ac4 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -8,13 +8,11 @@ pub mod error;
 pub mod ident;
 mod impls;
 pub mod mangle;
-pub mod mangled;
 pub mod namespace;
 mod parse;
 pub mod set;
 pub mod symbol;
 mod tokens;
-pub mod typename;
 pub mod types;
 
 use self::parse::kw;
@@ -92,7 +90,7 @@ pub enum Type {
     UniquePtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
-    Vector(Box<Ty1>),
+    CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
     Slice(Box<Slice>),
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index a4e972b..d26bb9e 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -11,7 +11,7 @@ mod kw {
 
 #[derive(Clone)]
 pub struct Namespace {
-    pub segments: Vec<String>,
+    segments: Vec<String>,
 }
 
 impl Namespace {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f5c598d..d14806d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,10 +300,10 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
-                } else if ident == "Vector" && generic.args.len() == 1 {
+                } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
-                        return Ok(Type::Vector(Box::new(Ty1 {
+                        return Ok(Type::CxxVector(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
                             inner,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 3d67a0a..13cbfcf 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -14,7 +14,7 @@ impl ToTokens for Type {
                 }
                 ident.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
+            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                 ty.to_tokens(tokens)
             }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
@@ -35,10 +35,12 @@ impl ToTokens for Var {
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        // Do not add cxx namespace to Vector since we're defining it in the user crate
-        if self.name == "UniquePtr" || self.name == "RustVec" {
-            let span = self.name.span();
+        let span = self.name.span();
+        let name = self.name.to_string();
+        if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
+        } else if name == "Vec" {
+            tokens.extend(quote_spanned!(span=> ::std::vec::));
         }
         self.name.to_tokens(tokens);
         self.langle.to_tokens(tokens);
diff --git a/syntax/typename.rs b/syntax/typename.rs
deleted file mode 100644
index 883e1fb..0000000
--- a/syntax/typename.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use crate::syntax::{Atom, Type};
-
-pub trait ToTypename {
-    fn to_typename(&self, namespace: &Vec<String>) -> String;
-}
-
-impl ToTypename for Type {
-    fn to_typename(&self, namespace: &Vec<String>) -> String {
-        match self {
-            Type::Ident(ident) => {
-                let mut inner = String::new();
-                // Do not apply namespace to built-in type
-                let is_user_type = Atom::from(ident).is_none();
-                if is_user_type {
-                    for name in namespace {
-                        inner += name;
-                        inner += "::";
-                    }
-                }
-                if let Some(ti) = Atom::from(ident) {
-                    inner += ti.to_cxx();
-                } else {
-                    inner += &ident.to_string();
-                };
-                inner
-            }
-            Type::RustBox(ptr) => format!("rust_box<{}>", ptr.inner.to_typename(namespace)),
-            Type::RustVec(ptr) => format!("rust_vec<{}>", ptr.inner.to_typename(namespace)),
-            Type::UniquePtr(ptr) => {
-                format!("std::unique_ptr<{}>", ptr.inner.to_typename(namespace))
-            }
-            Type::Vector(ptr) => format!("std::vector<{}>", ptr.inner.to_typename(namespace)),
-            _ => unimplemented!(),
-        }
-    }
-}
diff --git a/syntax/types.rs b/syntax/types.rs
index 7bce154..f3aaa16 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -24,9 +24,10 @@ impl<'a> Types<'a> {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
-                Type::RustBox(ty) | Type::UniquePtr(ty) | Type::Vector(ty) | Type::RustVec(ty) => {
-                    visit(all, &ty.inner)
-                }
+                Type::RustBox(ty)
+                | Type::UniquePtr(ty)
+                | Type::CxxVector(ty)
+                | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
@@ -95,6 +96,7 @@ impl<'a> Types<'a> {
                     Atom::from(ident) == Some(RustString)
                 }
             }
+            Type::RustVec(_) => true,
             _ => false,
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index da0040a..d2c860e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -27,9 +27,13 @@ pub mod ffi {
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
-        fn c_return_unique_ptr_vector_u8() -> UniquePtr<Vector<u8>>;
-        fn c_return_unique_ptr_vector_f64() -> UniquePtr<Vector<f64>>;
-        fn c_return_unique_ptr_vector_shared() -> UniquePtr<Vector<Shared>>;
+        fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
+        fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
+        fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
+        fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
+        fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
+        fn c_return_rust_vec() -> Vec<u8>;
+        fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -41,11 +45,13 @@ pub mod ffi {
         fn c_take_sliceu8(s: &[u8]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
-        fn c_take_unique_ptr_vector_u8(s: UniquePtr<Vector<u8>>);
-        fn c_take_unique_ptr_vector_f64(s: UniquePtr<Vector<f64>>);
-        fn c_take_unique_ptr_vector_shared(s: UniquePtr<Vector<Shared>>);
-        fn c_take_vec_u8(v: &Vec<u8>);
-        fn c_take_vec_shared(v: &Vec<Shared>);
+        fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
+        fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
+        fn c_take_ref_vector(v: &CxxVector<u8>);
+        fn c_take_rust_vec(v: Vec<u8>);
+        fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
@@ -57,6 +63,8 @@ pub mod ffi {
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
+        fn c_try_return_rust_vec() -> Result<Vec<u8>>;
+        fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
         fn set(self: &mut C, n: usize) -> usize;
@@ -76,6 +84,8 @@ pub mod ffi {
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
+        fn r_return_rust_vec() -> Vec<u8>;
+        fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -87,6 +97,8 @@ pub mod ffi {
         fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn r_take_rust_vec(v: Vec<u8>);
+        fn r_take_ref_rust_vec(v: &Vec<u8>);
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
@@ -163,6 +175,15 @@ fn r_return_unique_ptr_string() -> UniquePtr<CxxString> {
     unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr_string()) }
 }
 
+fn r_return_rust_vec() -> Vec<u8> {
+    Vec::new()
+}
+
+fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
+    let _ = shared;
+    unimplemented!()
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
@@ -204,6 +225,14 @@ fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
 
+fn r_take_rust_vec(v: Vec<u8>) {
+    let _ = v;
+}
+
+fn r_take_ref_rust_vec(v: &Vec<u8>) {
+    let _ = v;
+}
+
 fn r_try_return_void() -> Result<(), Error> {
     Ok(())
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a8d7018..c0b5888 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -28,6 +28,8 @@ size_t C::set2(size_t n) {
   return this->n;
 }
 
+const std::vector<uint8_t> &C::get_v() const { return this->v; }
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -59,29 +61,45 @@ std::unique_ptr<std::string> c_return_unique_ptr_string() {
 }
 
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8() {
-  auto retval =
-      std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
-  retval->push_back(86);
-  retval->push_back(75);
-  retval->push_back(30);
-  retval->push_back(9);
-  return retval;
+  auto vec = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  vec->push_back(86);
+  vec->push_back(75);
+  vec->push_back(30);
+  vec->push_back(9);
+  return vec;
 }
 
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
-  auto retval = std::unique_ptr<std::vector<double>>(new std::vector<double>());
-  retval->push_back(86.0);
-  retval->push_back(75.0);
-  retval->push_back(30.0);
-  retval->push_back(9.5);
-  return retval;
+  auto vec = std::unique_ptr<std::vector<double>>(new std::vector<double>());
+  vec->push_back(86.0);
+  vec->push_back(75.0);
+  vec->push_back(30.0);
+  vec->push_back(9.5);
+  return vec;
 }
 
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
-  auto retval = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
-  retval->push_back(Shared{1010});
-  retval->push_back(Shared{1011});
-  return retval;
+  auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
+  vec->push_back(Shared{1010});
+  vec->push_back(Shared{1011});
+  return vec;
+}
+
+std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque() {
+  return std::unique_ptr<std::vector<C>>(new std::vector<C>());
+}
+
+const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
+  return c.get_v();
+}
+
+rust::Vec<uint8_t> c_return_rust_vec() {
+  throw std::runtime_error("unimplemented");
+}
+
+const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
 }
 
 void c_take_primitive(size_t n) {
@@ -163,18 +181,17 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   }
 }
 
-void c_take_vec_u8(const ::rust::Vec<uint8_t> &v) {
-  auto cv = static_cast<std::vector<uint8_t>>(v);
-  uint8_t sum = std::accumulate(cv.begin(), cv.end(), 0);
-  if (sum == 200) {
+void c_take_ref_vector(const std::vector<uint8_t> &v) {
+  if (v.size() == 4) {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_vec_shared(const ::rust::Vec<Shared> &v) {
-  auto cv = static_cast<std::vector<Shared>>(v);
+void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
+
+void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   uint32_t sum = 0;
-  for (auto i : cv) {
+  for (auto i : v) {
     sum += i.z;
   }
   if (sum == 2021) {
@@ -182,6 +199,13 @@ void c_take_vec_shared(const ::rust::Vec<Shared> &v) {
   }
 }
 
+void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
+  uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
+  if (sum == 200) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
@@ -206,6 +230,15 @@ std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
   return c_return_unique_ptr_string();
 }
 
+rust::Vec<uint8_t> c_try_return_rust_vec() {
+  throw std::runtime_error("unimplemented");
+}
+
+const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 876e3c5..1d617ab 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -15,9 +15,11 @@ public:
   size_t set(size_t n);
   size_t get2() const;
   size_t set2(size_t n);
+  const std::vector<uint8_t> &get_v() const;
 
 private:
   size_t n;
+  std::vector<uint8_t> v;
 };
 
 size_t c_return_primitive();
@@ -32,6 +34,10 @@ std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
+std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
+const std::vector<uint8_t> &c_return_ref_vector(const C &c);
+rust::Vec<uint8_t> c_return_rust_vec();
+const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -46,8 +52,10 @@ void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
-void c_take_vec_u8(const ::rust::Vec<uint8_t> &v);
-void c_take_vec_shared(const ::rust::Vec<Shared> &v);
+void c_take_ref_vector(const std::vector<uint8_t> &v);
+void c_take_rust_vec(rust::Vec<uint8_t> v);
+void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
@@ -59,5 +67,7 @@ rust::Str c_try_return_str(rust::Str);
 rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
+rust::Vec<uint8_t> c_try_return_rust_vec();
+const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index b33c675..07c23bd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -32,44 +32,22 @@ fn test_c_return() {
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
-    assert_eq!(
-        4,
-        ffi::c_return_unique_ptr_vector_u8()
-            .as_ref()
-            .unwrap()
-            .size()
-    );
+    assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len());
     assert_eq!(
         200_u8,
-        ffi::c_return_unique_ptr_vector_u8()
-            .as_ref()
-            .unwrap()
-            .into_iter()
-            .sum()
+        ffi::c_return_unique_ptr_vector_u8().into_iter().sum(),
     );
     assert_eq!(
         200.5_f64,
-        ffi::c_return_unique_ptr_vector_f64()
-            .as_ref()
-            .unwrap()
-            .into_iter()
-            .sum()
-    );
-    assert_eq!(
-        2,
-        ffi::c_return_unique_ptr_vector_shared()
-            .as_ref()
-            .unwrap()
-            .size()
+        ffi::c_return_unique_ptr_vector_f64().into_iter().sum(),
     );
+    assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len());
     assert_eq!(
         2021_usize,
         ffi::c_return_unique_ptr_vector_shared()
-            .as_ref()
-            .unwrap()
             .into_iter()
             .map(|o| o.z)
-            .sum()
+            .sum(),
     );
 }
 
@@ -113,11 +91,15 @@ fn test_c_take() {
     check!(ffi::c_take_unique_ptr_vector_shared(
         ffi::c_return_unique_ptr_vector_shared()
     ));
-    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
-    check!(ffi::c_take_vec_shared(&vec![
+    check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
+    check!(ffi::c_take_rust_vec([86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
+    check!(ffi::c_take_rust_vec_shared(vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
     ]));
+    check!(ffi::c_take_ref_rust_vec(
+        &[86_u8, 75_u8, 30_u8, 9_u8].to_vec()
+    ));
 }
 
 #[test]

From a8df0943f5713622e79512dda87fe7e01a5782d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:08:40 +0000
Subject: [PATCH 462/2232] Document pass-by-value restriction of CxxVector


---

diff --git a/README.md b/README.md
index f967762..121abbe 100644
--- a/README.md
+++ b/README.md
@@ -304,7 +304,7 @@ returns of functions.
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/src/lib.rs b/src/lib.rs
index e4ef8f2..51783dd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -312,7 +312,7 @@
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>

From 8b6ffa6ab1099704e09e5ca0d3755167527622c4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:17:17 +0000
Subject: [PATCH 463/2232] Fix mutability of push_back trait method


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index be58cbd..c404e00 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -693,10 +693,10 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
                 }
                 &*__get_unchecked(v, pos)
             }
-            fn __push_back(v: &::cxx::CxxVector<Self>, item: &Self) {
+            fn __push_back(v: &mut ::cxx::CxxVector<Self>, item: &Self) {
                 extern "C" {
                     #[link_name = #link_push_back]
-                    fn __push_back(_: &::cxx::CxxVector<#elem>, _: &#elem);
+                    fn __push_back(_: &mut ::cxx::CxxVector<#elem>, _: &#elem);
                 }
                 unsafe { __push_back(v, item) }
             }
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 8294044..77e7af1 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -126,7 +126,7 @@ pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
     unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
-    fn __push_back(v: &CxxVector<Self>, item: &Self);
+    fn __push_back(v: &mut CxxVector<Self>, item: &Self);
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -158,11 +158,11 @@ macro_rules! impl_vector_element_for_primitive {
                 }
                 &*__get_unchecked(v, pos)
             }
-            fn __push_back(v: &CxxVector<$ty>, item: &$ty) {
+            fn __push_back(v: &mut CxxVector<$ty>, item: &$ty) {
                 extern "C" {
                     attr! {
                         #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$push_back")]
-                        fn __push_back(_: &CxxVector<$ty>, _: &$ty);
+                        fn __push_back(_: &mut CxxVector<$ty>, _: &$ty);
                     }
                 }
                 unsafe { __push_back(v, item) }

From 8d06f5b588e28524e89a1a8708e8ef4decd3854e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:17:42 +0000
Subject: [PATCH 464/2232] Remove CxxVector::push_back for now


I'd like to give some more thought to how to expose this. Taking the
value by reference and copying it into the vector is nice when T is an
opaque C++ type but otherwise a pretty weird API from Rust.

---

diff --git a/gen/write.rs b/gen/write.rs
index cdbfc75..b39d978 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -1217,13 +1217,6 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
     );
     writeln!(out, "  return s[pos];");
     writeln!(out, "}}");
-    writeln!(
-        out,
-        "void cxxbridge02$std$vector${}$push_back(::std::vector<{}> &s, const {} &item) noexcept {{",
-        instance, inner, inner
-    );
-    writeln!(out, "  s.push_back(item);");
-    writeln!(out, "}}");
 
     write_unique_ptr_common(out, vector_ty, types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c404e00..27d75fe 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -668,7 +668,6 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let prefix = format!("cxxbridge02$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let link_push_back = format!("{}push_back", prefix);
     let unique_ptr_prefix = format!("cxxbridge02$unique_ptr$std$vector${}{}$", namespace, elem);
     let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
     let link_unique_ptr_raw = format!("{}raw", unique_ptr_prefix);
@@ -693,13 +692,6 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
                 }
                 &*__get_unchecked(v, pos)
             }
-            fn __push_back(v: &mut ::cxx::CxxVector<Self>, item: &Self) {
-                extern "C" {
-                    #[link_name = #link_push_back]
-                    fn __push_back(_: &mut ::cxx::CxxVector<#elem>, _: &#elem);
-                }
-                unsafe { __push_back(v, item) }
-            }
             fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_null]
diff --git a/src/cxx.cc b/src/cxx.cc
index 0ead3f0..8409772 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -208,10 +208,6 @@ void cxxbridge02$unique_ptr$std$string$drop(
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  void cxxbridge02$std$vector$##RUST_TYPE##$push_back(                         \
-      std::vector<CXX_TYPE> &s, const CXX_TYPE &item) noexcept {               \
-    s.push_back(item);                                                         \
-  }                                                                            \
   void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 77e7af1..695fcad 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -62,11 +62,6 @@ where
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
         T::__get_unchecked(self, pos)
     }
-
-    /// Appends an element to the back of the vector.
-    pub fn push_back(&mut self, item: &T) {
-        T::__push_back(self, item);
-    }
 }
 
 pub struct Iter<'a, T> {
@@ -126,7 +121,6 @@ pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
     unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
-    fn __push_back(v: &mut CxxVector<Self>, item: &Self);
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -158,15 +152,6 @@ macro_rules! impl_vector_element_for_primitive {
                 }
                 &*__get_unchecked(v, pos)
             }
-            fn __push_back(v: &mut CxxVector<$ty>, item: &$ty) {
-                extern "C" {
-                    attr! {
-                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$push_back")]
-                        fn __push_back(_: &mut CxxVector<$ty>, _: &$ty);
-                    }
-                }
-                unsafe { __push_back(v, item) }
-            }
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {

From ad959f6f236d98b385f2c0e034d560cba33007ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:32:39 +0000
Subject: [PATCH 465/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 9696c97..d8e826f 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.17/src/**"]),
+    srcs = glob(["vendor/syn-1.0.18/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index a3db8b1..3a2ac5b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.17/src/**"]),
+    srcs = glob(["vendor/syn-1.0.18/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2e70499..c5d5302 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -299,9 +299,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.17"
+version = "1.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
+checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
 dependencies = [
  "proc-macro2",
  "quote",

From 7b4e6570154f6cb75e6a7c3677326330dd280a58 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:33:35 +0000
Subject: [PATCH 466/2232] Release 0.2.11


---

diff --git a/Cargo.toml b/Cargo.toml
index f497482..ad452fe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.10" # remember to update html_root_url
+version = "0.2.11" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.10", path = "macro" }
+cxxbridge-macro = { version = "=0.2.11", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 6ec328e..e87e1cf 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.10"
+version = "0.2.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index ca0e326..1dd11f5 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.10"
+version = "0.2.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 51783dd..0e724e1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.10")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.11")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index c5d5302..258e09c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.10"
+version = "0.2.11"
 dependencies = [
  "anyhow",
  "cc",
@@ -90,7 +90,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.10"
+version = "0.2.11"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.10"
+version = "0.2.11"
 dependencies = [
  "cxx",
  "proc-macro2",

From 52509840c7aa5317914ec88bfe44c08bc8255072 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:46:49 +0000
Subject: [PATCH 467/2232] Replace thiserror dependency with handwritten impls


A dependency wasn't carrying its weight for just two Error impls.

---

diff --git a/BUCK b/BUCK
index 4357dd6..50a9048 100644
--- a/BUCK
+++ b/BUCK
@@ -12,7 +12,6 @@ rust_library(
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
-        "//third-party:thiserror",
     ],
 )
 
@@ -30,7 +29,6 @@ rust_binary(
         "//third-party:quote",
         "//third-party:structopt",
         "//third-party:syn",
-        "//third-party:thiserror",
     ],
 )
 
diff --git a/BUILD b/BUILD
index 59ac9fc..2eea8c7 100644
--- a/BUILD
+++ b/BUILD
@@ -15,7 +15,6 @@ rust_library(
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
-        "//third-party:thiserror",
     ],
 )
 
@@ -31,7 +30,6 @@ rust_binary(
         "//third-party:quote",
         "//third-party:structopt",
         "//third-party:syn",
-        "//third-party:thiserror",
     ],
 )
 
diff --git a/Cargo.toml b/Cargo.toml
index ad452fe..1d6ede2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,7 +23,6 @@ link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
-thiserror = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index e87e1cf..9218478 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -21,7 +21,6 @@ proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0", features = ["full"] }
-thiserror = "1.0"
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/error.rs b/gen/error.rs
index ca78acb..2e8ecc4 100644
--- a/gen/error.rs
+++ b/gen/error.rs
@@ -1,15 +1,59 @@
-use crate::gen::Error;
 use crate::syntax;
 use anyhow::anyhow;
 use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
 use codespan_reporting::term::{self, Config};
-use std::io::Write;
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io::{self, Write};
 use std::ops::Range;
 use std::path::Path;
 use std::process;
 
+pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub(super) enum Error {
+    NoBridgeMod,
+    OutOfLineMod,
+    Io(io::Error),
+    Syn(syn::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
+            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
+            Error::Io(err) => err.fmt(f),
+            Error::Syn(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            Error::Syn(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
+}
+
+impl From<syn::Error> for Error {
+    fn from(err: syn::Error) -> Self {
+        Error::Syn(err)
+    }
+}
+
 pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
     match error {
         Error::Syn(syn_error) => {
diff --git a/gen/mod.rs b/gen/mod.rs
index 4c3a292..928c6ec 100644
--- a/gen/mod.rs
+++ b/gen/mod.rs
@@ -6,29 +6,13 @@ pub(super) mod include;
 pub(super) mod out;
 mod write;
 
-use self::error::format_err;
+use self::error::{format_err, Error, Result};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::{self, check, Types};
 use quote::quote;
 use std::fs;
-use std::io;
 use std::path::Path;
 use syn::{Attribute, File, Item};
-use thiserror::Error;
-
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
-
-#[derive(Error, Debug)]
-pub(super) enum Error {
-    #[error("no #[cxx::bridge] module found")]
-    NoBridgeMod,
-    #[error("#[cxx::bridge] module must have inline contents")]
-    OutOfLineMod,
-    #[error(transparent)]
-    Io(#[from] io::Error),
-    #[error(transparent)]
-    Syn(#[from] syn::Error),
-}
 
 struct Input {
     namespace: Namespace,
diff --git a/src/error.rs b/src/error.rs
index 0c19f98..740ab94 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,14 +1,37 @@
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
 use std::io;
-use thiserror::Error;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
-#[derive(Error, Debug)]
+#[derive(Debug)]
 pub(super) enum Error {
-    #[error("missing OUT_DIR environment variable")]
     MissingOutDir,
-    #[error("failed to locate target dir")]
     TargetDir,
-    #[error(transparent)]
-    Io(#[from] io::Error),
+    Io(io::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
+            Error::TargetDir => write!(f, "failed to locate target dir"),
+            Error::Io(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
 }
diff --git a/third-party/BUCK b/third-party/BUCK
index d8e826f..54a1e85 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -170,24 +170,6 @@ rust_library(
 )
 
 rust_library(
-    name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.15/src/**"]),
-    visibility = ["PUBLIC"],
-    deps = [":thiserror-impl"],
-)
-
-rust_library(
-    name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.15/src/**"]),
-    proc_macro = True,
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "unicode-segmentation",
     srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
     edition = "2015",
diff --git a/third-party/BUILD b/third-party/BUILD
index 3a2ac5b..c6ce473 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -175,24 +175,6 @@ rust_library(
 )
 
 rust_library(
-    name = "thiserror",
-    srcs = glob(["vendor/thiserror-1.0.15/src/**"]),
-    visibility = ["//visibility:public"],
-    deps = [":thiserror-impl"],
-)
-
-rust_library(
-    name = "thiserror-impl",
-    srcs = glob(["vendor/thiserror-impl-1.0.15/src/**"]),
-    crate_type = "proc-macro",
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "unicode-segmentation",
     srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
     edition = "2015",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 258e09c..0fc8cd8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -77,7 +77,6 @@ dependencies = [
  "quote",
  "rustversion",
  "syn",
- "thiserror",
  "trybuild",
 ]
 
@@ -98,7 +97,6 @@ dependencies = [
  "quote",
  "structopt",
  "syn",
- "thiserror",
 ]
 
 [[package]]
@@ -338,26 +336,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "thiserror"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54b3d3d2ff68104100ab257bb6bb0cb26c901abe4bd4ba15961f3bf867924012"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca972988113b7715266f91250ddb98070d033c62a011fa0fcc57434a649310dd"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "toml"
 version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From e948983427ffb4369cabbeabba6b08a94c66bfa5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 02:50:45 +0000
Subject: [PATCH 468/2232] Ignore BUILD files under target directory


After doing a `cargo publish` or `cargo package` we were getting a BUILD
file at target/package/cxx-0.2.11/BUILD which was subsequently picked up
by `bazel build ...`.

---

diff --git a/.bazelignore b/.bazelignore
new file mode 100644
index 0000000..2f7896d
--- /dev/null
+++ b/.bazelignore
@@ -0,0 +1 @@
+target/

From bd22ce57ddff10fb3060e4a2c2ed201098f2f013 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 26 2020 16:06:52 +0000
Subject: [PATCH 469/2232] Space out travis matrix


One big chunk of yaml with entries of varying length was annoying to
skim.

---

diff --git a/.travis.yml b/.travis.yml
index 124fc57..6c0ca54 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,7 @@ matrix:
     - name: macOS
       os: macos
       rust: nightly
+
     - name: Windows (gnu)
       os: windows
       rust: nightly-x86_64-pc-windows-gnu
@@ -21,12 +22,14 @@ matrix:
         # windows is bad at symlinks
         - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
         - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+
     - name: Windows (msvc)
       os: windows
       rust: nightly-x86_64-pc-windows-msvc
       before_script:
         - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
         - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+
     - name: Buck
       rust: nightly
       before_install:
@@ -41,6 +44,7 @@ matrix:
         - buck build :cxx#check --verbose=0
         - buck run demo-rs --verbose=0
         - buck test ... --verbose=0
+
     - name: Bazel
       rust: nightly
       before_install:
@@ -53,6 +57,7 @@ matrix:
       script:
         - bazel run demo-rs --verbose_failures --noshow_progress
         - bazel test ... --verbose_failures --noshow_progress
+
     - name: Minimum rustc
       rust: 1.42.0
       script:

From ba67607fa20cdcbfe9e52a9586d9a669ba9c3280 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 27 2020 23:00:50 +0000
Subject: [PATCH 470/2232] Allow wildcard argument names.


This adds support for wildcard variable names by internally giving
them unique names.

---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d14806d..a425c56 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,9 +6,9 @@ use crate::syntax::{
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
-    TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Ident,
+    Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token,
+    Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -193,6 +193,9 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
             FnArg::Typed(arg) => {
                 let ident = match arg.pat.as_ref() {
                     Pat::Ident(pat) => pat.ident.clone(),
+                    Pat::Wild(pat) => {
+                        Ident::new(&format!("_{}", args.len()), pat.underscore_token.span)
+                    }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
                 let ty = parse_type(&arg.ty)?;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d2c860e..69ef2b0 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -34,6 +34,8 @@ pub mod ffi {
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
+        fn c_return_identity(_: usize) -> usize;
+        fn c_return_sum(_: usize, _: usize) -> usize;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -86,6 +88,8 @@ pub mod ffi {
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
+        fn r_return_identity(_: usize) -> usize;
+        fn r_return_sum(_: usize, _: usize) -> usize;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -184,6 +188,14 @@ fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     unimplemented!()
 }
 
+fn r_return_identity(n: usize) -> usize {
+    n
+}
+
+fn r_return_sum(n1: usize, n2: usize) -> usize {
+    n1 + n2
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c0b5888..11096ba 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -102,6 +102,14 @@ const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+size_t c_return_identity(size_t n) {
+  return n;
+}
+
+size_t c_return_sum(size_t n1, size_t n2) {
+  return n1 + n2;
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -265,6 +273,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");
   ASSERT(*r_return_unique_ptr_string() == "2020");
+  ASSERT(r_return_identity(2020) == 2020);
+  ASSERT(r_return_sum(2020, 1) == 2021);
 
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 1d617ab..4600d64 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -38,6 +38,8 @@ std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
+size_t c_return_identity(size_t n);
+size_t c_return_sum(size_t n1, size_t n2);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
diff --git a/tests/test.rs b/tests/test.rs
index 07c23bd..4fd52d3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -49,6 +49,8 @@ fn test_c_return() {
             .map(|o| o.z)
             .sum(),
     );
+    assert_eq!(2020, ffi::c_return_identity(2020));
+    assert_eq!(2021, ffi::c_return_sum(2020, 1));
 }
 
 #[test]

From d6c521916f2893ceaecfe4a54f5fda503a6ec0f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 27 2020 23:46:22 +0000
Subject: [PATCH 471/2232] Merge pull request #159 from jgalenson/underscore


Allow wildcard argument names.
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d14806d..a425c56 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,9 +6,9 @@ use crate::syntax::{
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item,
-    ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType,
-    TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Ident,
+    Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token,
+    Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -193,6 +193,9 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
             FnArg::Typed(arg) => {
                 let ident = match arg.pat.as_ref() {
                     Pat::Ident(pat) => pat.ident.clone(),
+                    Pat::Wild(pat) => {
+                        Ident::new(&format!("_{}", args.len()), pat.underscore_token.span)
+                    }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
                 let ty = parse_type(&arg.ty)?;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d2c860e..69ef2b0 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -34,6 +34,8 @@ pub mod ffi {
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
+        fn c_return_identity(_: usize) -> usize;
+        fn c_return_sum(_: usize, _: usize) -> usize;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -86,6 +88,8 @@ pub mod ffi {
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
+        fn r_return_identity(_: usize) -> usize;
+        fn r_return_sum(_: usize, _: usize) -> usize;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -184,6 +188,14 @@ fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     unimplemented!()
 }
 
+fn r_return_identity(n: usize) -> usize {
+    n
+}
+
+fn r_return_sum(n1: usize, n2: usize) -> usize {
+    n1 + n2
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c0b5888..11096ba 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -102,6 +102,14 @@ const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+size_t c_return_identity(size_t n) {
+  return n;
+}
+
+size_t c_return_sum(size_t n1, size_t n2) {
+  return n1 + n2;
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -265,6 +273,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");
   ASSERT(*r_return_unique_ptr_string() == "2020");
+  ASSERT(r_return_identity(2020) == 2020);
+  ASSERT(r_return_sum(2020, 1) == 2021);
 
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 1d617ab..4600d64 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -38,6 +38,8 @@ std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
+size_t c_return_identity(size_t n);
+size_t c_return_sum(size_t n1, size_t n2);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
diff --git a/tests/test.rs b/tests/test.rs
index 07c23bd..4fd52d3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -49,6 +49,8 @@ fn test_c_return() {
             .map(|o| o.z)
             .sum(),
     );
+    assert_eq!(2020, ffi::c_return_identity(2020));
+    assert_eq!(2021, ffi::c_return_sum(2020, 1));
 }
 
 #[test]

From 378ca50c4c61ce15a23cf2080c7cdb41cdaa2cb5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 27 2020 23:47:55 +0000
Subject: [PATCH 472/2232] Format PR 159 with clang-format


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 11096ba..79db42c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -102,13 +102,9 @@ const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
-size_t c_return_identity(size_t n) {
-  return n;
-}
+size_t c_return_identity(size_t n) { return n; }
 
-size_t c_return_sum(size_t n1, size_t n2) {
-  return n1 + n2;
-}
+size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
 
 void c_take_primitive(size_t n) {
   if (n == 2020) {

From 4f3b6fd2e988478f96755250446792bb407136a7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 00:10:12 +0000
Subject: [PATCH 473/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 0fc8cd8..70ae2cc 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -139,9 +139,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d737e0f947a1864e93d33fdef4af8445a00d1ed8dc0c8ddb73139ea6abf15"
+checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
 dependencies = [
  "libc",
 ]
@@ -346,9 +346,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "459186ab1afd6d93bd23c2269125f4f7694f8771fe0e64434b4bdc212b94034d"
+checksum = "4e5696e4fd793743fbcc29943fe965ea3993b6c3d2a6a3a35c6680d926fd3a49"
 dependencies = [
  "dissimilar",
  "glob",

From 4fc533190ae771039fa5b4546767a06cbd6b502e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 00:10:39 +0000
Subject: [PATCH 474/2232] Release 0.2.12


---

diff --git a/Cargo.toml b/Cargo.toml
index 1d6ede2..a47a842 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.11" # remember to update html_root_url
+version = "0.2.12" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge02"
@@ -18,7 +18,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-cxxbridge-macro = { version = "=0.2.11", path = "macro" }
+cxxbridge-macro = { version = "=0.2.12", path = "macro" }
 link-cplusplus = "1.0"
 proc-macro2 = { version = "1.0", features = ["span-locations"] }
 quote = "1.0"
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
index 9218478..742d54b 100644
--- a/cmd/Cargo.toml
+++ b/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.11"
+version = "0.2.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1dd11f5..82401ee 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.11"
+version = "0.2.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 0e724e1..cff1e88 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -337,7 +337,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.11")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.2.12")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 70ae2cc..0bd470b 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.11"
+version = "0.2.12"
 dependencies = [
  "anyhow",
  "cc",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.11"
+version = "0.2.12"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.11"
+version = "0.2.12"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5d08baa8ae0c5473358e895bbd0a332ee9f0a620 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 01:12:08 +0000
Subject: [PATCH 475/2232] Link to release notes from readme


---

diff --git a/README.md b/README.md
index 121abbe..7dc7c8b 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,8 @@ can be 100% safe.
 cxx = "0.2"
 ```
 
-*Compiler support: requires rustc 1.42+*
+*Compiler support: requires rustc 1.42+*<br>
+*[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
 

From a53c90f08a56fdf6d9da202282ac9bd370129c63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 01:21:52 +0000
Subject: [PATCH 476/2232] Merge pull request #160 from dtolnay/relnotes


Link to release notes from readme
---

diff --git a/README.md b/README.md
index 121abbe..7dc7c8b 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,8 @@ can be 100% safe.
 cxx = "0.2"
 ```
 
-*Compiler support: requires rustc 1.42+*
+*Compiler support: requires rustc 1.42+*<br>
+*[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
 

From 2bd1312f2f1b942c671b20769c9f247b35cc1ef1 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 28 2020 17:14:41 +0000
Subject: [PATCH 477/2232] Disallow passing a reference to a reference.


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0c75de8..a90db49 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -230,6 +230,11 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 );
             }
         }
+        if let Type::Ref(ity) = &arg.ty {
+            if let Type::Ref(_) = &ity.inner {
+                cx.error(arg, "Passing a reference to a reference is not supported");
+            }
+        }
     }
 
     if let Some(ty) = &efn.ret {
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
new file mode 100644
index 0000000..526d036
--- /dev/null
+++ b/tests/ui/reference_to_reference.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type ThingC;
+        fn repro_c(t: &&ThingC);
+    }
+    extern "Rust" {
+        type ThingR;
+        fn repro_r(t: &&ThingR);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/reference_to_reference.stderr b/tests/ui/reference_to_reference.stderr
new file mode 100644
index 0000000..5b3eadc
--- /dev/null
+++ b/tests/ui/reference_to_reference.stderr
@@ -0,0 +1,11 @@
+error: Passing a reference to a reference is not supported
+ --> $DIR/reference_to_reference.rs:5:20
+  |
+5 |         fn repro_c(t: &&ThingC);
+  |                    ^^^^^^^^^^^
+
+error: Passing a reference to a reference is not supported
+ --> $DIR/reference_to_reference.rs:9:20
+  |
+9 |         fn repro_r(t: &&ThingR);
+  |                    ^^^^^^^^^^^

From f6a7167ea99d85cb691bfcb543271931a6111d85 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 19:32:01 +0000
Subject: [PATCH 478/2232] Merge pull request #162 from jgalenson/refref


Disallow passing a reference to a reference.
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0c75de8..a90db49 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -230,6 +230,11 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 );
             }
         }
+        if let Type::Ref(ity) = &arg.ty {
+            if let Type::Ref(_) = &ity.inner {
+                cx.error(arg, "Passing a reference to a reference is not supported");
+            }
+        }
     }
 
     if let Some(ty) = &efn.ret {
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
new file mode 100644
index 0000000..526d036
--- /dev/null
+++ b/tests/ui/reference_to_reference.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        type ThingC;
+        fn repro_c(t: &&ThingC);
+    }
+    extern "Rust" {
+        type ThingR;
+        fn repro_r(t: &&ThingR);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/reference_to_reference.stderr b/tests/ui/reference_to_reference.stderr
new file mode 100644
index 0000000..5b3eadc
--- /dev/null
+++ b/tests/ui/reference_to_reference.stderr
@@ -0,0 +1,11 @@
+error: Passing a reference to a reference is not supported
+ --> $DIR/reference_to_reference.rs:5:20
+  |
+5 |         fn repro_c(t: &&ThingC);
+  |                    ^^^^^^^^^^^
+
+error: Passing a reference to a reference is not supported
+ --> $DIR/reference_to_reference.rs:9:20
+  |
+9 |         fn repro_r(t: &&ThingR);
+  |                    ^^^^^^^^^^^

From 776fd8953dbafa9b06a333540fb51fce91a3de94 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 28 2020 20:38:28 +0000
Subject: [PATCH 479/2232] Generalize reference-to-reference check to cover all positions


Checking this in check_type_ref allows it to apply anywhere that a
reference is written, such as return position which was not covered by
the previous logic.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index a90db49..3e121b5 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -151,6 +151,10 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 
     match ty.inner {
         Type::Fn(_) | Type::Void(_) => {}
+        Type::Ref(_) => {
+            cx.error(ty, "C++ does not allow references to references");
+            return;
+        }
         _ => return,
     }
 
@@ -230,11 +234,6 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 );
             }
         }
-        if let Type::Ref(ity) = &arg.ty {
-            if let Type::Ref(_) = &ity.inner {
-                cx.error(arg, "Passing a reference to a reference is not supported");
-            }
-        }
     }
 
     if let Some(ty) = &efn.ret {
diff --git a/tests/ui/reference_to_reference.stderr b/tests/ui/reference_to_reference.stderr
index 5b3eadc..d4069c1 100644
--- a/tests/ui/reference_to_reference.stderr
+++ b/tests/ui/reference_to_reference.stderr
@@ -1,11 +1,11 @@
-error: Passing a reference to a reference is not supported
- --> $DIR/reference_to_reference.rs:5:20
+error: C++ does not allow references to references
+ --> $DIR/reference_to_reference.rs:5:23
   |
 5 |         fn repro_c(t: &&ThingC);
-  |                    ^^^^^^^^^^^
+  |                       ^^^^^^^^
 
-error: Passing a reference to a reference is not supported
- --> $DIR/reference_to_reference.rs:9:20
+error: C++ does not allow references to references
+ --> $DIR/reference_to_reference.rs:9:23
   |
 9 |         fn repro_r(t: &&ThingR);
-  |                    ^^^^^^^^^^^
+  |                       ^^^^^^^^

From da9be50ad868b4ba367e6197a9fc81499303fc76 Mon Sep 17 00:00:00 2001
From: myronahn <myronahn@gmail.com>
Date: Apr 28 2020 22:47:23 +0000
Subject: [PATCH 480/2232] Add all std::iterator_traits required types to const_iterator of rust::Vec<T> (#157)


https://en.cppreference.com/w/cpp/iterator/iterator_traits

`std::iterator_traits` requires the following 5 types:

- `difference_type` - a signed integer type that can be used to identify distance between iterators
- `value_type` - the type of the values that can be obtained by dereferencing the iterator. This type is void for output iterators.
- `pointer` - defines a pointer to the type iterated over (value_type)
- `reference` - defines a reference to the type iterated over (value_type)
- `iterator_category` - the category of the iterator. Must be one of iterator category tags.

The current `const_iterator` for `rust::Vec<T>` only defined `value_type` and `reference` which caused an error when using `std::copy` on gcc 7.5.0 on Ubuntu but seemed to work fine on MacOS.
---

diff --git a/include/cxx.h b/include/cxx.h
index c02d3d9..1e33618 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -235,15 +235,25 @@ public:
 
   class const_iterator {
   public:
+    using difference_type = ptrdiff_t;
     using value_type = typename std::add_const<T>::type;
+    using pointer = typename std::add_pointer<
+        typename std::add_const<T>::type>::type;
     using reference = typename std::add_lvalue_reference<
         typename std::add_const<T>::type>::type;
+    using iterator_category = std::forward_iterator_tag;
 
     const T &operator*() const { return *static_cast<const T *>(this->pos); }
+    const T *operator->() const { return static_cast<const T *>(this->pos); }
     const_iterator &operator++() {
       this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
       return *this;
     }
+    const_iterator operator++(int) {
+      auto ret = const_iterator(*this);
+      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+      return ret;
+    }
     bool operator==(const const_iterator &other) const {
       return this->pos == other.pos;
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 69ef2b0..01dc404 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -53,7 +53,9 @@ pub mod ffi {
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
         fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
+        fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         fn c_take_callback(callback: fn(String) -> usize);
 
         fn c_try_return_void() -> Result<()>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 79db42c..2b5431f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -203,6 +203,18 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
+  // Exercise requirements of ForwardIterator
+  // https://en.cppreference.com/w/cpp/named_req/ForwardIterator
+  uint32_t sum = 0;
+  for (auto it = v.begin(), it_end = v.end(); it != it_end; it++) {
+    sum += it->z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
@@ -210,6 +222,18 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   }
 }
 
+void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
+  // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
+  // requirements for std::iterator_traits.
+  // https://en.cppreference.com/w/cpp/iterator/iterator_traits
+  std::vector<uint8_t> cxx_v;
+  std::copy(v.begin(), v.end(), back_inserter(cxx_v));
+  uint8_t sum = std::accumulate(cxx_v.begin(), cxx_v.end(), 0);
+  if (sum == 200) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 4600d64..da8ca56 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -57,7 +57,9 @@ void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 
 void c_try_return_void();
diff --git a/tests/test.rs b/tests/test.rs
index 4fd52d3..d6850aa 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -94,14 +94,18 @@ fn test_c_take() {
         ffi::c_return_unique_ptr_vector_shared()
     ));
     check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
-    check!(ffi::c_take_rust_vec([86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
+    let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
+    check!(ffi::c_take_rust_vec(test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared(vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
     ]));
-    check!(ffi::c_take_ref_rust_vec(
-        &[86_u8, 75_u8, 30_u8, 9_u8].to_vec()
-    ));
+    check!(ffi::c_take_rust_vec_shared_forward_iterator(vec![
+        ffi::Shared { z: 1010 },
+        ffi::Shared { z: 1011 }
+    ]));
+    check!(ffi::c_take_ref_rust_vec(&test_vec));
+    check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
 }
 
 #[test]

From 6ba5ccf4c34e78af21684500515d91eeb86b6cbc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 29 2020 23:33:19 +0000
Subject: [PATCH 481/2232] Remove cargo author var from BUCK target


This was made unnecessary by 7f635f360e279d3c3a00f78a8911cca32d90991a.

---

diff --git a/BUCK b/BUCK
index 50a9048..40aeea6 100644
--- a/BUCK
+++ b/BUCK
@@ -19,9 +19,6 @@ rust_binary(
     name = "codegen",
     srcs = glob(["cmd/src/**"]),
     visibility = ["PUBLIC"],
-    env = {
-        "CARGO_PKG_AUTHORS": "David Tolnay <dtolnay@gmail.com>",
-    },
     deps = [
         "//third-party:anyhow",
         "//third-party:codespan-reporting",

From 1f5670249047033796d6840255113e18b385d1e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 29 2020 23:38:36 +0000
Subject: [PATCH 482/2232] Set binary name for buck-built codegen cli


---

diff --git a/BUCK b/BUCK
index 40aeea6..6a9870e 100644
--- a/BUCK
+++ b/BUCK
@@ -18,6 +18,7 @@ rust_library(
 rust_binary(
     name = "codegen",
     srcs = glob(["cmd/src/**"]),
+    crate = "cxxbridge",
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:anyhow",

From f8ed07327b5217c3e63b44597dc026f95156bdbd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:23:14 +0000
Subject: [PATCH 483/2232] Split cxx runtime and build components


---

diff --git a/.travis.yml b/.travis.yml
index 6c0ca54..f65f7f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,15 +20,15 @@ matrix:
       rust: nightly-x86_64-pc-windows-gnu
       before_script:
         # windows is bad at symlinks
-        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
-        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
+        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
 
     - name: Windows (msvc)
       os: windows
       rust: nightly-x86_64-pc-windows-msvc
       before_script:
-        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
-        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
+        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
 
     - name: Buck
       rust: nightly
diff --git a/BUCK b/BUCK
index 6a9870e..2339f71 100644
--- a/BUCK
+++ b/BUCK
@@ -5,19 +5,13 @@ rust_library(
     deps = [
         ":core",
         ":macro",
-        "//third-party:anyhow",
-        "//third-party:cc",
-        "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
-        "//third-party:proc-macro2",
-        "//third-party:quote",
-        "//third-party:syn",
     ],
 )
 
 rust_binary(
     name = "codegen",
-    srcs = glob(["cmd/src/**"]),
+    srcs = glob(["gen/cmd/src/**"]),
     crate = "cxxbridge",
     visibility = ["PUBLIC"],
     deps = [
@@ -52,3 +46,17 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "build",
+    srcs = glob(["gen/build/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/BUILD b/BUILD
index 2eea8c7..d63fea7 100644
--- a/BUILD
+++ b/BUILD
@@ -3,25 +3,18 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
-    data = ["src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
         ":cxxbridge-macro",
-        "//third-party:anyhow",
-        "//third-party:cc",
-        "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
-        "//third-party:proc-macro2",
-        "//third-party:quote",
-        "//third-party:syn",
     ],
 )
 
 rust_binary(
     name = "codegen",
-    srcs = glob(["cmd/src/**/*.rs"]),
-    data = ["cmd/src/gen/include/cxx.h"],
+    srcs = glob(["gen/cmd/src/**/*.rs"]),
+    data = ["gen/cmd/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
@@ -57,3 +50,18 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "build",
+    srcs = glob(["gen/build/src/**/*.rs"]),
+    data = ["gen/build/src/gen/include/cxx.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/Cargo.toml b/Cargo.toml
index a47a842..ea97712 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,25 +15,20 @@ exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 travis-ci = { repository = "dtolnay/cxx" }
 
 [dependencies]
-anyhow = "1.0"
-cc = "1.0.49"
-codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.12", path = "macro" }
 link-cplusplus = "1.0"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
+cxx-build = { version = "=0.2.12", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.21", features = ["diff"] }
 
 [workspace]
-members = ["cmd", "demo-rs", "macro", "tests/ffi"]
+members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/README.md b/README.md
index 7dc7c8b..59bcdac 100644
--- a/README.md
+++ b/README.md
@@ -219,8 +219,7 @@ set up any additional source files and compiler flags as normal.
 // build.rs
 
 fn main() {
-    cxx::Build::new()
-        .bridge("src/main.rs")  // returns a cc::Build
+    cxx_build::bridge("src/main.rs")  // returns a cc::Build
         .file("../demo-cxx/demo.cc")
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
deleted file mode 100644
index 742d54b..0000000
--- a/cmd/Cargo.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-[package]
-name = "cxxbridge-cmd"
-version = "0.2.12"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-license = "MIT OR Apache-2.0"
-description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
-repository = "https://github.com/dtolnay/cxx"
-
-[[bin]]
-name = "cxxbridge"
-path = "src/main.rs"
-
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
-[dependencies]
-anyhow = "1.0"
-codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
-quote = "1.0"
-structopt = "0.3"
-syn = { version = "1.0", features = ["full"] }
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/cmd/LICENSE-APACHE b/cmd/LICENSE-APACHE
deleted file mode 120000
index 965b606..0000000
--- a/cmd/LICENSE-APACHE
+++ /dev/null
@@ -1 +0,0 @@
-../LICENSE-APACHE
\ No newline at end of file
diff --git a/cmd/LICENSE-MIT b/cmd/LICENSE-MIT
deleted file mode 120000
index 76219eb..0000000
--- a/cmd/LICENSE-MIT
+++ /dev/null
@@ -1 +0,0 @@
-../LICENSE-MIT
\ No newline at end of file
diff --git a/cmd/src/gen b/cmd/src/gen
deleted file mode 120000
index eb22577..0000000
--- a/cmd/src/gen
+++ /dev/null
@@ -1 +0,0 @@
-../../gen
\ No newline at end of file
diff --git a/cmd/src/lib.rs b/cmd/src/lib.rs
deleted file mode 100644
index 8b1a393..0000000
--- a/cmd/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-// empty
diff --git a/cmd/src/main.rs b/cmd/src/main.rs
deleted file mode 100644
index a20179f..0000000
--- a/cmd/src/main.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-#![allow(
-    clippy::cognitive_complexity,
-    clippy::inherent_to_string,
-    clippy::large_enum_variant,
-    clippy::new_without_default,
-    clippy::toplevel_ref_arg
-)]
-
-mod gen;
-mod syntax;
-
-use gen::include;
-use std::io::{self, Write};
-use std::path::PathBuf;
-use structopt::StructOpt;
-
-#[derive(StructOpt, Debug)]
-#[structopt(
-    name = "cxxbridge",
-    author = "David Tolnay <dtolnay@gmail.com>",
-    about = "https://github.com/dtolnay/cxx",
-    usage = "\
-    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
-    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout",
-    help_message = "Print help information",
-    version_message = "Print version information"
-)]
-struct Opt {
-    /// Input Rust source file containing #[cxx::bridge]
-    #[structopt(parse(from_os_str), required_unless = "header")]
-    input: Option<PathBuf>,
-
-    /// Emit header with declarations only
-    #[structopt(long)]
-    header: bool,
-
-    /// Any additional headers to #include
-    #[structopt(short, long)]
-    include: Vec<String>,
-}
-
-fn write(content: impl AsRef<[u8]>) {
-    let _ = io::stdout().lock().write_all(content.as_ref());
-}
-
-fn main() {
-    let opt = Opt::from_args();
-
-    let gen = gen::Opt {
-        include: opt.include,
-    };
-
-    match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
-        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
-        (None, true) => write(include::HEADER),
-        (None, false) => unreachable!(), // enforced by required_unless
-    }
-}
diff --git a/cmd/src/syntax b/cmd/src/syntax
deleted file mode 120000
index 83b0080..0000000
--- a/cmd/src/syntax
+++ /dev/null
@@ -1 +0,0 @@
-../../syntax
\ No newline at end of file
diff --git a/demo-rs/Cargo.toml b/demo-rs/Cargo.toml
index f7e7f84..d2147ab 100644
--- a/demo-rs/Cargo.toml
+++ b/demo-rs/Cargo.toml
@@ -9,4 +9,4 @@ publish = false
 cxx = { path = ".." }
 
 [build-dependencies]
-cxx = { path = ".." }
+cxx-build = { path = "../gen/build" }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index 71def71..edbb281 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,6 +1,5 @@
 fn main() {
-    cxx::Build::new()
-        .bridge("src/main.rs")
+    cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
diff --git a/gen/README.md b/gen/README.md
new file mode 100644
index 0000000..9786911
--- /dev/null
+++ b/gen/README.md
@@ -0,0 +1,4 @@
+This directory contains CXX's C++ code generator. This code generator has two
+public frontends, one a command-line application (binary) in the *cmd* directory
+and the other a library intended to be used from a build.rs in the *build*
+directory.
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
new file mode 100644
index 0000000..3552524
--- /dev/null
+++ b/gen/build/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "cxx-build"
+version = "0.2.12"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into a Cargo build."
+repository = "https://github.com/dtolnay/cxx"
+
+[badges]
+travis-ci = { repository = "dtolnay/cxx" }
+
+[dependencies]
+anyhow = "1.0"
+cc = "1.0.49"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0", features = ["span-locations"] }
+quote = "1.0"
+syn = { version = "1.0", features = ["full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/build/LICENSE-APACHE b/gen/build/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/build/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/build/LICENSE-MIT b/gen/build/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/build/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
new file mode 100644
index 0000000..740ab94
--- /dev/null
+++ b/gen/build/src/error.rs
@@ -0,0 +1,37 @@
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+
+pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub(super) enum Error {
+    MissingOutDir,
+    TargetDir,
+    Io(io::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
+            Error::TargetDir => write!(f, "failed to locate target dir"),
+            Error::Io(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
+}
diff --git a/gen/build/src/gen b/gen/build/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/build/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
new file mode 100644
index 0000000..5bee67f
--- /dev/null
+++ b/gen/build/src/lib.rs
@@ -0,0 +1,96 @@
+//! The CXX code generator for constructing and compiling C++ code.
+//!
+//! This is intended to be used from Cargo build scripts to execute CXX's
+//! C++ code generator, set up any additional compiler flags depending on
+//! the use case, and make the C++ compiler invocation.
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! Example of a canonical Cargo build script that builds a CXX bridge:
+//!
+//! ```no_run
+//! // build.rs
+//!
+//! fn main() {
+//!     cxx_build::bridge("src/main.rs")
+//!         .file("../demo-cxx/demo.cc")
+//!         .flag("-std=c++11")
+//!         .compile("cxxbridge-demo");
+//!
+//!     println!("cargo:rerun-if-changed=src/main.rs");
+//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
+//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//! }
+//! ```
+//!
+//! A runnable working setup with this build script is shown in the
+//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
+//!
+//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
+//!
+//! <br>
+//!
+//! # Alternatives
+//!
+//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
+//! alternate way of invoking the C++ code generator as a standalone command
+//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
+//!
+//! ```bash
+//! $ cargo install cxxbridge-cmd  # or build it from the repo
+//!
+//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
+//! $ cxxbridge src/main.rs > path/to/mybridge.cc
+//! ```
+
+mod error;
+mod gen;
+mod paths;
+mod syntax;
+
+use crate::error::Result;
+use crate::gen::Opt;
+use anyhow::anyhow;
+use std::fs;
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+/// This returns a [`cc::Build`] on which you should continue to set up any
+/// additional source files or compiler flags, and lastly call its [`compile`]
+/// method to execute the C++ build.
+///
+/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
+#[must_use]
+pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
+    match try_generate_bridge(rust_source_file.as_ref()) {
+        Ok(build) => build,
+        Err(err) => {
+            let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
+            process::exit(1);
+        }
+    }
+}
+
+fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
+    let header = gen::do_generate_header(rust_source_file, Opt::default());
+    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
+    fs::create_dir_all(header_path.parent().unwrap())?;
+    fs::write(&header_path, header)?;
+    paths::symlink_header(&header_path, rust_source_file);
+
+    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
+    let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
+    fs::write(&bridge_path, bridge)?;
+    let mut build = paths::cc_build();
+    build.file(&bridge_path);
+
+    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
+    let _ = fs::remove_file(cxx_h);
+    let _ = fs::write(cxx_h, gen::include::HEADER);
+
+    Ok(build)
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
new file mode 100644
index 0000000..ca183d9
--- /dev/null
+++ b/gen/build/src/paths.rs
@@ -0,0 +1,116 @@
+use crate::error::{Error, Result};
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+fn out_dir() -> Result<PathBuf> {
+    env::var_os("OUT_DIR")
+        .map(PathBuf::from)
+        .ok_or(Error::MissingOutDir)
+}
+
+pub(crate) fn cc_build() -> cc::Build {
+    try_cc_build().unwrap_or_default()
+}
+
+fn try_cc_build() -> Result<cc::Build> {
+    let mut build = cc::Build::new();
+    build.include(include_dir()?);
+    build.include(target_dir()?.parent().unwrap());
+    Ok(build)
+}
+
+// Symlink the header file into a predictable place. The header generated from
+// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
+pub(crate) fn symlink_header(path: &Path, original: &Path) {
+    let _ = try_symlink_header(path, original);
+}
+
+fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
+    let suffix = relative_to_parent_of_target_dir(original)?;
+    let ref dst = include_dir()?.join(suffix);
+
+    fs::create_dir_all(dst.parent().unwrap())?;
+    let _ = fs::remove_file(dst);
+    symlink_or_copy(path, dst)?;
+
+    let mut file_name = dst.file_name().unwrap().to_os_string();
+    file_name.push(".h");
+    let ref dst2 = dst.with_file_name(file_name);
+    symlink_or_copy(path, dst2)?;
+
+    Ok(())
+}
+
+fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
+    let target_dir = target_dir()?;
+    let mut outer = target_dir.parent().unwrap();
+    let original = canonicalize(original)?;
+    loop {
+        if let Ok(suffix) = original.strip_prefix(outer) {
+            return Ok(suffix.to_owned());
+        }
+        match outer.parent() {
+            Some(parent) => outer = parent,
+            None => return Ok(original.components().skip(1).collect()),
+        }
+    }
+}
+
+pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
+    let mut file_name = path.file_name().unwrap().to_owned();
+    file_name.push(ext);
+
+    let out_dir = out_dir()?;
+    let rel = relative_to_parent_of_target_dir(path)?;
+    Ok(out_dir.join(rel).with_file_name(file_name))
+}
+
+pub(crate) fn include_dir() -> Result<PathBuf> {
+    let target_dir = target_dir()?;
+    Ok(target_dir.join("cxxbridge"))
+}
+
+fn target_dir() -> Result<PathBuf> {
+    let mut dir = out_dir().and_then(canonicalize)?;
+    loop {
+        if dir.ends_with("target") {
+            return Ok(dir);
+        }
+        if !dir.pop() {
+            return Err(Error::TargetDir);
+        }
+    }
+}
+
+#[cfg(not(windows))]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    Ok(fs::canonicalize(path)?)
+}
+
+#[cfg(windows)]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
+    // unable to handle in includes. Use a poor approximation instead.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    Ok(env::current_dir()?.join(path))
+}
+
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_or_copy;
+
+#[cfg(windows)]
+fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+    use std::os::windows::fs::symlink_file;
+
+    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
+    // require Developer Mode. If it fails, fall back to copying the file.
+    if symlink_file(src, dst).is_err() {
+        fs::copy(src, dst)?;
+    }
+    Ok(())
+}
+
+#[cfg(not(any(unix, windows)))]
+use std::fs::copy as symlink_or_copy;
diff --git a/gen/build/src/syntax b/gen/build/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/build/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
new file mode 100644
index 0000000..742d54b
--- /dev/null
+++ b/gen/cmd/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "cxxbridge-cmd"
+version = "0.2.12"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
+repository = "https://github.com/dtolnay/cxx"
+
+[[bin]]
+name = "cxxbridge"
+path = "src/main.rs"
+
+[badges]
+travis-ci = { repository = "dtolnay/cxx" }
+
+[dependencies]
+anyhow = "1.0"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0", features = ["span-locations"] }
+quote = "1.0"
+structopt = "0.3"
+syn = { version = "1.0", features = ["full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/LICENSE-APACHE b/gen/cmd/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/cmd/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/cmd/LICENSE-MIT b/gen/cmd/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/cmd/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/cmd/src/gen b/gen/cmd/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/cmd/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/cmd/src/lib.rs b/gen/cmd/src/lib.rs
new file mode 100644
index 0000000..8b1a393
--- /dev/null
+++ b/gen/cmd/src/lib.rs
@@ -0,0 +1 @@
+// empty
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
new file mode 100644
index 0000000..a20179f
--- /dev/null
+++ b/gen/cmd/src/main.rs
@@ -0,0 +1,60 @@
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::inherent_to_string,
+    clippy::large_enum_variant,
+    clippy::new_without_default,
+    clippy::toplevel_ref_arg
+)]
+
+mod gen;
+mod syntax;
+
+use gen::include;
+use std::io::{self, Write};
+use std::path::PathBuf;
+use structopt::StructOpt;
+
+#[derive(StructOpt, Debug)]
+#[structopt(
+    name = "cxxbridge",
+    author = "David Tolnay <dtolnay@gmail.com>",
+    about = "https://github.com/dtolnay/cxx",
+    usage = "\
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit rust/cxx.h header to stdout",
+    help_message = "Print help information",
+    version_message = "Print version information"
+)]
+struct Opt {
+    /// Input Rust source file containing #[cxx::bridge]
+    #[structopt(parse(from_os_str), required_unless = "header")]
+    input: Option<PathBuf>,
+
+    /// Emit header with declarations only
+    #[structopt(long)]
+    header: bool,
+
+    /// Any additional headers to #include
+    #[structopt(short, long)]
+    include: Vec<String>,
+}
+
+fn write(content: impl AsRef<[u8]>) {
+    let _ = io::stdout().lock().write_all(content.as_ref());
+}
+
+fn main() {
+    let opt = Opt::from_args();
+
+    let gen = gen::Opt {
+        include: opt.include,
+    };
+
+    match (opt.input, opt.header) {
+        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
+        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
+        (None, true) => write(include::HEADER),
+        (None, false) => unreachable!(), // enforced by required_unless
+    }
+}
diff --git a/gen/cmd/src/syntax b/gen/cmd/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/cmd/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/error.rs b/gen/error.rs
deleted file mode 100644
index 2e8ecc4..0000000
--- a/gen/error.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use crate::syntax;
-use anyhow::anyhow;
-use codespan_reporting::diagnostic::{Diagnostic, Label};
-use codespan_reporting::files::SimpleFiles;
-use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
-use codespan_reporting::term::{self, Config};
-use std::error::Error as StdError;
-use std::fmt::{self, Display};
-use std::io::{self, Write};
-use std::ops::Range;
-use std::path::Path;
-use std::process;
-
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
-
-#[derive(Debug)]
-pub(super) enum Error {
-    NoBridgeMod,
-    OutOfLineMod,
-    Io(io::Error),
-    Syn(syn::Error),
-}
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
-            Error::Io(err) => err.fmt(f),
-            Error::Syn(err) => err.fmt(f),
-        }
-    }
-}
-
-impl StdError for Error {
-    fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        match self {
-            Error::Io(err) => Some(err),
-            Error::Syn(err) => Some(err),
-            _ => None,
-        }
-    }
-}
-
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
-    }
-}
-
-impl From<syn::Error> for Error {
-    fn from(err: syn::Error) -> Self {
-        Error::Syn(err)
-    }
-}
-
-pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
-    match error {
-        Error::Syn(syn_error) => {
-            let writer = StandardStream::stderr(ColorChoice::Auto);
-            let ref mut stderr = writer.lock();
-            for error in syn_error {
-                let _ = writeln!(stderr);
-                display_syn_error(stderr, path, source, error);
-            }
-        }
-        _ => eprintln!("cxxbridge: {:?}", anyhow!(error)),
-    }
-    process::exit(1);
-}
-
-fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
-    let span = error.span();
-    let start = span.start();
-    let end = span.end();
-
-    let mut start_offset = 0;
-    for _ in 1..start.line {
-        start_offset += source[start_offset..].find('\n').unwrap() + 1;
-    }
-    start_offset += start.column;
-
-    let mut end_offset = start_offset;
-    if start.line == end.line {
-        end_offset -= start.column;
-    } else {
-        for _ in 0..end.line - start.line {
-            end_offset += source[end_offset..].find('\n').unwrap() + 1;
-        }
-    }
-    end_offset += end.column;
-
-    let mut files = SimpleFiles::new();
-    let file = files.add(path.to_string_lossy(), source);
-
-    let diagnostic = diagnose(file, start_offset..end_offset, error);
-
-    let config = Config::default();
-    let _ = term::emit(stderr, &config, &files, &diagnostic);
-}
-
-fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
-    let message = error.to_string();
-    let info = syntax::error::ERRORS
-        .iter()
-        .find(|e| message.contains(e.msg));
-    let mut diagnostic = Diagnostic::error().with_message(&message);
-    let mut label = Label::primary(file, range);
-    if let Some(info) = info {
-        label.message = info.label.map_or(message, str::to_owned);
-        diagnostic.labels.push(label);
-        diagnostic.notes.extend(info.note.map(str::to_owned));
-    } else {
-        label.message = message;
-        diagnostic.labels.push(label);
-    }
-    diagnostic.code = Some("cxxbridge".to_owned());
-    diagnostic
-}
diff --git a/gen/include b/gen/include
deleted file mode 120000
index f5030fe..0000000
--- a/gen/include
+++ /dev/null
@@ -1 +0,0 @@
-../include
\ No newline at end of file
diff --git a/gen/include.rs b/gen/include.rs
deleted file mode 100644
index 129a8e6..0000000
--- a/gen/include.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-use std::fmt::{self, Display};
-
-pub static HEADER: &str = include_str!("include/cxx.h");
-
-pub fn get(guard: &str) -> &'static str {
-    let ifndef = format!("#ifndef {}", guard);
-    let endif = format!("#endif // {}", guard);
-    let begin = find_line(&ifndef);
-    let end = find_line(&endif);
-    if let (Some(begin), Some(end)) = (begin, end) {
-        &HEADER[begin..end + endif.len()]
-    } else {
-        panic!("not found in cxx.h header: {}", guard)
-    }
-}
-
-fn find_line(line: &str) -> Option<usize> {
-    let mut offset = 0;
-    loop {
-        offset += HEADER[offset..].find(line)?;
-        let rest = &HEADER[offset + line.len()..];
-        if rest.starts_with('\n') || rest.starts_with('\r') {
-            return Some(offset);
-        }
-        offset += line.len();
-    }
-}
-
-#[derive(Default, PartialEq)]
-pub struct Includes {
-    custom: Vec<String>,
-    pub array: bool,
-    pub cstddef: bool,
-    pub cstdint: bool,
-    pub cstring: bool,
-    pub exception: bool,
-    pub memory: bool,
-    pub string: bool,
-    pub type_traits: bool,
-    pub utility: bool,
-    pub vector: bool,
-    pub base_tsd: bool,
-}
-
-impl Includes {
-    pub fn new() -> Self {
-        Includes::default()
-    }
-
-    pub fn insert(&mut self, include: String) {
-        self.custom.push(include);
-    }
-}
-
-impl Extend<String> for Includes {
-    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
-        self.custom.extend(iter);
-    }
-}
-
-impl Display for Includes {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for include in &self.custom {
-            writeln!(f, "#include \"{}\"", include.escape_default())?;
-        }
-        if self.array {
-            writeln!(f, "#include <array>")?;
-        }
-        if self.cstddef {
-            writeln!(f, "#include <cstddef>")?;
-        }
-        if self.cstdint {
-            writeln!(f, "#include <cstdint>")?;
-        }
-        if self.cstring {
-            writeln!(f, "#include <cstring>")?;
-        }
-        if self.exception {
-            writeln!(f, "#include <exception>")?;
-        }
-        if self.memory {
-            writeln!(f, "#include <memory>")?;
-        }
-        if self.string {
-            writeln!(f, "#include <string>")?;
-        }
-        if self.type_traits {
-            writeln!(f, "#include <type_traits>")?;
-        }
-        if self.utility {
-            writeln!(f, "#include <utility>")?;
-        }
-        if self.vector {
-            writeln!(f, "#include <vector>")?;
-        }
-        if self.base_tsd {
-            writeln!(f, "#if defined(_WIN32)")?;
-            writeln!(f, "#include <BaseTsd.h>")?;
-            writeln!(f, "#endif")?;
-        }
-        if *self != Self::default() {
-            writeln!(f)?;
-        }
-        Ok(())
-    }
-}
diff --git a/gen/mod.rs b/gen/mod.rs
deleted file mode 100644
index 928c6ec..0000000
--- a/gen/mod.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Functionality that is shared between the cxx::generate_bridge entry point and
-// the cmd.
-
-mod error;
-pub(super) mod include;
-pub(super) mod out;
-mod write;
-
-use self::error::{format_err, Error, Result};
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{self, check, Types};
-use quote::quote;
-use std::fs;
-use std::path::Path;
-use syn::{Attribute, File, Item};
-
-struct Input {
-    namespace: Namespace,
-    module: Vec<Item>,
-}
-
-#[derive(Default)]
-pub(super) struct Opt {
-    /// Any additional headers to #include
-    pub include: Vec<String>,
-}
-
-pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
-    let header = false;
-    generate(path, opt, header)
-}
-
-pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
-    let header = true;
-    generate(path, opt, header)
-}
-
-fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
-    let source = match fs::read_to_string(path) {
-        Ok(source) => source,
-        Err(err) => format_err(path, "", Error::Io(err)),
-    };
-    match (|| -> Result<_> {
-        let syntax = syn::parse_file(&source)?;
-        let bridge = find_bridge_mod(syntax)?;
-        let apis = syntax::parse_items(bridge.module)?;
-        let types = Types::collect(&apis)?;
-        check::typecheck(&apis, &types)?;
-        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
-        Ok(out)
-    })() {
-        Ok(out) => out.content(),
-        Err(err) => format_err(path, &source, err),
-    }
-}
-
-fn find_bridge_mod(syntax: File) -> Result<Input> {
-    for item in syntax.items {
-        if let Item::Mod(item) = item {
-            for attr in &item.attrs {
-                let path = &attr.path;
-                if quote!(#path).to_string() == "cxx :: bridge" {
-                    let module = match item.content {
-                        Some(module) => module.1,
-                        None => {
-                            return Err(Error::Syn(syn::Error::new_spanned(
-                                item,
-                                Error::OutOfLineMod,
-                            )));
-                        }
-                    };
-                    let namespace = parse_args(attr)?;
-                    return Ok(Input { namespace, module });
-                }
-            }
-        }
-    }
-    Err(Error::NoBridgeMod)
-}
-
-fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
-    if attr.tokens.is_empty() {
-        Ok(Namespace::none())
-    } else {
-        attr.parse_args()
-    }
-}
diff --git a/gen/out.rs b/gen/out.rs
deleted file mode 100644
index 08bf85f..0000000
--- a/gen/out.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use crate::gen::include::Includes;
-use crate::syntax::namespace::Namespace;
-use std::cell::RefCell;
-use std::fmt::{self, Arguments, Write};
-
-pub(crate) struct OutFile {
-    pub namespace: Namespace,
-    pub header: bool,
-    pub include: Includes,
-    content: RefCell<Content>,
-}
-
-struct Content {
-    bytes: Vec<u8>,
-    section_pending: bool,
-    blocks_pending: Vec<&'static str>,
-}
-
-impl OutFile {
-    pub fn new(namespace: Namespace, header: bool) -> Self {
-        OutFile {
-            namespace,
-            header,
-            include: Includes::new(),
-            content: RefCell::new(Content {
-                bytes: Vec::new(),
-                section_pending: false,
-                blocks_pending: Vec::new(),
-            }),
-        }
-    }
-
-    // Write a blank line if the preceding section had any contents.
-    pub fn next_section(&mut self) {
-        let content = self.content.get_mut();
-        content.section_pending = true;
-    }
-
-    pub fn begin_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        content.blocks_pending.push(block);
-    }
-
-    pub fn end_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        if content.blocks_pending.pop().is_none() {
-            content.bytes.extend_from_slice(b"} // ");
-            content.bytes.extend_from_slice(block.as_bytes());
-            content.bytes.push(b'\n');
-            content.section_pending = true;
-        }
-    }
-
-    pub fn prepend(&mut self, section: String) {
-        let content = self.content.get_mut();
-        content.bytes.splice(..0, section.into_bytes());
-    }
-
-    pub fn write_fmt(&self, args: Arguments) {
-        let content = &mut *self.content.borrow_mut();
-        Write::write_fmt(content, args).unwrap();
-    }
-
-    pub fn content(&self) -> Vec<u8> {
-        self.content.borrow().bytes.clone()
-    }
-}
-
-impl Write for Content {
-    fn write_str(&mut self, s: &str) -> fmt::Result {
-        if !s.is_empty() {
-            if !self.blocks_pending.is_empty() {
-                if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
-                }
-                for block in self.blocks_pending.drain(..) {
-                    self.bytes.extend_from_slice(block.as_bytes());
-                    self.bytes.extend_from_slice(b" {\n");
-                }
-                self.section_pending = false;
-            } else if self.section_pending {
-                if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
-                }
-                self.section_pending = false;
-            }
-            self.bytes.extend_from_slice(s.as_bytes());
-        }
-        Ok(())
-    }
-}
diff --git a/gen/src/error.rs b/gen/src/error.rs
new file mode 100644
index 0000000..2e8ecc4
--- /dev/null
+++ b/gen/src/error.rs
@@ -0,0 +1,119 @@
+use crate::syntax;
+use anyhow::anyhow;
+use codespan_reporting::diagnostic::{Diagnostic, Label};
+use codespan_reporting::files::SimpleFiles;
+use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
+use codespan_reporting::term::{self, Config};
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io::{self, Write};
+use std::ops::Range;
+use std::path::Path;
+use std::process;
+
+pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub(super) enum Error {
+    NoBridgeMod,
+    OutOfLineMod,
+    Io(io::Error),
+    Syn(syn::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
+            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
+            Error::Io(err) => err.fmt(f),
+            Error::Syn(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            Error::Syn(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
+}
+
+impl From<syn::Error> for Error {
+    fn from(err: syn::Error) -> Self {
+        Error::Syn(err)
+    }
+}
+
+pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
+    match error {
+        Error::Syn(syn_error) => {
+            let writer = StandardStream::stderr(ColorChoice::Auto);
+            let ref mut stderr = writer.lock();
+            for error in syn_error {
+                let _ = writeln!(stderr);
+                display_syn_error(stderr, path, source, error);
+            }
+        }
+        _ => eprintln!("cxxbridge: {:?}", anyhow!(error)),
+    }
+    process::exit(1);
+}
+
+fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
+    let span = error.span();
+    let start = span.start();
+    let end = span.end();
+
+    let mut start_offset = 0;
+    for _ in 1..start.line {
+        start_offset += source[start_offset..].find('\n').unwrap() + 1;
+    }
+    start_offset += start.column;
+
+    let mut end_offset = start_offset;
+    if start.line == end.line {
+        end_offset -= start.column;
+    } else {
+        for _ in 0..end.line - start.line {
+            end_offset += source[end_offset..].find('\n').unwrap() + 1;
+        }
+    }
+    end_offset += end.column;
+
+    let mut files = SimpleFiles::new();
+    let file = files.add(path.to_string_lossy(), source);
+
+    let diagnostic = diagnose(file, start_offset..end_offset, error);
+
+    let config = Config::default();
+    let _ = term::emit(stderr, &config, &files, &diagnostic);
+}
+
+fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
+    let message = error.to_string();
+    let info = syntax::error::ERRORS
+        .iter()
+        .find(|e| message.contains(e.msg));
+    let mut diagnostic = Diagnostic::error().with_message(&message);
+    let mut label = Label::primary(file, range);
+    if let Some(info) = info {
+        label.message = info.label.map_or(message, str::to_owned);
+        diagnostic.labels.push(label);
+        diagnostic.notes.extend(info.note.map(str::to_owned));
+    } else {
+        label.message = message;
+        diagnostic.labels.push(label);
+    }
+    diagnostic.code = Some("cxxbridge".to_owned());
+    diagnostic
+}
diff --git a/gen/src/include b/gen/src/include
new file mode 120000
index 0000000..fcffffb
--- /dev/null
+++ b/gen/src/include
@@ -0,0 +1 @@
+../../include
\ No newline at end of file
diff --git a/gen/src/include.rs b/gen/src/include.rs
new file mode 100644
index 0000000..129a8e6
--- /dev/null
+++ b/gen/src/include.rs
@@ -0,0 +1,106 @@
+use std::fmt::{self, Display};
+
+pub static HEADER: &str = include_str!("include/cxx.h");
+
+pub fn get(guard: &str) -> &'static str {
+    let ifndef = format!("#ifndef {}", guard);
+    let endif = format!("#endif // {}", guard);
+    let begin = find_line(&ifndef);
+    let end = find_line(&endif);
+    if let (Some(begin), Some(end)) = (begin, end) {
+        &HEADER[begin..end + endif.len()]
+    } else {
+        panic!("not found in cxx.h header: {}", guard)
+    }
+}
+
+fn find_line(line: &str) -> Option<usize> {
+    let mut offset = 0;
+    loop {
+        offset += HEADER[offset..].find(line)?;
+        let rest = &HEADER[offset + line.len()..];
+        if rest.starts_with('\n') || rest.starts_with('\r') {
+            return Some(offset);
+        }
+        offset += line.len();
+    }
+}
+
+#[derive(Default, PartialEq)]
+pub struct Includes {
+    custom: Vec<String>,
+    pub array: bool,
+    pub cstddef: bool,
+    pub cstdint: bool,
+    pub cstring: bool,
+    pub exception: bool,
+    pub memory: bool,
+    pub string: bool,
+    pub type_traits: bool,
+    pub utility: bool,
+    pub vector: bool,
+    pub base_tsd: bool,
+}
+
+impl Includes {
+    pub fn new() -> Self {
+        Includes::default()
+    }
+
+    pub fn insert(&mut self, include: String) {
+        self.custom.push(include);
+    }
+}
+
+impl Extend<String> for Includes {
+    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
+        self.custom.extend(iter);
+    }
+}
+
+impl Display for Includes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for include in &self.custom {
+            writeln!(f, "#include \"{}\"", include.escape_default())?;
+        }
+        if self.array {
+            writeln!(f, "#include <array>")?;
+        }
+        if self.cstddef {
+            writeln!(f, "#include <cstddef>")?;
+        }
+        if self.cstdint {
+            writeln!(f, "#include <cstdint>")?;
+        }
+        if self.cstring {
+            writeln!(f, "#include <cstring>")?;
+        }
+        if self.exception {
+            writeln!(f, "#include <exception>")?;
+        }
+        if self.memory {
+            writeln!(f, "#include <memory>")?;
+        }
+        if self.string {
+            writeln!(f, "#include <string>")?;
+        }
+        if self.type_traits {
+            writeln!(f, "#include <type_traits>")?;
+        }
+        if self.utility {
+            writeln!(f, "#include <utility>")?;
+        }
+        if self.vector {
+            writeln!(f, "#include <vector>")?;
+        }
+        if self.base_tsd {
+            writeln!(f, "#if defined(_WIN32)")?;
+            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#endif")?;
+        }
+        if *self != Self::default() {
+            writeln!(f)?;
+        }
+        Ok(())
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
new file mode 100644
index 0000000..928c6ec
--- /dev/null
+++ b/gen/src/mod.rs
@@ -0,0 +1,87 @@
+// Functionality that is shared between the cxx::generate_bridge entry point and
+// the cmd.
+
+mod error;
+pub(super) mod include;
+pub(super) mod out;
+mod write;
+
+use self::error::{format_err, Error, Result};
+use crate::syntax::namespace::Namespace;
+use crate::syntax::{self, check, Types};
+use quote::quote;
+use std::fs;
+use std::path::Path;
+use syn::{Attribute, File, Item};
+
+struct Input {
+    namespace: Namespace,
+    module: Vec<Item>,
+}
+
+#[derive(Default)]
+pub(super) struct Opt {
+    /// Any additional headers to #include
+    pub include: Vec<String>,
+}
+
+pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
+    let header = false;
+    generate(path, opt, header)
+}
+
+pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
+    let header = true;
+    generate(path, opt, header)
+}
+
+fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
+    let source = match fs::read_to_string(path) {
+        Ok(source) => source,
+        Err(err) => format_err(path, "", Error::Io(err)),
+    };
+    match (|| -> Result<_> {
+        let syntax = syn::parse_file(&source)?;
+        let bridge = find_bridge_mod(syntax)?;
+        let apis = syntax::parse_items(bridge.module)?;
+        let types = Types::collect(&apis)?;
+        check::typecheck(&apis, &types)?;
+        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
+        Ok(out)
+    })() {
+        Ok(out) => out.content(),
+        Err(err) => format_err(path, &source, err),
+    }
+}
+
+fn find_bridge_mod(syntax: File) -> Result<Input> {
+    for item in syntax.items {
+        if let Item::Mod(item) = item {
+            for attr in &item.attrs {
+                let path = &attr.path;
+                if quote!(#path).to_string() == "cxx :: bridge" {
+                    let module = match item.content {
+                        Some(module) => module.1,
+                        None => {
+                            return Err(Error::Syn(syn::Error::new_spanned(
+                                item,
+                                Error::OutOfLineMod,
+                            )));
+                        }
+                    };
+                    let namespace = parse_args(attr)?;
+                    return Ok(Input { namespace, module });
+                }
+            }
+        }
+    }
+    Err(Error::NoBridgeMod)
+}
+
+fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
+    if attr.tokens.is_empty() {
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
+    }
+}
diff --git a/gen/src/out.rs b/gen/src/out.rs
new file mode 100644
index 0000000..08bf85f
--- /dev/null
+++ b/gen/src/out.rs
@@ -0,0 +1,91 @@
+use crate::gen::include::Includes;
+use crate::syntax::namespace::Namespace;
+use std::cell::RefCell;
+use std::fmt::{self, Arguments, Write};
+
+pub(crate) struct OutFile {
+    pub namespace: Namespace,
+    pub header: bool,
+    pub include: Includes,
+    content: RefCell<Content>,
+}
+
+struct Content {
+    bytes: Vec<u8>,
+    section_pending: bool,
+    blocks_pending: Vec<&'static str>,
+}
+
+impl OutFile {
+    pub fn new(namespace: Namespace, header: bool) -> Self {
+        OutFile {
+            namespace,
+            header,
+            include: Includes::new(),
+            content: RefCell::new(Content {
+                bytes: Vec::new(),
+                section_pending: false,
+                blocks_pending: Vec::new(),
+            }),
+        }
+    }
+
+    // Write a blank line if the preceding section had any contents.
+    pub fn next_section(&mut self) {
+        let content = self.content.get_mut();
+        content.section_pending = true;
+    }
+
+    pub fn begin_block(&mut self, block: &'static str) {
+        let content = self.content.get_mut();
+        content.blocks_pending.push(block);
+    }
+
+    pub fn end_block(&mut self, block: &'static str) {
+        let content = self.content.get_mut();
+        if content.blocks_pending.pop().is_none() {
+            content.bytes.extend_from_slice(b"} // ");
+            content.bytes.extend_from_slice(block.as_bytes());
+            content.bytes.push(b'\n');
+            content.section_pending = true;
+        }
+    }
+
+    pub fn prepend(&mut self, section: String) {
+        let content = self.content.get_mut();
+        content.bytes.splice(..0, section.into_bytes());
+    }
+
+    pub fn write_fmt(&self, args: Arguments) {
+        let content = &mut *self.content.borrow_mut();
+        Write::write_fmt(content, args).unwrap();
+    }
+
+    pub fn content(&self) -> Vec<u8> {
+        self.content.borrow().bytes.clone()
+    }
+}
+
+impl Write for Content {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        if !s.is_empty() {
+            if !self.blocks_pending.is_empty() {
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
+                }
+                for block in self.blocks_pending.drain(..) {
+                    self.bytes.extend_from_slice(block.as_bytes());
+                    self.bytes.extend_from_slice(b" {\n");
+                }
+                self.section_pending = false;
+            } else if self.section_pending {
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
+                }
+                self.section_pending = false;
+            }
+            self.bytes.extend_from_slice(s.as_bytes());
+        }
+        Ok(())
+    }
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
new file mode 100644
index 0000000..b39d978
--- /dev/null
+++ b/gen/src/write.rs
@@ -0,0 +1,1224 @@
+use crate::gen::out::OutFile;
+use crate::gen::{include, Opt};
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
+use crate::syntax::symbol::Symbol;
+use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use proc_macro2::Ident;
+use std::collections::HashMap;
+
+pub(super) fn gen(
+    namespace: Namespace,
+    apis: &[Api],
+    types: &Types,
+    opt: Opt,
+    header: bool,
+) -> OutFile {
+    let mut out_file = OutFile::new(namespace.clone(), header);
+    let out = &mut out_file;
+
+    if header {
+        writeln!(out, "#pragma once");
+    }
+
+    out.include.extend(opt.include);
+    for api in apis {
+        if let Api::Include(include) = api {
+            out.include.insert(include.value());
+        }
+    }
+
+    write_includes(out, types);
+    write_include_cxxbridge(out, apis, types);
+
+    out.next_section();
+    for name in &namespace {
+        writeln!(out, "namespace {} {{", name);
+    }
+
+    out.next_section();
+    for api in apis {
+        match api {
+            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            _ => {}
+        }
+    }
+
+    let mut methods_for_type = HashMap::new();
+    for api in apis {
+        if let Api::RustFunction(efn) = api {
+            if let Some(receiver) = &efn.sig.receiver {
+                methods_for_type
+                    .entry(&receiver.ty)
+                    .or_insert_with(Vec::new)
+                    .push(efn);
+            }
+        }
+    }
+
+    for api in apis {
+        match api {
+            Api::Struct(strct) => {
+                out.next_section();
+                write_struct(out, strct);
+            }
+            Api::RustType(ety) => {
+                if let Some(methods) = methods_for_type.get(&ety.ident) {
+                    out.next_section();
+                    write_struct_with_methods(out, ety, methods);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    if !header {
+        out.begin_block("extern \"C\"");
+        write_exception_glue(out, apis);
+        for api in apis {
+            let (efn, write): (_, fn(_, _, _)) = match api {
+                Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
+                Api::RustFunction(efn) => (efn, write_rust_function_decl),
+                _ => continue,
+            };
+            out.next_section();
+            write(out, efn, types);
+        }
+        out.end_block("extern \"C\"");
+    }
+
+    for api in apis {
+        if let Api::RustFunction(efn) = api {
+            out.next_section();
+            write_rust_function_shim(out, efn, types);
+        }
+    }
+
+    out.next_section();
+    for name in namespace.iter().rev() {
+        writeln!(out, "}} // namespace {}", name);
+    }
+
+    if !header {
+        out.next_section();
+        write_generic_instantiations(out, types);
+    }
+
+    out.prepend(out.include.to_string());
+
+    out_file
+}
+
+fn write_includes(out: &mut OutFile, types: &Types) {
+    for ty in types {
+        match ty {
+            Type::Ident(ident) => match Atom::from(ident) {
+                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
+                | Some(I64) => out.include.cstdint = true,
+                Some(Usize) => out.include.cstddef = true,
+                Some(CxxString) => out.include.string = true,
+                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+            },
+            Type::RustBox(_) => out.include.type_traits = true,
+            Type::UniquePtr(_) => out.include.memory = true,
+            Type::CxxVector(_) => out.include.vector = true,
+            Type::SliceRefU8(_) => out.include.cstdint = true,
+            _ => {}
+        }
+    }
+}
+
+fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
+    let mut needs_rust_string = false;
+    let mut needs_rust_str = false;
+    let mut needs_rust_slice = false;
+    let mut needs_rust_box = false;
+    let mut needs_rust_vec = false;
+    let mut needs_rust_fn = false;
+    let mut needs_rust_isize = false;
+    for ty in types {
+        match ty {
+            Type::RustBox(_) => {
+                out.include.type_traits = true;
+                needs_rust_box = true;
+            }
+            Type::RustVec(_) => {
+                out.include.array = true;
+                out.include.type_traits = true;
+                needs_rust_vec = true;
+            }
+            Type::Str(_) => {
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_str = true;
+            }
+            Type::Fn(_) => {
+                needs_rust_fn = true;
+            }
+            Type::Slice(_) | Type::SliceRefU8(_) => {
+                needs_rust_slice = true;
+            }
+            ty if ty == Isize => {
+                out.include.base_tsd = true;
+                needs_rust_isize = true;
+            }
+            ty if ty == RustString => {
+                out.include.array = true;
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_string = true;
+            }
+            _ => {}
+        }
+    }
+
+    let mut needs_rust_error = false;
+    let mut needs_unsafe_bitcopy = false;
+    let mut needs_manually_drop = false;
+    let mut needs_maybe_uninit = false;
+    let mut needs_trycatch = false;
+    for api in apis {
+        match api {
+            Api::CxxFunction(efn) if !out.header => {
+                if efn.throws {
+                    needs_trycatch = true;
+                }
+                for arg in &efn.args {
+                    let bitcopy = match arg.ty {
+                        Type::RustVec(_) => true,
+                        _ => arg.ty == RustString,
+                    };
+                    if bitcopy {
+                        needs_unsafe_bitcopy = true;
+                        break;
+                    }
+                }
+            }
+            Api::RustFunction(efn) if !out.header => {
+                if efn.throws {
+                    out.include.exception = true;
+                    needs_rust_error = true;
+                }
+                for arg in &efn.args {
+                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                        needs_manually_drop = true;
+                        break;
+                    }
+                }
+                if let Some(ret) = &efn.ret {
+                    if types.needs_indirect_abi(ret) {
+                        needs_maybe_uninit = true;
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge02");
+
+    if needs_rust_string
+        || needs_rust_str
+        || needs_rust_slice
+        || needs_rust_box
+        || needs_rust_vec
+        || needs_rust_fn
+        || needs_rust_error
+        || needs_rust_isize
+        || needs_unsafe_bitcopy
+        || needs_manually_drop
+        || needs_maybe_uninit
+        || needs_trycatch
+    {
+        writeln!(out, "// #include \"rust/cxx.h\"");
+    }
+
+    if needs_rust_string {
+        out.next_section();
+        writeln!(out, "struct unsafe_bitcopy_t;");
+    }
+
+    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
+    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
+    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
+    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
+    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
+    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
+    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
+
+    if needs_manually_drop {
+        out.next_section();
+        out.include.utility = true;
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union ManuallyDrop {{");
+        writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
+        );
+        writeln!(out, "  ~ManuallyDrop() {{}}");
+        writeln!(out, "}};");
+    }
+
+    if needs_maybe_uninit {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union MaybeUninit {{");
+        writeln!(out, "  T value;");
+        writeln!(out, "  MaybeUninit() {{}}");
+        writeln!(out, "  ~MaybeUninit() {{}}");
+        writeln!(out, "}};");
+    }
+
+    out.end_block("namespace cxxbridge02");
+
+    if needs_trycatch {
+        out.begin_block("namespace behavior");
+        out.include.exception = true;
+        out.include.type_traits = true;
+        out.include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
+        writeln!(out);
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename std::enable_if<");
+        writeln!(
+            out,
+            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
+        );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+        out.end_block("namespace behavior");
+    }
+
+    out.end_block("namespace rust");
+}
+
+fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
+    let section = include::get(section);
+    if needed {
+        out.next_section();
+        for line in section.lines() {
+            if !line.trim_start().starts_with("//") {
+                writeln!(out, "{}", line);
+            }
+        }
+    }
+}
+
+fn write_struct(out: &mut OutFile, strct: &Struct) {
+    for line in strct.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", strct.ident);
+    for field in &strct.fields {
+        write!(out, "  ");
+        write_type_space(out, &field.ty);
+        writeln!(out, "{};", field.ident);
+    }
+    writeln!(out, "}};");
+}
+
+fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "struct {};", ident);
+}
+
+fn write_struct_using(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "using {} = {};", ident, ident);
+}
+
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+    for line in ety.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", ety.ident);
+    writeln!(out, "  {}() = delete;", ety.ident);
+    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
+    for method in methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false);
+        writeln!(out, ";");
+    }
+    writeln!(out, "}};");
+}
+
+fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+    let mut has_cxx_throws = false;
+    for api in apis {
+        if let Api::CxxFunction(efn) = api {
+            if efn.throws {
+                has_cxx_throws = true;
+                break;
+            }
+        }
+    }
+
+    if has_cxx_throws {
+        out.next_section();
+        writeln!(
+            out,
+            "const char *cxxbridge02$exception(const char *, size_t);",
+        );
+    }
+}
+
+fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type_space(out, &efn.ret, types);
+    }
+    let mangled = mangle::extern_fn(&out.namespace, efn);
+    write!(out, "{}(", mangled);
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
+        write!(out, "{} &self", receiver.ty);
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 || efn.receiver.is_some() {
+            write!(out, ", ");
+        }
+        if arg.ty == RustString {
+            write!(out, "const ");
+        } else if let Type::RustVec(_) = arg.ty {
+            write!(out, "const ");
+        }
+        write_extern_arg(out, arg, types);
+    }
+    let indirect_return = indirect_return(efn, types);
+    if indirect_return {
+        if !efn.args.is_empty() {
+            write!(out, ", ");
+        }
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
+        write!(out, "*return$");
+    }
+    writeln!(out, ") noexcept {{");
+    write!(out, "  ");
+    write_return_type(out, &efn.ret);
+    match &efn.receiver {
+        None => write!(out, "(*{}$)(", efn.ident),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        write_type(out, &arg.ty);
+    }
+    write!(out, ")");
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
+    }
+    write!(out, " = ");
+    match &efn.receiver {
+        None => write!(out, "{}", efn.ident),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
+    }
+    writeln!(out, ";");
+    write!(out, "  ");
+    if efn.throws {
+        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "  ::rust::behavior::trycatch(");
+        writeln!(out, "      [&] {{");
+        write!(out, "        ");
+    }
+    if indirect_return {
+        write!(out, "new (return$) ");
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
+        write!(out, "(");
+    } else if efn.ret.is_some() {
+        write!(out, "return ");
+    }
+    match &efn.ret {
+        Some(Type::Ref(_)) => write!(out, "&"),
+        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
+        Some(Type::SliceRefU8(_)) if !indirect_return => {
+            write!(out, "::rust::Slice<uint8_t>::Repr(")
+        }
+        _ => {}
+    }
+    match &efn.receiver {
+        None => write!(out, "{}$(", efn.ident),
+        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        if let Type::RustBox(_) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "::from_raw({})", arg.ident);
+        } else if let Type::UniquePtr(_) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "({})", arg.ident);
+        } else if arg.ty == RustString {
+            write!(
+                out,
+                "::rust::String(::rust::unsafe_bitcopy, *{})",
+                arg.ident,
+            );
+        } else if let Type::RustVec(_) = arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
+        } else if types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
+            write!(out, "::std::move(*{})", arg.ident);
+        } else {
+            write!(out, "{}", arg.ident);
+        }
+    }
+    write!(out, ")");
+    match &efn.ret {
+        Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
+        Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::CxxVector(_)) => write!(
+            out,
+            " /* Use RVO to convert to r-value and move construct */"
+        ),
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        _ => {}
+    }
+    if indirect_return {
+        write!(out, ")");
+    }
+    writeln!(out, ";");
+    if efn.throws {
+        out.include.cstring = true;
+        writeln!(out, "        throw$.ptr = nullptr;");
+        writeln!(out, "      }},");
+        writeln!(out, "      [&](const char *catch$) noexcept {{");
+        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
+        writeln!(
+            out,
+            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
+        );
+        writeln!(out, "      }});");
+        writeln!(out, "  return throw$;");
+    }
+    writeln!(out, "}}");
+    for arg in &efn.args {
+        if let Type::Fn(f) = &arg.ty {
+            let var = &arg.ident;
+            write_function_pointer_trampoline(out, efn, var, f, types);
+        }
+    }
+}
+
+fn write_function_pointer_trampoline(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    var: &Ident,
+    f: &Signature,
+    types: &Types,
+) {
+    out.next_section();
+    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
+    let indirect_call = true;
+    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
+
+    out.next_section();
+    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
+    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
+}
+
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    let link_name = mangle::extern_fn(&out.namespace, efn);
+    let indirect_call = false;
+    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
+}
+
+fn write_rust_function_decl_impl(
+    out: &mut OutFile,
+    link_name: &Symbol,
+    sig: &Signature,
+    types: &Types,
+    indirect_call: bool,
+) {
+    if sig.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type_space(out, &sig.ret, types);
+    }
+    write!(out, "{}(", link_name);
+    let mut needs_comma = false;
+    if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
+        write!(out, "{} &self", receiver.ty);
+        needs_comma = true;
+    }
+    for arg in &sig.args {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write_extern_arg(out, arg, types);
+        needs_comma = true;
+    }
+    if indirect_return(sig, types) {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write_return_type(out, &sig.ret);
+        write!(out, "*return$");
+        needs_comma = true;
+    }
+    if indirect_call {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write!(out, "void *");
+    }
+    writeln!(out, ") noexcept;");
+}
+
+fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    for line in efn.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    let local_name = match &efn.sig.receiver {
+        None => efn.ident.to_string(),
+        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
+    };
+    let invoke = mangle::extern_fn(&out.namespace, efn);
+    let indirect_call = false;
+    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
+}
+
+fn write_rust_function_shim_decl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    indirect_call: bool,
+) {
+    write_return_type(out, &sig.ret);
+    write!(out, "{}(", local_name);
+    for (i, arg) in sig.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        write_type_space(out, &arg.ty);
+        write!(out, "{}", arg.ident);
+    }
+    if indirect_call {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "void *extern$");
+    }
+    write!(out, ")");
+    if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
+    }
+    if !sig.throws {
+        write!(out, " noexcept");
+    }
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &Symbol,
+    indirect_call: bool,
+) {
+    if out.header && sig.receiver.is_some() {
+        // We've already defined this inside the struct.
+        return;
+    }
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
+    if out.header {
+        writeln!(out, ";");
+        return;
+    }
+    writeln!(out, " {{");
+    for arg in &sig.args {
+        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
+            write!(out, "  ::rust::ManuallyDrop<");
+            write_type(out, &arg.ty);
+            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
+        }
+    }
+    write!(out, "  ");
+    let indirect_return = indirect_return(sig, types);
+    if indirect_return {
+        write!(out, "::rust::MaybeUninit<");
+        write_type(out, sig.ret.as_ref().unwrap());
+        writeln!(out, "> return$;");
+        write!(out, "  ");
+    } else if let Some(ret) = &sig.ret {
+        write!(out, "return ");
+        match ret {
+            Type::RustBox(_) => {
+                write_type(out, ret);
+                write!(out, "::from_raw(");
+            }
+            Type::UniquePtr(_) => {
+                write_type(out, ret);
+                write!(out, "(");
+            }
+            Type::Ref(_) => write!(out, "*"),
+            _ => {}
+        }
+    }
+    if sig.throws {
+        write!(out, "::rust::Str::Repr error$ = ");
+    }
+    write!(out, "{}(", invoke);
+    if sig.receiver.is_some() {
+        write!(out, "*this");
+    }
+    for (i, arg) in sig.args.iter().enumerate() {
+        if i > 0 || sig.receiver.is_some() {
+            write!(out, ", ");
+        }
+        match &arg.ty {
+            Type::Str(_) => write!(out, "::rust::Str::Repr("),
+            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
+            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+            _ => {}
+        }
+        write!(out, "{}", arg.ident);
+        match &arg.ty {
+            Type::RustBox(_) => write!(out, ".into_raw()"),
+            Type::UniquePtr(_) => write!(out, ".release()"),
+            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
+            _ => {}
+        }
+    }
+    if indirect_return {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "&return$.value");
+    }
+    if indirect_call {
+        if !sig.args.is_empty() || indirect_return {
+            write!(out, ", ");
+        }
+        write!(out, "extern$");
+    }
+    write!(out, ")");
+    if let Some(ret) = &sig.ret {
+        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+            write!(out, ")");
+        }
+    }
+    writeln!(out, ";");
+    if sig.throws {
+        writeln!(out, "  if (error$.ptr) {{");
+        writeln!(out, "    throw ::rust::Error(error$);");
+        writeln!(out, "  }}");
+    }
+    if indirect_return {
+        out.include.utility = true;
+        writeln!(out, "  return ::std::move(return$.value);");
+    }
+    writeln!(out, "}}");
+}
+
+fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
+    match ty {
+        None => write!(out, "void "),
+        Some(ty) => write_type_space(out, ty),
+    }
+}
+
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
+        .as_ref()
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
+}
+
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::RustBox(ty) | Type::UniquePtr(ty) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Type::Ref(ty) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
+        Type::Str(_) => write!(out, "::rust::Str::Repr"),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
+        _ => write_type(out, ty),
+    }
+}
+
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
+    write_indirect_return_type(out, ty);
+    match ty {
+        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
+        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
+        _ => write_space_after_type(out, ty),
+    }
+}
+
+fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
+    match ty {
+        Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Some(Type::Ref(ty)) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
+        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
+        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
+        Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
+        _ => write_return_type(out, ty),
+    }
+}
+
+fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
+    match &arg.ty {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Type::Str(_) => write!(out, "::rust::Str::Repr "),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
+        _ => write_type_space(out, &arg.ty),
+    }
+    if types.needs_indirect_abi(&arg.ty) {
+        write!(out, "*");
+    }
+    write!(out, "{}", arg.ident);
+}
+
+fn write_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::Ident(ident) => match Atom::from(ident) {
+            Some(Bool) => write!(out, "bool"),
+            Some(U8) => write!(out, "uint8_t"),
+            Some(U16) => write!(out, "uint16_t"),
+            Some(U32) => write!(out, "uint32_t"),
+            Some(U64) => write!(out, "uint64_t"),
+            Some(Usize) => write!(out, "size_t"),
+            Some(I8) => write!(out, "int8_t"),
+            Some(I16) => write!(out, "int16_t"),
+            Some(I32) => write!(out, "int32_t"),
+            Some(I64) => write!(out, "int64_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
+            Some(CxxString) => write!(out, "::std::string"),
+            Some(RustString) => write!(out, "::rust::String"),
+            None => write!(out, "{}", ident),
+        },
+        Type::RustBox(ty) => {
+            write!(out, "::rust::Box<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::RustVec(ty) => {
+            write!(out, "::rust::Vec<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::UniquePtr(ptr) => {
+            write!(out, "::std::unique_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
+        Type::CxxVector(ty) => {
+            write!(out, "::std::vector<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::Ref(r) => {
+            if r.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &r.inner);
+            write!(out, " &");
+        }
+        Type::Slice(_) => {
+            // For now, only U8 slices are supported, which are covered separately below
+            unreachable!()
+        }
+        Type::Str(_) => {
+            write!(out, "::rust::Str");
+        }
+        Type::SliceRefU8(_) => {
+            write!(out, "::rust::Slice<uint8_t>");
+        }
+        Type::Fn(f) => {
+            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
+            match &f.ret {
+                Some(ret) => write_type(out, ret),
+                None => write!(out, "void"),
+            }
+            write!(out, "(");
+            for (i, arg) in f.args.iter().enumerate() {
+                if i > 0 {
+                    write!(out, ", ");
+                }
+                write_type(out, &arg.ty);
+            }
+            write!(out, ")>");
+        }
+        Type::Void(_) => unreachable!(),
+    }
+}
+
+fn write_type_space(out: &mut OutFile, ty: &Type) {
+    write_type(out, ty);
+    write_space_after_type(out, ty);
+}
+
+fn write_space_after_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::Ident(_)
+        | Type::RustBox(_)
+        | Type::UniquePtr(_)
+        | Type::Str(_)
+        | Type::CxxVector(_)
+        | Type::RustVec(_)
+        | Type::SliceRefU8(_)
+        | Type::Fn(_) => write!(out, " "),
+        Type::Ref(_) => {}
+        Type::Void(_) | Type::Slice(_) => unreachable!(),
+    }
+}
+
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut path = String::new();
+            for name in namespace {
+                path += name;
+                path += "::";
+            }
+            path += &ident.to_string();
+            path
+        }
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        _ => unreachable!(),
+    }
+}
+
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
+        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        _ => unreachable!(),
+    }
+}
+
+fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
+    fn allow_unique_ptr(ident: &Ident) -> bool {
+        Atom::from(ident).is_none()
+    }
+
+    out.begin_block("extern \"C\"");
+    for ty in types {
+        if let Type::RustBox(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                out.next_section();
+                write_rust_box_extern(out, inner);
+            }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_rust_vec_extern(out, inner);
+                }
+            }
+        } else if let Type::UniquePtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if allow_unique_ptr(inner) {
+                    out.next_section();
+                    write_unique_ptr(out, inner, types);
+                }
+            }
+        } else if let Type::CxxVector(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_cxx_vector(out, ty, inner, types);
+                }
+            }
+        }
+    }
+    out.end_block("extern \"C\"");
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge02");
+    for ty in types {
+        if let Type::RustBox(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                write_rust_box_impl(out, inner);
+            }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    write_rust_vec_impl(out, inner);
+                }
+            }
+        }
+    }
+    out.end_block("namespace cxxbridge02");
+    out.end_block("namespace rust");
+}
+
+fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    for name in &out.namespace {
+        inner += name;
+        inner += "::";
+    }
+    inner += &ident.to_string();
+    let instance = inner.replace("::", "$");
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
+}
+
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        inner, instance,
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
+        instance,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
+}
+
+fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    for name in &out.namespace {
+        inner += name;
+        inner += "::";
+    }
+    inner += &ident.to_string();
+    let instance = inner.replace("::", "$");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
+    writeln!(out, "}}");
+}
+
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "template <>");
+    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$drop(this);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$data(this);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
+    writeln!(out, "}}");
+}
+
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+    let ty = Type::Ident(ident.clone());
+    let instance = to_mangled(&out.namespace, &ty);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+
+    write_unique_ptr_common(out, &ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+}
+
+// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
+fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.utility = true;
+    let inner = to_typename(&out.namespace, ty);
+    let instance = to_mangled(&out.namespace, ty);
+
+    let can_construct_from_value = match ty {
+        Type::Ident(ident) => types.structs.contains_key(ident),
+        _ => false,
+    };
+
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    if can_construct_from_value {
+        writeln!(
+            out,
+            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return ptr.get();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return ptr.release();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  ptr->~unique_ptr();");
+    writeln!(out, "}}");
+}
+
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(
+        out,
+        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  return s.size();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return s[pos];");
+    writeln!(out, "}}");
+
+    write_unique_ptr_common(out, vector_ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
+}
diff --git a/gen/write.rs b/gen/write.rs
deleted file mode 100644
index b39d978..0000000
--- a/gen/write.rs
+++ /dev/null
@@ -1,1224 +0,0 @@
-use crate::gen::out::OutFile;
-use crate::gen::{include, Opt};
-use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
-use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
-use proc_macro2::Ident;
-use std::collections::HashMap;
-
-pub(super) fn gen(
-    namespace: Namespace,
-    apis: &[Api],
-    types: &Types,
-    opt: Opt,
-    header: bool,
-) -> OutFile {
-    let mut out_file = OutFile::new(namespace.clone(), header);
-    let out = &mut out_file;
-
-    if header {
-        writeln!(out, "#pragma once");
-    }
-
-    out.include.extend(opt.include);
-    for api in apis {
-        if let Api::Include(include) = api {
-            out.include.insert(include.value());
-        }
-    }
-
-    write_includes(out, types);
-    write_include_cxxbridge(out, apis, types);
-
-    out.next_section();
-    for name in &namespace {
-        writeln!(out, "namespace {} {{", name);
-    }
-
-    out.next_section();
-    for api in apis {
-        match api {
-            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
-            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
-            _ => {}
-        }
-    }
-
-    let mut methods_for_type = HashMap::new();
-    for api in apis {
-        if let Api::RustFunction(efn) = api {
-            if let Some(receiver) = &efn.sig.receiver {
-                methods_for_type
-                    .entry(&receiver.ty)
-                    .or_insert_with(Vec::new)
-                    .push(efn);
-            }
-        }
-    }
-
-    for api in apis {
-        match api {
-            Api::Struct(strct) => {
-                out.next_section();
-                write_struct(out, strct);
-            }
-            Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.ident) {
-                    out.next_section();
-                    write_struct_with_methods(out, ety, methods);
-                }
-            }
-            _ => {}
-        }
-    }
-
-    if !header {
-        out.begin_block("extern \"C\"");
-        write_exception_glue(out, apis);
-        for api in apis {
-            let (efn, write): (_, fn(_, _, _)) = match api {
-                Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
-                Api::RustFunction(efn) => (efn, write_rust_function_decl),
-                _ => continue,
-            };
-            out.next_section();
-            write(out, efn, types);
-        }
-        out.end_block("extern \"C\"");
-    }
-
-    for api in apis {
-        if let Api::RustFunction(efn) = api {
-            out.next_section();
-            write_rust_function_shim(out, efn, types);
-        }
-    }
-
-    out.next_section();
-    for name in namespace.iter().rev() {
-        writeln!(out, "}} // namespace {}", name);
-    }
-
-    if !header {
-        out.next_section();
-        write_generic_instantiations(out, types);
-    }
-
-    out.prepend(out.include.to_string());
-
-    out_file
-}
-
-fn write_includes(out: &mut OutFile, types: &Types) {
-    for ty in types {
-        match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
-                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
-                | Some(I64) => out.include.cstdint = true,
-                Some(Usize) => out.include.cstddef = true,
-                Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
-            },
-            Type::RustBox(_) => out.include.type_traits = true,
-            Type::UniquePtr(_) => out.include.memory = true,
-            Type::CxxVector(_) => out.include.vector = true,
-            Type::SliceRefU8(_) => out.include.cstdint = true,
-            _ => {}
-        }
-    }
-}
-
-fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
-    let mut needs_rust_string = false;
-    let mut needs_rust_str = false;
-    let mut needs_rust_slice = false;
-    let mut needs_rust_box = false;
-    let mut needs_rust_vec = false;
-    let mut needs_rust_fn = false;
-    let mut needs_rust_isize = false;
-    for ty in types {
-        match ty {
-            Type::RustBox(_) => {
-                out.include.type_traits = true;
-                needs_rust_box = true;
-            }
-            Type::RustVec(_) => {
-                out.include.array = true;
-                out.include.type_traits = true;
-                needs_rust_vec = true;
-            }
-            Type::Str(_) => {
-                out.include.cstdint = true;
-                out.include.string = true;
-                needs_rust_str = true;
-            }
-            Type::Fn(_) => {
-                needs_rust_fn = true;
-            }
-            Type::Slice(_) | Type::SliceRefU8(_) => {
-                needs_rust_slice = true;
-            }
-            ty if ty == Isize => {
-                out.include.base_tsd = true;
-                needs_rust_isize = true;
-            }
-            ty if ty == RustString => {
-                out.include.array = true;
-                out.include.cstdint = true;
-                out.include.string = true;
-                needs_rust_string = true;
-            }
-            _ => {}
-        }
-    }
-
-    let mut needs_rust_error = false;
-    let mut needs_unsafe_bitcopy = false;
-    let mut needs_manually_drop = false;
-    let mut needs_maybe_uninit = false;
-    let mut needs_trycatch = false;
-    for api in apis {
-        match api {
-            Api::CxxFunction(efn) if !out.header => {
-                if efn.throws {
-                    needs_trycatch = true;
-                }
-                for arg in &efn.args {
-                    let bitcopy = match arg.ty {
-                        Type::RustVec(_) => true,
-                        _ => arg.ty == RustString,
-                    };
-                    if bitcopy {
-                        needs_unsafe_bitcopy = true;
-                        break;
-                    }
-                }
-            }
-            Api::RustFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.include.exception = true;
-                    needs_rust_error = true;
-                }
-                for arg in &efn.args {
-                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-                        needs_manually_drop = true;
-                        break;
-                    }
-                }
-                if let Some(ret) = &efn.ret {
-                    if types.needs_indirect_abi(ret) {
-                        needs_maybe_uninit = true;
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
-
-    if needs_rust_string
-        || needs_rust_str
-        || needs_rust_slice
-        || needs_rust_box
-        || needs_rust_vec
-        || needs_rust_fn
-        || needs_rust_error
-        || needs_rust_isize
-        || needs_unsafe_bitcopy
-        || needs_manually_drop
-        || needs_maybe_uninit
-        || needs_trycatch
-    {
-        writeln!(out, "// #include \"rust/cxx.h\"");
-    }
-
-    if needs_rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
-
-    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
-    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
-    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
-    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
-    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
-    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
-    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
-    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
-
-    if needs_manually_drop {
-        out.next_section();
-        out.include.utility = true;
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union ManuallyDrop {{");
-        writeln!(out, "  T value;");
-        writeln!(
-            out,
-            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
-        );
-        writeln!(out, "  ~ManuallyDrop() {{}}");
-        writeln!(out, "}};");
-    }
-
-    if needs_maybe_uninit {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union MaybeUninit {{");
-        writeln!(out, "  T value;");
-        writeln!(out, "  MaybeUninit() {{}}");
-        writeln!(out, "  ~MaybeUninit() {{}}");
-        writeln!(out, "}};");
-    }
-
-    out.end_block("namespace cxxbridge02");
-
-    if needs_trycatch {
-        out.begin_block("namespace behavior");
-        out.include.exception = true;
-        out.include.type_traits = true;
-        out.include.utility = true;
-        writeln!(out, "class missing {{}};");
-        writeln!(out, "missing trycatch(...);");
-        writeln!(out);
-        writeln!(out, "template <typename Try, typename Fail>");
-        writeln!(out, "static typename std::enable_if<");
-        writeln!(
-            out,
-            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
-        );
-        writeln!(out, "                 missing>::value>::type");
-        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
-        writeln!(out, "  func();");
-        writeln!(out, "}} catch (const ::std::exception &e) {{");
-        writeln!(out, "  fail(e.what());");
-        writeln!(out, "}}");
-        out.end_block("namespace behavior");
-    }
-
-    out.end_block("namespace rust");
-}
-
-fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
-    let section = include::get(section);
-    if needed {
-        out.next_section();
-        for line in section.lines() {
-            if !line.trim_start().starts_with("//") {
-                writeln!(out, "{}", line);
-            }
-        }
-    }
-}
-
-fn write_struct(out: &mut OutFile, strct: &Struct) {
-    for line in strct.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    writeln!(out, "struct {} final {{", strct.ident);
-    for field in &strct.fields {
-        write!(out, "  ");
-        write_type_space(out, &field.ty);
-        writeln!(out, "{};", field.ident);
-    }
-    writeln!(out, "}};");
-}
-
-fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "struct {};", ident);
-}
-
-fn write_struct_using(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "using {} = {};", ident, ident);
-}
-
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    for line in ety.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    writeln!(out, "struct {} final {{", ety.ident);
-    writeln!(out, "  {}() = delete;", ety.ident);
-    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
-    for method in methods {
-        write!(out, "  ");
-        let sig = &method.sig;
-        let local_name = method.ident.to_string();
-        write_rust_function_shim_decl(out, &local_name, sig, false);
-        writeln!(out, ";");
-    }
-    writeln!(out, "}};");
-}
-
-fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
-    let mut has_cxx_throws = false;
-    for api in apis {
-        if let Api::CxxFunction(efn) = api {
-            if efn.throws {
-                has_cxx_throws = true;
-                break;
-            }
-        }
-    }
-
-    if has_cxx_throws {
-        out.next_section();
-        writeln!(
-            out,
-            "const char *cxxbridge02$exception(const char *, size_t);",
-        );
-    }
-}
-
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    if efn.throws {
-        write!(out, "::rust::Str::Repr ");
-    } else {
-        write_extern_return_type_space(out, &efn.ret, types);
-    }
-    let mangled = mangle::extern_fn(&out.namespace, efn);
-    write!(out, "{}(", mangled);
-    if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, "const ");
-        }
-        write!(out, "{} &self", receiver.ty);
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 || efn.receiver.is_some() {
-            write!(out, ", ");
-        }
-        if arg.ty == RustString {
-            write!(out, "const ");
-        } else if let Type::RustVec(_) = arg.ty {
-            write!(out, "const ");
-        }
-        write_extern_arg(out, arg, types);
-    }
-    let indirect_return = indirect_return(efn, types);
-    if indirect_return {
-        if !efn.args.is_empty() {
-            write!(out, ", ");
-        }
-        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
-        write!(out, "*return$");
-    }
-    writeln!(out, ") noexcept {{");
-    write!(out, "  ");
-    write_return_type(out, &efn.ret);
-    match &efn.receiver {
-        None => write!(out, "(*{}$)(", efn.ident),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        write_type(out, &arg.ty);
-    }
-    write!(out, ")");
-    if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, " const");
-        }
-    }
-    write!(out, " = ");
-    match &efn.receiver {
-        None => write!(out, "{}", efn.ident),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
-    }
-    writeln!(out, ";");
-    write!(out, "  ");
-    if efn.throws {
-        writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  ::rust::behavior::trycatch(");
-        writeln!(out, "      [&] {{");
-        write!(out, "        ");
-    }
-    if indirect_return {
-        write!(out, "new (return$) ");
-        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
-        write!(out, "(");
-    } else if efn.ret.is_some() {
-        write!(out, "return ");
-    }
-    match &efn.ret {
-        Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
-        Some(Type::SliceRefU8(_)) if !indirect_return => {
-            write!(out, "::rust::Slice<uint8_t>::Repr(")
-        }
-        _ => {}
-    }
-    match &efn.receiver {
-        None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        if let Type::RustBox(_) = &arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "::from_raw({})", arg.ident);
-        } else if let Type::UniquePtr(_) = &arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "({})", arg.ident);
-        } else if arg.ty == RustString {
-            write!(
-                out,
-                "::rust::String(::rust::unsafe_bitcopy, *{})",
-                arg.ident,
-            );
-        } else if let Type::RustVec(_) = arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if types.needs_indirect_abi(&arg.ty) {
-            out.include.utility = true;
-            write!(out, "::std::move(*{})", arg.ident);
-        } else {
-            write!(out, "{}", arg.ident);
-        }
-    }
-    write!(out, ")");
-    match &efn.ret {
-        Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
-        Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::CxxVector(_)) => write!(
-            out,
-            " /* Use RVO to convert to r-value and move construct */"
-        ),
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
-        _ => {}
-    }
-    if indirect_return {
-        write!(out, ")");
-    }
-    writeln!(out, ";");
-    if efn.throws {
-        out.include.cstring = true;
-        writeln!(out, "        throw$.ptr = nullptr;");
-        writeln!(out, "      }},");
-        writeln!(out, "      [&](const char *catch$) noexcept {{");
-        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
-        writeln!(
-            out,
-            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
-        );
-        writeln!(out, "      }});");
-        writeln!(out, "  return throw$;");
-    }
-    writeln!(out, "}}");
-    for arg in &efn.args {
-        if let Type::Fn(f) = &arg.ty {
-            let var = &arg.ident;
-            write_function_pointer_trampoline(out, efn, var, f, types);
-        }
-    }
-}
-
-fn write_function_pointer_trampoline(
-    out: &mut OutFile,
-    efn: &ExternFn,
-    var: &Ident,
-    f: &Signature,
-    types: &Types,
-) {
-    out.next_section();
-    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
-    let indirect_call = true;
-    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
-
-    out.next_section();
-    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
-    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
-}
-
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let link_name = mangle::extern_fn(&out.namespace, efn);
-    let indirect_call = false;
-    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
-}
-
-fn write_rust_function_decl_impl(
-    out: &mut OutFile,
-    link_name: &Symbol,
-    sig: &Signature,
-    types: &Types,
-    indirect_call: bool,
-) {
-    if sig.throws {
-        write!(out, "::rust::Str::Repr ");
-    } else {
-        write_extern_return_type_space(out, &sig.ret, types);
-    }
-    write!(out, "{}(", link_name);
-    let mut needs_comma = false;
-    if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, "const ");
-        }
-        write!(out, "{} &self", receiver.ty);
-        needs_comma = true;
-    }
-    for arg in &sig.args {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write_extern_arg(out, arg, types);
-        needs_comma = true;
-    }
-    if indirect_return(sig, types) {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write_return_type(out, &sig.ret);
-        write!(out, "*return$");
-        needs_comma = true;
-    }
-    if indirect_call {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write!(out, "void *");
-    }
-    writeln!(out, ") noexcept;");
-}
-
-fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    for line in efn.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    let local_name = match &efn.sig.receiver {
-        None => efn.ident.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
-    };
-    let invoke = mangle::extern_fn(&out.namespace, efn);
-    let indirect_call = false;
-    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
-}
-
-fn write_rust_function_shim_decl(
-    out: &mut OutFile,
-    local_name: &str,
-    sig: &Signature,
-    indirect_call: bool,
-) {
-    write_return_type(out, &sig.ret);
-    write!(out, "{}(", local_name);
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        write_type_space(out, &arg.ty);
-        write!(out, "{}", arg.ident);
-    }
-    if indirect_call {
-        if !sig.args.is_empty() {
-            write!(out, ", ");
-        }
-        write!(out, "void *extern$");
-    }
-    write!(out, ")");
-    if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, " const");
-        }
-    }
-    if !sig.throws {
-        write!(out, " noexcept");
-    }
-}
-
-fn write_rust_function_shim_impl(
-    out: &mut OutFile,
-    local_name: &str,
-    sig: &Signature,
-    types: &Types,
-    invoke: &Symbol,
-    indirect_call: bool,
-) {
-    if out.header && sig.receiver.is_some() {
-        // We've already defined this inside the struct.
-        return;
-    }
-    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
-    if out.header {
-        writeln!(out, ";");
-        return;
-    }
-    writeln!(out, " {{");
-    for arg in &sig.args {
-        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-            out.include.utility = true;
-            write!(out, "  ::rust::ManuallyDrop<");
-            write_type(out, &arg.ty);
-            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
-        }
-    }
-    write!(out, "  ");
-    let indirect_return = indirect_return(sig, types);
-    if indirect_return {
-        write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
-        writeln!(out, "> return$;");
-        write!(out, "  ");
-    } else if let Some(ret) = &sig.ret {
-        write!(out, "return ");
-        match ret {
-            Type::RustBox(_) => {
-                write_type(out, ret);
-                write!(out, "::from_raw(");
-            }
-            Type::UniquePtr(_) => {
-                write_type(out, ret);
-                write!(out, "(");
-            }
-            Type::Ref(_) => write!(out, "*"),
-            _ => {}
-        }
-    }
-    if sig.throws {
-        write!(out, "::rust::Str::Repr error$ = ");
-    }
-    write!(out, "{}(", invoke);
-    if sig.receiver.is_some() {
-        write!(out, "*this");
-    }
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 || sig.receiver.is_some() {
-            write!(out, ", ");
-        }
-        match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::Str::Repr("),
-            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
-            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
-            _ => {}
-        }
-        write!(out, "{}", arg.ident);
-        match &arg.ty {
-            Type::RustBox(_) => write!(out, ".into_raw()"),
-            Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
-            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
-            _ => {}
-        }
-    }
-    if indirect_return {
-        if !sig.args.is_empty() {
-            write!(out, ", ");
-        }
-        write!(out, "&return$.value");
-    }
-    if indirect_call {
-        if !sig.args.is_empty() || indirect_return {
-            write!(out, ", ");
-        }
-        write!(out, "extern$");
-    }
-    write!(out, ")");
-    if let Some(ret) = &sig.ret {
-        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-            write!(out, ")");
-        }
-    }
-    writeln!(out, ";");
-    if sig.throws {
-        writeln!(out, "  if (error$.ptr) {{");
-        writeln!(out, "    throw ::rust::Error(error$);");
-        writeln!(out, "  }}");
-    }
-    if indirect_return {
-        out.include.utility = true;
-        writeln!(out, "  return ::std::move(return$.value);");
-    }
-    writeln!(out, "}}");
-}
-
-fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
-    match ty {
-        None => write!(out, "void "),
-        Some(ty) => write_type_space(out, ty),
-    }
-}
-
-fn indirect_return(sig: &Signature, types: &Types) -> bool {
-    sig.ret
-        .as_ref()
-        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
-}
-
-fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Type::Ref(ty) => {
-            if ty.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &ty.inner);
-            write!(out, " *");
-        }
-        Type::Str(_) => write!(out, "::rust::Str::Repr"),
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
-        _ => write_type(out, ty),
-    }
-}
-
-fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
-    write_indirect_return_type(out, ty);
-    match ty {
-        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
-        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
-        _ => write_space_after_type(out, ty),
-    }
-}
-
-fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
-    match ty {
-        Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Some(Type::Ref(ty)) => {
-            if ty.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &ty.inner);
-            write!(out, " *");
-        }
-        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
-        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
-        _ => write_return_type(out, ty),
-    }
-}
-
-fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
-    match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Type::Str(_) => write!(out, "::rust::Str::Repr "),
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        _ => write_type_space(out, &arg.ty),
-    }
-    if types.needs_indirect_abi(&arg.ty) {
-        write!(out, "*");
-    }
-    write!(out, "{}", arg.ident);
-}
-
-fn write_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
-            None => write!(out, "{}", ident),
-        },
-        Type::RustBox(ty) => {
-            write!(out, "::rust::Box<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::RustVec(ty) => {
-            write!(out, "::rust::Vec<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::UniquePtr(ptr) => {
-            write!(out, "::std::unique_ptr<");
-            write_type(out, &ptr.inner);
-            write!(out, ">");
-        }
-        Type::CxxVector(ty) => {
-            write!(out, "::std::vector<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::Ref(r) => {
-            if r.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &r.inner);
-            write!(out, " &");
-        }
-        Type::Slice(_) => {
-            // For now, only U8 slices are supported, which are covered separately below
-            unreachable!()
-        }
-        Type::Str(_) => {
-            write!(out, "::rust::Str");
-        }
-        Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<uint8_t>");
-        }
-        Type::Fn(f) => {
-            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
-            match &f.ret {
-                Some(ret) => write_type(out, ret),
-                None => write!(out, "void"),
-            }
-            write!(out, "(");
-            for (i, arg) in f.args.iter().enumerate() {
-                if i > 0 {
-                    write!(out, ", ");
-                }
-                write_type(out, &arg.ty);
-            }
-            write!(out, ")>");
-        }
-        Type::Void(_) => unreachable!(),
-    }
-}
-
-fn write_type_space(out: &mut OutFile, ty: &Type) {
-    write_type(out, ty);
-    write_space_after_type(out, ty);
-}
-
-fn write_space_after_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::Ident(_)
-        | Type::RustBox(_)
-        | Type::UniquePtr(_)
-        | Type::Str(_)
-        | Type::CxxVector(_)
-        | Type::RustVec(_)
-        | Type::SliceRefU8(_)
-        | Type::Fn(_) => write!(out, " "),
-        Type::Ref(_) => {}
-        Type::Void(_) | Type::Slice(_) => unreachable!(),
-    }
-}
-
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_typename(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(ident) => {
-            let mut path = String::new();
-            for name in namespace {
-                path += name;
-                path += "::";
-            }
-            path += &ident.to_string();
-            path
-        }
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
-        _ => unreachable!(),
-    }
-}
-
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
-        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
-        _ => unreachable!(),
-    }
-}
-
-fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
-    fn allow_unique_ptr(ident: &Ident) -> bool {
-        Atom::from(ident).is_none()
-    }
-
-    out.begin_block("extern \"C\"");
-    for ty in types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                out.next_section();
-                write_rust_box_extern(out, inner);
-            }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    out.next_section();
-                    write_rust_vec_extern(out, inner);
-                }
-            }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if allow_unique_ptr(inner) {
-                    out.next_section();
-                    write_unique_ptr(out, inner, types);
-                }
-            }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() {
-                    out.next_section();
-                    write_cxx_vector(out, ty, inner, types);
-                }
-            }
-        }
-    }
-    out.end_block("extern \"C\"");
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
-    for ty in types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, inner);
-            }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    write_rust_vec_impl(out, inner);
-                }
-            }
-        }
-    }
-    out.end_block("namespace cxxbridge02");
-    out.end_block("namespace rust");
-}
-
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
-
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
-    writeln!(
-        out,
-        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
-}
-
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
-    writeln!(
-        out,
-        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
-        inner, instance,
-    );
-    writeln!(
-        out,
-        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
-        instance,
-    );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
-}
-
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
-    writeln!(out, "}}");
-}
-
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "template <>");
-    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge02$rust_vec${}$drop(this);",
-        instance,
-    );
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge02$rust_vec${}$data(this);",
-        instance,
-    );
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
-    writeln!(out, "}}");
-}
-
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
-    let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&out.namespace, &ty);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-
-    write_unique_ptr_common(out, &ty, types);
-
-    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-}
-
-// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
-fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
-    out.include.utility = true;
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
-
-    let can_construct_from_value = match ty {
-        Type::Ident(ident) => types.structs.contains_key(ident),
-        _ => false,
-    };
-
-    writeln!(
-        out,
-        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
-        inner,
-    );
-    writeln!(
-        out,
-        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
-        inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
-    writeln!(out, "}}");
-    if can_construct_from_value {
-        writeln!(
-            out,
-            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
-            instance, inner, inner,
-        );
-        writeln!(
-            out,
-            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
-        );
-        writeln!(out, "}}");
-    }
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
-        instance, inner, inner,
-    );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return ptr.get();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return ptr.release();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  ptr->~unique_ptr();");
-    writeln!(out, "}}");
-}
-
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
-    writeln!(
-        out,
-        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  return s.size();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return s[pos];");
-    writeln!(out, "}}");
-
-    write_unique_ptr_common(out, vector_ty, types);
-
-    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
-}
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 82401ee..c7c48ec 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["README.md"]
 
 [lib]
 proc-macro = true
diff --git a/macro/README.md b/macro/README.md
new file mode 100644
index 0000000..b9c1779
--- /dev/null
+++ b/macro/README.md
@@ -0,0 +1,3 @@
+This directory contains CXX's Rust code generator, which is a procedural macro.
+Users won't depend on this crate directly. Instead they'll invoke its macro
+through the reexport in the main `cxx` crate.
diff --git a/src/error.rs b/src/error.rs
deleted file mode 100644
index 740ab94..0000000
--- a/src/error.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-use std::error::Error as StdError;
-use std::fmt::{self, Display};
-use std::io;
-
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
-
-#[derive(Debug)]
-pub(super) enum Error {
-    MissingOutDir,
-    TargetDir,
-    Io(io::Error),
-}
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
-            Error::TargetDir => write!(f, "failed to locate target dir"),
-            Error::Io(err) => err.fmt(f),
-        }
-    }
-}
-
-impl StdError for Error {
-    fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        match self {
-            Error::Io(err) => Some(err),
-            _ => None,
-        }
-    }
-}
-
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
-    }
-}
diff --git a/src/gen b/src/gen
deleted file mode 120000
index 334e0fb..0000000
--- a/src/gen
+++ /dev/null
@@ -1 +0,0 @@
-../gen
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index cff1e88..7e8e9ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -224,8 +224,7 @@
 //! // build.rs
 //!
 //! fn main() {
-//!     cxx::Build::new()
-//!         .bridge("src/main.rs")  // returns a cc::Build
+//!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
 //!         .file("../demo-cxx/demo.cc")
 //!         .flag("-std=c++11")
 //!         .compile("cxxbridge-demo");
@@ -363,18 +362,14 @@ mod concat;
 
 mod cxx_string;
 mod cxx_vector;
-mod error;
 mod exception;
 mod function;
-mod gen;
 mod opaque;
-mod paths;
 mod result;
 mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
-mod syntax;
 mod unique_ptr;
 mod unwind;
 
@@ -398,107 +393,3 @@ pub mod private {
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
-
-use crate::error::Result;
-use crate::gen::Opt;
-use anyhow::anyhow;
-use std::fs;
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-/// The CXX code generator for constructing and compiling C++ code.
-///
-/// This is intended to be used from Cargo build scripts to execute CXX's
-/// C++ code generator, set up any additional compiler flags depending on
-/// the use case, and make the C++ compiler invocation.
-///
-/// <br>
-///
-/// # Example
-///
-/// Example of a canonical Cargo build script that builds a CXX bridge:
-///
-/// ```no_run
-/// // build.rs
-///
-/// fn main() {
-///     cxx::Build::new()
-///         .bridge("src/main.rs")
-///         .file("../demo-cxx/demo.cc")
-///         .flag("-std=c++11")
-///         .compile("cxxbridge-demo");
-///
-///     println!("cargo:rerun-if-changed=src/main.rs");
-///     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-///     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
-/// }
-/// ```
-///
-/// A runnable working setup with this build script is shown in the
-/// *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
-///
-/// [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
-///
-/// <br>
-///
-/// # Alternatives
-///
-/// For use in non-Cargo builds like Bazel or Buck, CXX provides an
-/// alternate way of invoking the C++ code generator as a standalone command
-/// line tool. The tool is packaged as the `cxxbridge-cmd` crate.
-///
-/// ```bash
-/// $ cargo install cxxbridge-cmd  # or build it from the repo
-///
-/// $ cxxbridge src/main.rs --header > path/to/mybridge.h
-/// $ cxxbridge src/main.rs > path/to/mybridge.cc
-/// ```
-#[must_use]
-pub struct Build {
-    _private: (),
-}
-
-impl Build {
-    /// Begin with a [`cc::Build`] in its default configuration.
-    pub fn new() -> Self {
-        Build { _private: () }
-    }
-
-    /// This returns a [`cc::Build`] on which you should continue to set up
-    /// any additional source files or compiler flags, and lastly call its
-    /// [`compile`] method to execute the C++ build.
-    ///
-    /// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
-    #[must_use]
-    pub fn bridge(&self, rust_source_file: impl AsRef<Path>) -> cc::Build {
-        match try_generate_bridge(rust_source_file.as_ref()) {
-            Ok(build) => build,
-            Err(err) => {
-                let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
-                process::exit(1);
-            }
-        }
-    }
-}
-
-fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
-    let header = gen::do_generate_header(rust_source_file, Opt::default());
-    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
-    fs::create_dir_all(header_path.parent().unwrap())?;
-    fs::write(&header_path, header)?;
-    paths::symlink_header(&header_path, rust_source_file);
-
-    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
-    let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
-    fs::write(&bridge_path, bridge)?;
-    let mut build = paths::cc_build();
-    build.file(&bridge_path);
-
-    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
-    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
-    let _ = fs::remove_file(cxx_h);
-    let _ = fs::write(cxx_h, gen::include::HEADER);
-
-    Ok(build)
-}
diff --git a/src/paths.rs b/src/paths.rs
deleted file mode 100644
index ca183d9..0000000
--- a/src/paths.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-use crate::error::{Error, Result};
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
-
-fn out_dir() -> Result<PathBuf> {
-    env::var_os("OUT_DIR")
-        .map(PathBuf::from)
-        .ok_or(Error::MissingOutDir)
-}
-
-pub(crate) fn cc_build() -> cc::Build {
-    try_cc_build().unwrap_or_default()
-}
-
-fn try_cc_build() -> Result<cc::Build> {
-    let mut build = cc::Build::new();
-    build.include(include_dir()?);
-    build.include(target_dir()?.parent().unwrap());
-    Ok(build)
-}
-
-// Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(path: &Path, original: &Path) {
-    let _ = try_symlink_header(path, original);
-}
-
-fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(original)?;
-    let ref dst = include_dir()?.join(suffix);
-
-    fs::create_dir_all(dst.parent().unwrap())?;
-    let _ = fs::remove_file(dst);
-    symlink_or_copy(path, dst)?;
-
-    let mut file_name = dst.file_name().unwrap().to_os_string();
-    file_name.push(".h");
-    let ref dst2 = dst.with_file_name(file_name);
-    symlink_or_copy(path, dst2)?;
-
-    Ok(())
-}
-
-fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
-    let target_dir = target_dir()?;
-    let mut outer = target_dir.parent().unwrap();
-    let original = canonicalize(original)?;
-    loop {
-        if let Ok(suffix) = original.strip_prefix(outer) {
-            return Ok(suffix.to_owned());
-        }
-        match outer.parent() {
-            Some(parent) => outer = parent,
-            None => return Ok(original.components().skip(1).collect()),
-        }
-    }
-}
-
-pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
-    let mut file_name = path.file_name().unwrap().to_owned();
-    file_name.push(ext);
-
-    let out_dir = out_dir()?;
-    let rel = relative_to_parent_of_target_dir(path)?;
-    Ok(out_dir.join(rel).with_file_name(file_name))
-}
-
-pub(crate) fn include_dir() -> Result<PathBuf> {
-    let target_dir = target_dir()?;
-    Ok(target_dir.join("cxxbridge"))
-}
-
-fn target_dir() -> Result<PathBuf> {
-    let mut dir = out_dir().and_then(canonicalize)?;
-    loop {
-        if dir.ends_with("target") {
-            return Ok(dir);
-        }
-        if !dir.pop() {
-            return Err(Error::TargetDir);
-        }
-    }
-}
-
-#[cfg(not(windows))]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    Ok(fs::canonicalize(path)?)
-}
-
-#[cfg(windows)]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
-    // unable to handle in includes. Use a poor approximation instead.
-    // https://github.com/rust-lang/rust/issues/42869
-    // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(env::current_dir()?.join(path))
-}
-
-#[cfg(unix)]
-use std::os::unix::fs::symlink as symlink_or_copy;
-
-#[cfg(windows)]
-fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
-    use std::os::windows::fs::symlink_file;
-
-    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
-    // require Developer Mode. If it fails, fall back to copying the file.
-    if symlink_file(src, dst).is_err() {
-        fs::copy(src, dst)?;
-    }
-    Ok(())
-}
-
-#[cfg(not(any(unix, windows)))]
-use std::fs::copy as symlink_or_copy;
diff --git a/src/syntax b/src/syntax
deleted file mode 120000
index f400712..0000000
--- a/src/syntax
+++ /dev/null
@@ -1 +0,0 @@
-../syntax
\ No newline at end of file
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
index c84df61..c2d8227 100644
--- a/tests/ffi/Cargo.toml
+++ b/tests/ffi/Cargo.toml
@@ -11,4 +11,4 @@ path = "lib.rs"
 cxx = { path = "../.." }
 
 [build-dependencies]
-cxx = { path = "../.." }
+cxx-build = { path = "../../gen/build" }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 5c1bec3..b970362 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -3,8 +3,7 @@ fn main() {
         return;
     }
 
-    cxx::Build::new()
-        .bridge("lib.rs")
+    cxx_build::bridge("lib.rs")
         .file("tests.cc")
         .flag("-std=c++11")
         .compile("cxx-test-suite");
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 0bd470b..f4068d9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -67,17 +67,25 @@ dependencies = [
 name = "cxx"
 version = "0.2.12"
 dependencies = [
- "anyhow",
  "cc",
- "codespan-reporting",
+ "cxx-build",
  "cxx-test-suite",
  "cxxbridge-macro",
  "link-cplusplus",
+ "rustversion",
+ "trybuild",
+]
+
+[[package]]
+name = "cxx-build"
+version = "0.2.12"
+dependencies = [
+ "anyhow",
+ "cc",
+ "codespan-reporting",
  "proc-macro2",
  "quote",
- "rustversion",
  "syn",
- "trybuild",
 ]
 
 [[package]]
@@ -85,6 +93,7 @@ name = "cxx-test-suite"
 version = "0.0.0"
 dependencies = [
  "cxx",
+ "cxx-build",
 ]
 
 [[package]]
@@ -104,6 +113,7 @@ name = "cxxbridge-demo"
 version = "0.0.0"
 dependencies = [
  "cxx",
+ "cxx-build",
 ]
 
 [[package]]

From 171412c0361267c17b6fad0c22b46d62c6922354 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:32:09 +0000
Subject: [PATCH 484/2232] Disable Buck build


---

diff --git a/.travis.yml b/.travis.yml
index f65f7f8..0243407 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -62,3 +62,7 @@ matrix:
       rust: 1.42.0
       script:
         - cargo run --manifest-path demo-rs/Cargo.toml
+
+  # https://github.com/dtolnay/cxx/pull/167
+  allow_failures:
+    - name: Buck

From b4714a7b52520426c6b594188924b5b474665edf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:43:29 +0000
Subject: [PATCH 485/2232] Merge pull request #167 from dtolnay/split


Split cxx runtime and build components
---

diff --git a/.travis.yml b/.travis.yml
index 6c0ca54..0243407 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,15 +20,15 @@ matrix:
       rust: nightly-x86_64-pc-windows-gnu
       before_script:
         # windows is bad at symlinks
-        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
-        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
+        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
 
     - name: Windows (msvc)
       os: windows
       rust: nightly-x86_64-pc-windows-msvc
       before_script:
-        - rm cmd/src/gen cmd/src/syntax gen/include macro/src/syntax src/gen src/syntax
-        - cp -r include gen; cp -r gen cmd/src; cp -r syntax cmd/src; cp -r syntax macro/src; cp -r gen src; cp -r syntax src
+        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
+        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
 
     - name: Buck
       rust: nightly
@@ -62,3 +62,7 @@ matrix:
       rust: 1.42.0
       script:
         - cargo run --manifest-path demo-rs/Cargo.toml
+
+  # https://github.com/dtolnay/cxx/pull/167
+  allow_failures:
+    - name: Buck
diff --git a/BUCK b/BUCK
index 6a9870e..2339f71 100644
--- a/BUCK
+++ b/BUCK
@@ -5,19 +5,13 @@ rust_library(
     deps = [
         ":core",
         ":macro",
-        "//third-party:anyhow",
-        "//third-party:cc",
-        "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
-        "//third-party:proc-macro2",
-        "//third-party:quote",
-        "//third-party:syn",
     ],
 )
 
 rust_binary(
     name = "codegen",
-    srcs = glob(["cmd/src/**"]),
+    srcs = glob(["gen/cmd/src/**"]),
     crate = "cxxbridge",
     visibility = ["PUBLIC"],
     deps = [
@@ -52,3 +46,17 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "build",
+    srcs = glob(["gen/build/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/BUILD b/BUILD
index 2eea8c7..d63fea7 100644
--- a/BUILD
+++ b/BUILD
@@ -3,25 +3,18 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
-    data = ["src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
         ":cxxbridge-macro",
-        "//third-party:anyhow",
-        "//third-party:cc",
-        "//third-party:codespan-reporting",
         "//third-party:link-cplusplus",
-        "//third-party:proc-macro2",
-        "//third-party:quote",
-        "//third-party:syn",
     ],
 )
 
 rust_binary(
     name = "codegen",
-    srcs = glob(["cmd/src/**/*.rs"]),
-    data = ["cmd/src/gen/include/cxx.h"],
+    srcs = glob(["gen/cmd/src/**/*.rs"]),
+    data = ["gen/cmd/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
@@ -57,3 +50,18 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "build",
+    srcs = glob(["gen/build/src/**/*.rs"]),
+    data = ["gen/build/src/gen/include/cxx.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/Cargo.toml b/Cargo.toml
index a47a842..ea97712 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,25 +15,20 @@ exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 travis-ci = { repository = "dtolnay/cxx" }
 
 [dependencies]
-anyhow = "1.0"
-cc = "1.0.49"
-codespan-reporting = "0.9"
 cxxbridge-macro = { version = "=0.2.12", path = "macro" }
 link-cplusplus = "1.0"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
+cxx-build = { version = "=0.2.12", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.21", features = ["diff"] }
 
 [workspace]
-members = ["cmd", "demo-rs", "macro", "tests/ffi"]
+members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/README.md b/README.md
index 7dc7c8b..59bcdac 100644
--- a/README.md
+++ b/README.md
@@ -219,8 +219,7 @@ set up any additional source files and compiler flags as normal.
 // build.rs
 
 fn main() {
-    cxx::Build::new()
-        .bridge("src/main.rs")  // returns a cc::Build
+    cxx_build::bridge("src/main.rs")  // returns a cc::Build
         .file("../demo-cxx/demo.cc")
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
diff --git a/cmd/Cargo.toml b/cmd/Cargo.toml
deleted file mode 100644
index 742d54b..0000000
--- a/cmd/Cargo.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-[package]
-name = "cxxbridge-cmd"
-version = "0.2.12"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-license = "MIT OR Apache-2.0"
-description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
-repository = "https://github.com/dtolnay/cxx"
-
-[[bin]]
-name = "cxxbridge"
-path = "src/main.rs"
-
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
-[dependencies]
-anyhow = "1.0"
-codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
-quote = "1.0"
-structopt = "0.3"
-syn = { version = "1.0", features = ["full"] }
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/cmd/LICENSE-APACHE b/cmd/LICENSE-APACHE
deleted file mode 120000
index 965b606..0000000
--- a/cmd/LICENSE-APACHE
+++ /dev/null
@@ -1 +0,0 @@
-../LICENSE-APACHE
\ No newline at end of file
diff --git a/cmd/LICENSE-MIT b/cmd/LICENSE-MIT
deleted file mode 120000
index 76219eb..0000000
--- a/cmd/LICENSE-MIT
+++ /dev/null
@@ -1 +0,0 @@
-../LICENSE-MIT
\ No newline at end of file
diff --git a/cmd/src/gen b/cmd/src/gen
deleted file mode 120000
index eb22577..0000000
--- a/cmd/src/gen
+++ /dev/null
@@ -1 +0,0 @@
-../../gen
\ No newline at end of file
diff --git a/cmd/src/lib.rs b/cmd/src/lib.rs
deleted file mode 100644
index 8b1a393..0000000
--- a/cmd/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-// empty
diff --git a/cmd/src/main.rs b/cmd/src/main.rs
deleted file mode 100644
index a20179f..0000000
--- a/cmd/src/main.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-#![allow(
-    clippy::cognitive_complexity,
-    clippy::inherent_to_string,
-    clippy::large_enum_variant,
-    clippy::new_without_default,
-    clippy::toplevel_ref_arg
-)]
-
-mod gen;
-mod syntax;
-
-use gen::include;
-use std::io::{self, Write};
-use std::path::PathBuf;
-use structopt::StructOpt;
-
-#[derive(StructOpt, Debug)]
-#[structopt(
-    name = "cxxbridge",
-    author = "David Tolnay <dtolnay@gmail.com>",
-    about = "https://github.com/dtolnay/cxx",
-    usage = "\
-    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
-    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout",
-    help_message = "Print help information",
-    version_message = "Print version information"
-)]
-struct Opt {
-    /// Input Rust source file containing #[cxx::bridge]
-    #[structopt(parse(from_os_str), required_unless = "header")]
-    input: Option<PathBuf>,
-
-    /// Emit header with declarations only
-    #[structopt(long)]
-    header: bool,
-
-    /// Any additional headers to #include
-    #[structopt(short, long)]
-    include: Vec<String>,
-}
-
-fn write(content: impl AsRef<[u8]>) {
-    let _ = io::stdout().lock().write_all(content.as_ref());
-}
-
-fn main() {
-    let opt = Opt::from_args();
-
-    let gen = gen::Opt {
-        include: opt.include,
-    };
-
-    match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
-        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
-        (None, true) => write(include::HEADER),
-        (None, false) => unreachable!(), // enforced by required_unless
-    }
-}
diff --git a/cmd/src/syntax b/cmd/src/syntax
deleted file mode 120000
index 83b0080..0000000
--- a/cmd/src/syntax
+++ /dev/null
@@ -1 +0,0 @@
-../../syntax
\ No newline at end of file
diff --git a/demo-rs/Cargo.toml b/demo-rs/Cargo.toml
index f7e7f84..d2147ab 100644
--- a/demo-rs/Cargo.toml
+++ b/demo-rs/Cargo.toml
@@ -9,4 +9,4 @@ publish = false
 cxx = { path = ".." }
 
 [build-dependencies]
-cxx = { path = ".." }
+cxx-build = { path = "../gen/build" }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index 71def71..edbb281 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,6 +1,5 @@
 fn main() {
-    cxx::Build::new()
-        .bridge("src/main.rs")
+    cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
diff --git a/gen/README.md b/gen/README.md
new file mode 100644
index 0000000..9786911
--- /dev/null
+++ b/gen/README.md
@@ -0,0 +1,4 @@
+This directory contains CXX's C++ code generator. This code generator has two
+public frontends, one a command-line application (binary) in the *cmd* directory
+and the other a library intended to be used from a build.rs in the *build*
+directory.
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
new file mode 100644
index 0000000..3552524
--- /dev/null
+++ b/gen/build/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "cxx-build"
+version = "0.2.12"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into a Cargo build."
+repository = "https://github.com/dtolnay/cxx"
+
+[badges]
+travis-ci = { repository = "dtolnay/cxx" }
+
+[dependencies]
+anyhow = "1.0"
+cc = "1.0.49"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0", features = ["span-locations"] }
+quote = "1.0"
+syn = { version = "1.0", features = ["full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/build/LICENSE-APACHE b/gen/build/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/build/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/build/LICENSE-MIT b/gen/build/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/build/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
new file mode 100644
index 0000000..740ab94
--- /dev/null
+++ b/gen/build/src/error.rs
@@ -0,0 +1,37 @@
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+
+pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub(super) enum Error {
+    MissingOutDir,
+    TargetDir,
+    Io(io::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
+            Error::TargetDir => write!(f, "failed to locate target dir"),
+            Error::Io(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
+}
diff --git a/gen/build/src/gen b/gen/build/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/build/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
new file mode 100644
index 0000000..5bee67f
--- /dev/null
+++ b/gen/build/src/lib.rs
@@ -0,0 +1,96 @@
+//! The CXX code generator for constructing and compiling C++ code.
+//!
+//! This is intended to be used from Cargo build scripts to execute CXX's
+//! C++ code generator, set up any additional compiler flags depending on
+//! the use case, and make the C++ compiler invocation.
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! Example of a canonical Cargo build script that builds a CXX bridge:
+//!
+//! ```no_run
+//! // build.rs
+//!
+//! fn main() {
+//!     cxx_build::bridge("src/main.rs")
+//!         .file("../demo-cxx/demo.cc")
+//!         .flag("-std=c++11")
+//!         .compile("cxxbridge-demo");
+//!
+//!     println!("cargo:rerun-if-changed=src/main.rs");
+//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
+//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//! }
+//! ```
+//!
+//! A runnable working setup with this build script is shown in the
+//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
+//!
+//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
+//!
+//! <br>
+//!
+//! # Alternatives
+//!
+//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
+//! alternate way of invoking the C++ code generator as a standalone command
+//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
+//!
+//! ```bash
+//! $ cargo install cxxbridge-cmd  # or build it from the repo
+//!
+//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
+//! $ cxxbridge src/main.rs > path/to/mybridge.cc
+//! ```
+
+mod error;
+mod gen;
+mod paths;
+mod syntax;
+
+use crate::error::Result;
+use crate::gen::Opt;
+use anyhow::anyhow;
+use std::fs;
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+/// This returns a [`cc::Build`] on which you should continue to set up any
+/// additional source files or compiler flags, and lastly call its [`compile`]
+/// method to execute the C++ build.
+///
+/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
+#[must_use]
+pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
+    match try_generate_bridge(rust_source_file.as_ref()) {
+        Ok(build) => build,
+        Err(err) => {
+            let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
+            process::exit(1);
+        }
+    }
+}
+
+fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
+    let header = gen::do_generate_header(rust_source_file, Opt::default());
+    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
+    fs::create_dir_all(header_path.parent().unwrap())?;
+    fs::write(&header_path, header)?;
+    paths::symlink_header(&header_path, rust_source_file);
+
+    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
+    let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
+    fs::write(&bridge_path, bridge)?;
+    let mut build = paths::cc_build();
+    build.file(&bridge_path);
+
+    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
+    let _ = fs::remove_file(cxx_h);
+    let _ = fs::write(cxx_h, gen::include::HEADER);
+
+    Ok(build)
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
new file mode 100644
index 0000000..ca183d9
--- /dev/null
+++ b/gen/build/src/paths.rs
@@ -0,0 +1,116 @@
+use crate::error::{Error, Result};
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+
+fn out_dir() -> Result<PathBuf> {
+    env::var_os("OUT_DIR")
+        .map(PathBuf::from)
+        .ok_or(Error::MissingOutDir)
+}
+
+pub(crate) fn cc_build() -> cc::Build {
+    try_cc_build().unwrap_or_default()
+}
+
+fn try_cc_build() -> Result<cc::Build> {
+    let mut build = cc::Build::new();
+    build.include(include_dir()?);
+    build.include(target_dir()?.parent().unwrap());
+    Ok(build)
+}
+
+// Symlink the header file into a predictable place. The header generated from
+// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
+pub(crate) fn symlink_header(path: &Path, original: &Path) {
+    let _ = try_symlink_header(path, original);
+}
+
+fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
+    let suffix = relative_to_parent_of_target_dir(original)?;
+    let ref dst = include_dir()?.join(suffix);
+
+    fs::create_dir_all(dst.parent().unwrap())?;
+    let _ = fs::remove_file(dst);
+    symlink_or_copy(path, dst)?;
+
+    let mut file_name = dst.file_name().unwrap().to_os_string();
+    file_name.push(".h");
+    let ref dst2 = dst.with_file_name(file_name);
+    symlink_or_copy(path, dst2)?;
+
+    Ok(())
+}
+
+fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
+    let target_dir = target_dir()?;
+    let mut outer = target_dir.parent().unwrap();
+    let original = canonicalize(original)?;
+    loop {
+        if let Ok(suffix) = original.strip_prefix(outer) {
+            return Ok(suffix.to_owned());
+        }
+        match outer.parent() {
+            Some(parent) => outer = parent,
+            None => return Ok(original.components().skip(1).collect()),
+        }
+    }
+}
+
+pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
+    let mut file_name = path.file_name().unwrap().to_owned();
+    file_name.push(ext);
+
+    let out_dir = out_dir()?;
+    let rel = relative_to_parent_of_target_dir(path)?;
+    Ok(out_dir.join(rel).with_file_name(file_name))
+}
+
+pub(crate) fn include_dir() -> Result<PathBuf> {
+    let target_dir = target_dir()?;
+    Ok(target_dir.join("cxxbridge"))
+}
+
+fn target_dir() -> Result<PathBuf> {
+    let mut dir = out_dir().and_then(canonicalize)?;
+    loop {
+        if dir.ends_with("target") {
+            return Ok(dir);
+        }
+        if !dir.pop() {
+            return Err(Error::TargetDir);
+        }
+    }
+}
+
+#[cfg(not(windows))]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    Ok(fs::canonicalize(path)?)
+}
+
+#[cfg(windows)]
+fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
+    // unable to handle in includes. Use a poor approximation instead.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    Ok(env::current_dir()?.join(path))
+}
+
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_or_copy;
+
+#[cfg(windows)]
+fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+    use std::os::windows::fs::symlink_file;
+
+    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
+    // require Developer Mode. If it fails, fall back to copying the file.
+    if symlink_file(src, dst).is_err() {
+        fs::copy(src, dst)?;
+    }
+    Ok(())
+}
+
+#[cfg(not(any(unix, windows)))]
+use std::fs::copy as symlink_or_copy;
diff --git a/gen/build/src/syntax b/gen/build/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/build/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
new file mode 100644
index 0000000..742d54b
--- /dev/null
+++ b/gen/cmd/Cargo.toml
@@ -0,0 +1,26 @@
+[package]
+name = "cxxbridge-cmd"
+version = "0.2.12"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
+repository = "https://github.com/dtolnay/cxx"
+
+[[bin]]
+name = "cxxbridge"
+path = "src/main.rs"
+
+[badges]
+travis-ci = { repository = "dtolnay/cxx" }
+
+[dependencies]
+anyhow = "1.0"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0", features = ["span-locations"] }
+quote = "1.0"
+structopt = "0.3"
+syn = { version = "1.0", features = ["full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/LICENSE-APACHE b/gen/cmd/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/cmd/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/cmd/LICENSE-MIT b/gen/cmd/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/cmd/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/cmd/src/gen b/gen/cmd/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/cmd/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/cmd/src/lib.rs b/gen/cmd/src/lib.rs
new file mode 100644
index 0000000..8b1a393
--- /dev/null
+++ b/gen/cmd/src/lib.rs
@@ -0,0 +1 @@
+// empty
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
new file mode 100644
index 0000000..a20179f
--- /dev/null
+++ b/gen/cmd/src/main.rs
@@ -0,0 +1,60 @@
+#![allow(
+    clippy::cognitive_complexity,
+    clippy::inherent_to_string,
+    clippy::large_enum_variant,
+    clippy::new_without_default,
+    clippy::toplevel_ref_arg
+)]
+
+mod gen;
+mod syntax;
+
+use gen::include;
+use std::io::{self, Write};
+use std::path::PathBuf;
+use structopt::StructOpt;
+
+#[derive(StructOpt, Debug)]
+#[structopt(
+    name = "cxxbridge",
+    author = "David Tolnay <dtolnay@gmail.com>",
+    about = "https://github.com/dtolnay/cxx",
+    usage = "\
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit rust/cxx.h header to stdout",
+    help_message = "Print help information",
+    version_message = "Print version information"
+)]
+struct Opt {
+    /// Input Rust source file containing #[cxx::bridge]
+    #[structopt(parse(from_os_str), required_unless = "header")]
+    input: Option<PathBuf>,
+
+    /// Emit header with declarations only
+    #[structopt(long)]
+    header: bool,
+
+    /// Any additional headers to #include
+    #[structopt(short, long)]
+    include: Vec<String>,
+}
+
+fn write(content: impl AsRef<[u8]>) {
+    let _ = io::stdout().lock().write_all(content.as_ref());
+}
+
+fn main() {
+    let opt = Opt::from_args();
+
+    let gen = gen::Opt {
+        include: opt.include,
+    };
+
+    match (opt.input, opt.header) {
+        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
+        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
+        (None, true) => write(include::HEADER),
+        (None, false) => unreachable!(), // enforced by required_unless
+    }
+}
diff --git a/gen/cmd/src/syntax b/gen/cmd/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/cmd/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/error.rs b/gen/error.rs
deleted file mode 100644
index 2e8ecc4..0000000
--- a/gen/error.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use crate::syntax;
-use anyhow::anyhow;
-use codespan_reporting::diagnostic::{Diagnostic, Label};
-use codespan_reporting::files::SimpleFiles;
-use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
-use codespan_reporting::term::{self, Config};
-use std::error::Error as StdError;
-use std::fmt::{self, Display};
-use std::io::{self, Write};
-use std::ops::Range;
-use std::path::Path;
-use std::process;
-
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
-
-#[derive(Debug)]
-pub(super) enum Error {
-    NoBridgeMod,
-    OutOfLineMod,
-    Io(io::Error),
-    Syn(syn::Error),
-}
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
-            Error::Io(err) => err.fmt(f),
-            Error::Syn(err) => err.fmt(f),
-        }
-    }
-}
-
-impl StdError for Error {
-    fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        match self {
-            Error::Io(err) => Some(err),
-            Error::Syn(err) => Some(err),
-            _ => None,
-        }
-    }
-}
-
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
-    }
-}
-
-impl From<syn::Error> for Error {
-    fn from(err: syn::Error) -> Self {
-        Error::Syn(err)
-    }
-}
-
-pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
-    match error {
-        Error::Syn(syn_error) => {
-            let writer = StandardStream::stderr(ColorChoice::Auto);
-            let ref mut stderr = writer.lock();
-            for error in syn_error {
-                let _ = writeln!(stderr);
-                display_syn_error(stderr, path, source, error);
-            }
-        }
-        _ => eprintln!("cxxbridge: {:?}", anyhow!(error)),
-    }
-    process::exit(1);
-}
-
-fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
-    let span = error.span();
-    let start = span.start();
-    let end = span.end();
-
-    let mut start_offset = 0;
-    for _ in 1..start.line {
-        start_offset += source[start_offset..].find('\n').unwrap() + 1;
-    }
-    start_offset += start.column;
-
-    let mut end_offset = start_offset;
-    if start.line == end.line {
-        end_offset -= start.column;
-    } else {
-        for _ in 0..end.line - start.line {
-            end_offset += source[end_offset..].find('\n').unwrap() + 1;
-        }
-    }
-    end_offset += end.column;
-
-    let mut files = SimpleFiles::new();
-    let file = files.add(path.to_string_lossy(), source);
-
-    let diagnostic = diagnose(file, start_offset..end_offset, error);
-
-    let config = Config::default();
-    let _ = term::emit(stderr, &config, &files, &diagnostic);
-}
-
-fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
-    let message = error.to_string();
-    let info = syntax::error::ERRORS
-        .iter()
-        .find(|e| message.contains(e.msg));
-    let mut diagnostic = Diagnostic::error().with_message(&message);
-    let mut label = Label::primary(file, range);
-    if let Some(info) = info {
-        label.message = info.label.map_or(message, str::to_owned);
-        diagnostic.labels.push(label);
-        diagnostic.notes.extend(info.note.map(str::to_owned));
-    } else {
-        label.message = message;
-        diagnostic.labels.push(label);
-    }
-    diagnostic.code = Some("cxxbridge".to_owned());
-    diagnostic
-}
diff --git a/gen/include b/gen/include
deleted file mode 120000
index f5030fe..0000000
--- a/gen/include
+++ /dev/null
@@ -1 +0,0 @@
-../include
\ No newline at end of file
diff --git a/gen/include.rs b/gen/include.rs
deleted file mode 100644
index 129a8e6..0000000
--- a/gen/include.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-use std::fmt::{self, Display};
-
-pub static HEADER: &str = include_str!("include/cxx.h");
-
-pub fn get(guard: &str) -> &'static str {
-    let ifndef = format!("#ifndef {}", guard);
-    let endif = format!("#endif // {}", guard);
-    let begin = find_line(&ifndef);
-    let end = find_line(&endif);
-    if let (Some(begin), Some(end)) = (begin, end) {
-        &HEADER[begin..end + endif.len()]
-    } else {
-        panic!("not found in cxx.h header: {}", guard)
-    }
-}
-
-fn find_line(line: &str) -> Option<usize> {
-    let mut offset = 0;
-    loop {
-        offset += HEADER[offset..].find(line)?;
-        let rest = &HEADER[offset + line.len()..];
-        if rest.starts_with('\n') || rest.starts_with('\r') {
-            return Some(offset);
-        }
-        offset += line.len();
-    }
-}
-
-#[derive(Default, PartialEq)]
-pub struct Includes {
-    custom: Vec<String>,
-    pub array: bool,
-    pub cstddef: bool,
-    pub cstdint: bool,
-    pub cstring: bool,
-    pub exception: bool,
-    pub memory: bool,
-    pub string: bool,
-    pub type_traits: bool,
-    pub utility: bool,
-    pub vector: bool,
-    pub base_tsd: bool,
-}
-
-impl Includes {
-    pub fn new() -> Self {
-        Includes::default()
-    }
-
-    pub fn insert(&mut self, include: String) {
-        self.custom.push(include);
-    }
-}
-
-impl Extend<String> for Includes {
-    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
-        self.custom.extend(iter);
-    }
-}
-
-impl Display for Includes {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for include in &self.custom {
-            writeln!(f, "#include \"{}\"", include.escape_default())?;
-        }
-        if self.array {
-            writeln!(f, "#include <array>")?;
-        }
-        if self.cstddef {
-            writeln!(f, "#include <cstddef>")?;
-        }
-        if self.cstdint {
-            writeln!(f, "#include <cstdint>")?;
-        }
-        if self.cstring {
-            writeln!(f, "#include <cstring>")?;
-        }
-        if self.exception {
-            writeln!(f, "#include <exception>")?;
-        }
-        if self.memory {
-            writeln!(f, "#include <memory>")?;
-        }
-        if self.string {
-            writeln!(f, "#include <string>")?;
-        }
-        if self.type_traits {
-            writeln!(f, "#include <type_traits>")?;
-        }
-        if self.utility {
-            writeln!(f, "#include <utility>")?;
-        }
-        if self.vector {
-            writeln!(f, "#include <vector>")?;
-        }
-        if self.base_tsd {
-            writeln!(f, "#if defined(_WIN32)")?;
-            writeln!(f, "#include <BaseTsd.h>")?;
-            writeln!(f, "#endif")?;
-        }
-        if *self != Self::default() {
-            writeln!(f)?;
-        }
-        Ok(())
-    }
-}
diff --git a/gen/mod.rs b/gen/mod.rs
deleted file mode 100644
index 928c6ec..0000000
--- a/gen/mod.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Functionality that is shared between the cxx::generate_bridge entry point and
-// the cmd.
-
-mod error;
-pub(super) mod include;
-pub(super) mod out;
-mod write;
-
-use self::error::{format_err, Error, Result};
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{self, check, Types};
-use quote::quote;
-use std::fs;
-use std::path::Path;
-use syn::{Attribute, File, Item};
-
-struct Input {
-    namespace: Namespace,
-    module: Vec<Item>,
-}
-
-#[derive(Default)]
-pub(super) struct Opt {
-    /// Any additional headers to #include
-    pub include: Vec<String>,
-}
-
-pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
-    let header = false;
-    generate(path, opt, header)
-}
-
-pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
-    let header = true;
-    generate(path, opt, header)
-}
-
-fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
-    let source = match fs::read_to_string(path) {
-        Ok(source) => source,
-        Err(err) => format_err(path, "", Error::Io(err)),
-    };
-    match (|| -> Result<_> {
-        let syntax = syn::parse_file(&source)?;
-        let bridge = find_bridge_mod(syntax)?;
-        let apis = syntax::parse_items(bridge.module)?;
-        let types = Types::collect(&apis)?;
-        check::typecheck(&apis, &types)?;
-        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
-        Ok(out)
-    })() {
-        Ok(out) => out.content(),
-        Err(err) => format_err(path, &source, err),
-    }
-}
-
-fn find_bridge_mod(syntax: File) -> Result<Input> {
-    for item in syntax.items {
-        if let Item::Mod(item) = item {
-            for attr in &item.attrs {
-                let path = &attr.path;
-                if quote!(#path).to_string() == "cxx :: bridge" {
-                    let module = match item.content {
-                        Some(module) => module.1,
-                        None => {
-                            return Err(Error::Syn(syn::Error::new_spanned(
-                                item,
-                                Error::OutOfLineMod,
-                            )));
-                        }
-                    };
-                    let namespace = parse_args(attr)?;
-                    return Ok(Input { namespace, module });
-                }
-            }
-        }
-    }
-    Err(Error::NoBridgeMod)
-}
-
-fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
-    if attr.tokens.is_empty() {
-        Ok(Namespace::none())
-    } else {
-        attr.parse_args()
-    }
-}
diff --git a/gen/out.rs b/gen/out.rs
deleted file mode 100644
index 08bf85f..0000000
--- a/gen/out.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use crate::gen::include::Includes;
-use crate::syntax::namespace::Namespace;
-use std::cell::RefCell;
-use std::fmt::{self, Arguments, Write};
-
-pub(crate) struct OutFile {
-    pub namespace: Namespace,
-    pub header: bool,
-    pub include: Includes,
-    content: RefCell<Content>,
-}
-
-struct Content {
-    bytes: Vec<u8>,
-    section_pending: bool,
-    blocks_pending: Vec<&'static str>,
-}
-
-impl OutFile {
-    pub fn new(namespace: Namespace, header: bool) -> Self {
-        OutFile {
-            namespace,
-            header,
-            include: Includes::new(),
-            content: RefCell::new(Content {
-                bytes: Vec::new(),
-                section_pending: false,
-                blocks_pending: Vec::new(),
-            }),
-        }
-    }
-
-    // Write a blank line if the preceding section had any contents.
-    pub fn next_section(&mut self) {
-        let content = self.content.get_mut();
-        content.section_pending = true;
-    }
-
-    pub fn begin_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        content.blocks_pending.push(block);
-    }
-
-    pub fn end_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        if content.blocks_pending.pop().is_none() {
-            content.bytes.extend_from_slice(b"} // ");
-            content.bytes.extend_from_slice(block.as_bytes());
-            content.bytes.push(b'\n');
-            content.section_pending = true;
-        }
-    }
-
-    pub fn prepend(&mut self, section: String) {
-        let content = self.content.get_mut();
-        content.bytes.splice(..0, section.into_bytes());
-    }
-
-    pub fn write_fmt(&self, args: Arguments) {
-        let content = &mut *self.content.borrow_mut();
-        Write::write_fmt(content, args).unwrap();
-    }
-
-    pub fn content(&self) -> Vec<u8> {
-        self.content.borrow().bytes.clone()
-    }
-}
-
-impl Write for Content {
-    fn write_str(&mut self, s: &str) -> fmt::Result {
-        if !s.is_empty() {
-            if !self.blocks_pending.is_empty() {
-                if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
-                }
-                for block in self.blocks_pending.drain(..) {
-                    self.bytes.extend_from_slice(block.as_bytes());
-                    self.bytes.extend_from_slice(b" {\n");
-                }
-                self.section_pending = false;
-            } else if self.section_pending {
-                if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
-                }
-                self.section_pending = false;
-            }
-            self.bytes.extend_from_slice(s.as_bytes());
-        }
-        Ok(())
-    }
-}
diff --git a/gen/src/error.rs b/gen/src/error.rs
new file mode 100644
index 0000000..2e8ecc4
--- /dev/null
+++ b/gen/src/error.rs
@@ -0,0 +1,119 @@
+use crate::syntax;
+use anyhow::anyhow;
+use codespan_reporting::diagnostic::{Diagnostic, Label};
+use codespan_reporting::files::SimpleFiles;
+use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
+use codespan_reporting::term::{self, Config};
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io::{self, Write};
+use std::ops::Range;
+use std::path::Path;
+use std::process;
+
+pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub(super) enum Error {
+    NoBridgeMod,
+    OutOfLineMod,
+    Io(io::Error),
+    Syn(syn::Error),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
+            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
+            Error::Io(err) => err.fmt(f),
+            Error::Syn(err) => err.fmt(f),
+        }
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        match self {
+            Error::Io(err) => Some(err),
+            Error::Syn(err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
+impl From<io::Error> for Error {
+    fn from(err: io::Error) -> Self {
+        Error::Io(err)
+    }
+}
+
+impl From<syn::Error> for Error {
+    fn from(err: syn::Error) -> Self {
+        Error::Syn(err)
+    }
+}
+
+pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
+    match error {
+        Error::Syn(syn_error) => {
+            let writer = StandardStream::stderr(ColorChoice::Auto);
+            let ref mut stderr = writer.lock();
+            for error in syn_error {
+                let _ = writeln!(stderr);
+                display_syn_error(stderr, path, source, error);
+            }
+        }
+        _ => eprintln!("cxxbridge: {:?}", anyhow!(error)),
+    }
+    process::exit(1);
+}
+
+fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
+    let span = error.span();
+    let start = span.start();
+    let end = span.end();
+
+    let mut start_offset = 0;
+    for _ in 1..start.line {
+        start_offset += source[start_offset..].find('\n').unwrap() + 1;
+    }
+    start_offset += start.column;
+
+    let mut end_offset = start_offset;
+    if start.line == end.line {
+        end_offset -= start.column;
+    } else {
+        for _ in 0..end.line - start.line {
+            end_offset += source[end_offset..].find('\n').unwrap() + 1;
+        }
+    }
+    end_offset += end.column;
+
+    let mut files = SimpleFiles::new();
+    let file = files.add(path.to_string_lossy(), source);
+
+    let diagnostic = diagnose(file, start_offset..end_offset, error);
+
+    let config = Config::default();
+    let _ = term::emit(stderr, &config, &files, &diagnostic);
+}
+
+fn diagnose(file: usize, range: Range<usize>, error: syn::Error) -> Diagnostic<usize> {
+    let message = error.to_string();
+    let info = syntax::error::ERRORS
+        .iter()
+        .find(|e| message.contains(e.msg));
+    let mut diagnostic = Diagnostic::error().with_message(&message);
+    let mut label = Label::primary(file, range);
+    if let Some(info) = info {
+        label.message = info.label.map_or(message, str::to_owned);
+        diagnostic.labels.push(label);
+        diagnostic.notes.extend(info.note.map(str::to_owned));
+    } else {
+        label.message = message;
+        diagnostic.labels.push(label);
+    }
+    diagnostic.code = Some("cxxbridge".to_owned());
+    diagnostic
+}
diff --git a/gen/src/include b/gen/src/include
new file mode 120000
index 0000000..fcffffb
--- /dev/null
+++ b/gen/src/include
@@ -0,0 +1 @@
+../../include
\ No newline at end of file
diff --git a/gen/src/include.rs b/gen/src/include.rs
new file mode 100644
index 0000000..129a8e6
--- /dev/null
+++ b/gen/src/include.rs
@@ -0,0 +1,106 @@
+use std::fmt::{self, Display};
+
+pub static HEADER: &str = include_str!("include/cxx.h");
+
+pub fn get(guard: &str) -> &'static str {
+    let ifndef = format!("#ifndef {}", guard);
+    let endif = format!("#endif // {}", guard);
+    let begin = find_line(&ifndef);
+    let end = find_line(&endif);
+    if let (Some(begin), Some(end)) = (begin, end) {
+        &HEADER[begin..end + endif.len()]
+    } else {
+        panic!("not found in cxx.h header: {}", guard)
+    }
+}
+
+fn find_line(line: &str) -> Option<usize> {
+    let mut offset = 0;
+    loop {
+        offset += HEADER[offset..].find(line)?;
+        let rest = &HEADER[offset + line.len()..];
+        if rest.starts_with('\n') || rest.starts_with('\r') {
+            return Some(offset);
+        }
+        offset += line.len();
+    }
+}
+
+#[derive(Default, PartialEq)]
+pub struct Includes {
+    custom: Vec<String>,
+    pub array: bool,
+    pub cstddef: bool,
+    pub cstdint: bool,
+    pub cstring: bool,
+    pub exception: bool,
+    pub memory: bool,
+    pub string: bool,
+    pub type_traits: bool,
+    pub utility: bool,
+    pub vector: bool,
+    pub base_tsd: bool,
+}
+
+impl Includes {
+    pub fn new() -> Self {
+        Includes::default()
+    }
+
+    pub fn insert(&mut self, include: String) {
+        self.custom.push(include);
+    }
+}
+
+impl Extend<String> for Includes {
+    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
+        self.custom.extend(iter);
+    }
+}
+
+impl Display for Includes {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        for include in &self.custom {
+            writeln!(f, "#include \"{}\"", include.escape_default())?;
+        }
+        if self.array {
+            writeln!(f, "#include <array>")?;
+        }
+        if self.cstddef {
+            writeln!(f, "#include <cstddef>")?;
+        }
+        if self.cstdint {
+            writeln!(f, "#include <cstdint>")?;
+        }
+        if self.cstring {
+            writeln!(f, "#include <cstring>")?;
+        }
+        if self.exception {
+            writeln!(f, "#include <exception>")?;
+        }
+        if self.memory {
+            writeln!(f, "#include <memory>")?;
+        }
+        if self.string {
+            writeln!(f, "#include <string>")?;
+        }
+        if self.type_traits {
+            writeln!(f, "#include <type_traits>")?;
+        }
+        if self.utility {
+            writeln!(f, "#include <utility>")?;
+        }
+        if self.vector {
+            writeln!(f, "#include <vector>")?;
+        }
+        if self.base_tsd {
+            writeln!(f, "#if defined(_WIN32)")?;
+            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#endif")?;
+        }
+        if *self != Self::default() {
+            writeln!(f)?;
+        }
+        Ok(())
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
new file mode 100644
index 0000000..928c6ec
--- /dev/null
+++ b/gen/src/mod.rs
@@ -0,0 +1,87 @@
+// Functionality that is shared between the cxx::generate_bridge entry point and
+// the cmd.
+
+mod error;
+pub(super) mod include;
+pub(super) mod out;
+mod write;
+
+use self::error::{format_err, Error, Result};
+use crate::syntax::namespace::Namespace;
+use crate::syntax::{self, check, Types};
+use quote::quote;
+use std::fs;
+use std::path::Path;
+use syn::{Attribute, File, Item};
+
+struct Input {
+    namespace: Namespace,
+    module: Vec<Item>,
+}
+
+#[derive(Default)]
+pub(super) struct Opt {
+    /// Any additional headers to #include
+    pub include: Vec<String>,
+}
+
+pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
+    let header = false;
+    generate(path, opt, header)
+}
+
+pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
+    let header = true;
+    generate(path, opt, header)
+}
+
+fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
+    let source = match fs::read_to_string(path) {
+        Ok(source) => source,
+        Err(err) => format_err(path, "", Error::Io(err)),
+    };
+    match (|| -> Result<_> {
+        let syntax = syn::parse_file(&source)?;
+        let bridge = find_bridge_mod(syntax)?;
+        let apis = syntax::parse_items(bridge.module)?;
+        let types = Types::collect(&apis)?;
+        check::typecheck(&apis, &types)?;
+        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
+        Ok(out)
+    })() {
+        Ok(out) => out.content(),
+        Err(err) => format_err(path, &source, err),
+    }
+}
+
+fn find_bridge_mod(syntax: File) -> Result<Input> {
+    for item in syntax.items {
+        if let Item::Mod(item) = item {
+            for attr in &item.attrs {
+                let path = &attr.path;
+                if quote!(#path).to_string() == "cxx :: bridge" {
+                    let module = match item.content {
+                        Some(module) => module.1,
+                        None => {
+                            return Err(Error::Syn(syn::Error::new_spanned(
+                                item,
+                                Error::OutOfLineMod,
+                            )));
+                        }
+                    };
+                    let namespace = parse_args(attr)?;
+                    return Ok(Input { namespace, module });
+                }
+            }
+        }
+    }
+    Err(Error::NoBridgeMod)
+}
+
+fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
+    if attr.tokens.is_empty() {
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
+    }
+}
diff --git a/gen/src/out.rs b/gen/src/out.rs
new file mode 100644
index 0000000..08bf85f
--- /dev/null
+++ b/gen/src/out.rs
@@ -0,0 +1,91 @@
+use crate::gen::include::Includes;
+use crate::syntax::namespace::Namespace;
+use std::cell::RefCell;
+use std::fmt::{self, Arguments, Write};
+
+pub(crate) struct OutFile {
+    pub namespace: Namespace,
+    pub header: bool,
+    pub include: Includes,
+    content: RefCell<Content>,
+}
+
+struct Content {
+    bytes: Vec<u8>,
+    section_pending: bool,
+    blocks_pending: Vec<&'static str>,
+}
+
+impl OutFile {
+    pub fn new(namespace: Namespace, header: bool) -> Self {
+        OutFile {
+            namespace,
+            header,
+            include: Includes::new(),
+            content: RefCell::new(Content {
+                bytes: Vec::new(),
+                section_pending: false,
+                blocks_pending: Vec::new(),
+            }),
+        }
+    }
+
+    // Write a blank line if the preceding section had any contents.
+    pub fn next_section(&mut self) {
+        let content = self.content.get_mut();
+        content.section_pending = true;
+    }
+
+    pub fn begin_block(&mut self, block: &'static str) {
+        let content = self.content.get_mut();
+        content.blocks_pending.push(block);
+    }
+
+    pub fn end_block(&mut self, block: &'static str) {
+        let content = self.content.get_mut();
+        if content.blocks_pending.pop().is_none() {
+            content.bytes.extend_from_slice(b"} // ");
+            content.bytes.extend_from_slice(block.as_bytes());
+            content.bytes.push(b'\n');
+            content.section_pending = true;
+        }
+    }
+
+    pub fn prepend(&mut self, section: String) {
+        let content = self.content.get_mut();
+        content.bytes.splice(..0, section.into_bytes());
+    }
+
+    pub fn write_fmt(&self, args: Arguments) {
+        let content = &mut *self.content.borrow_mut();
+        Write::write_fmt(content, args).unwrap();
+    }
+
+    pub fn content(&self) -> Vec<u8> {
+        self.content.borrow().bytes.clone()
+    }
+}
+
+impl Write for Content {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        if !s.is_empty() {
+            if !self.blocks_pending.is_empty() {
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
+                }
+                for block in self.blocks_pending.drain(..) {
+                    self.bytes.extend_from_slice(block.as_bytes());
+                    self.bytes.extend_from_slice(b" {\n");
+                }
+                self.section_pending = false;
+            } else if self.section_pending {
+                if !self.bytes.is_empty() {
+                    self.bytes.push(b'\n');
+                }
+                self.section_pending = false;
+            }
+            self.bytes.extend_from_slice(s.as_bytes());
+        }
+        Ok(())
+    }
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
new file mode 100644
index 0000000..b39d978
--- /dev/null
+++ b/gen/src/write.rs
@@ -0,0 +1,1224 @@
+use crate::gen::out::OutFile;
+use crate::gen::{include, Opt};
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
+use crate::syntax::symbol::Symbol;
+use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use proc_macro2::Ident;
+use std::collections::HashMap;
+
+pub(super) fn gen(
+    namespace: Namespace,
+    apis: &[Api],
+    types: &Types,
+    opt: Opt,
+    header: bool,
+) -> OutFile {
+    let mut out_file = OutFile::new(namespace.clone(), header);
+    let out = &mut out_file;
+
+    if header {
+        writeln!(out, "#pragma once");
+    }
+
+    out.include.extend(opt.include);
+    for api in apis {
+        if let Api::Include(include) = api {
+            out.include.insert(include.value());
+        }
+    }
+
+    write_includes(out, types);
+    write_include_cxxbridge(out, apis, types);
+
+    out.next_section();
+    for name in &namespace {
+        writeln!(out, "namespace {} {{", name);
+    }
+
+    out.next_section();
+    for api in apis {
+        match api {
+            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            _ => {}
+        }
+    }
+
+    let mut methods_for_type = HashMap::new();
+    for api in apis {
+        if let Api::RustFunction(efn) = api {
+            if let Some(receiver) = &efn.sig.receiver {
+                methods_for_type
+                    .entry(&receiver.ty)
+                    .or_insert_with(Vec::new)
+                    .push(efn);
+            }
+        }
+    }
+
+    for api in apis {
+        match api {
+            Api::Struct(strct) => {
+                out.next_section();
+                write_struct(out, strct);
+            }
+            Api::RustType(ety) => {
+                if let Some(methods) = methods_for_type.get(&ety.ident) {
+                    out.next_section();
+                    write_struct_with_methods(out, ety, methods);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    if !header {
+        out.begin_block("extern \"C\"");
+        write_exception_glue(out, apis);
+        for api in apis {
+            let (efn, write): (_, fn(_, _, _)) = match api {
+                Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
+                Api::RustFunction(efn) => (efn, write_rust_function_decl),
+                _ => continue,
+            };
+            out.next_section();
+            write(out, efn, types);
+        }
+        out.end_block("extern \"C\"");
+    }
+
+    for api in apis {
+        if let Api::RustFunction(efn) = api {
+            out.next_section();
+            write_rust_function_shim(out, efn, types);
+        }
+    }
+
+    out.next_section();
+    for name in namespace.iter().rev() {
+        writeln!(out, "}} // namespace {}", name);
+    }
+
+    if !header {
+        out.next_section();
+        write_generic_instantiations(out, types);
+    }
+
+    out.prepend(out.include.to_string());
+
+    out_file
+}
+
+fn write_includes(out: &mut OutFile, types: &Types) {
+    for ty in types {
+        match ty {
+            Type::Ident(ident) => match Atom::from(ident) {
+                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
+                | Some(I64) => out.include.cstdint = true,
+                Some(Usize) => out.include.cstddef = true,
+                Some(CxxString) => out.include.string = true,
+                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+            },
+            Type::RustBox(_) => out.include.type_traits = true,
+            Type::UniquePtr(_) => out.include.memory = true,
+            Type::CxxVector(_) => out.include.vector = true,
+            Type::SliceRefU8(_) => out.include.cstdint = true,
+            _ => {}
+        }
+    }
+}
+
+fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
+    let mut needs_rust_string = false;
+    let mut needs_rust_str = false;
+    let mut needs_rust_slice = false;
+    let mut needs_rust_box = false;
+    let mut needs_rust_vec = false;
+    let mut needs_rust_fn = false;
+    let mut needs_rust_isize = false;
+    for ty in types {
+        match ty {
+            Type::RustBox(_) => {
+                out.include.type_traits = true;
+                needs_rust_box = true;
+            }
+            Type::RustVec(_) => {
+                out.include.array = true;
+                out.include.type_traits = true;
+                needs_rust_vec = true;
+            }
+            Type::Str(_) => {
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_str = true;
+            }
+            Type::Fn(_) => {
+                needs_rust_fn = true;
+            }
+            Type::Slice(_) | Type::SliceRefU8(_) => {
+                needs_rust_slice = true;
+            }
+            ty if ty == Isize => {
+                out.include.base_tsd = true;
+                needs_rust_isize = true;
+            }
+            ty if ty == RustString => {
+                out.include.array = true;
+                out.include.cstdint = true;
+                out.include.string = true;
+                needs_rust_string = true;
+            }
+            _ => {}
+        }
+    }
+
+    let mut needs_rust_error = false;
+    let mut needs_unsafe_bitcopy = false;
+    let mut needs_manually_drop = false;
+    let mut needs_maybe_uninit = false;
+    let mut needs_trycatch = false;
+    for api in apis {
+        match api {
+            Api::CxxFunction(efn) if !out.header => {
+                if efn.throws {
+                    needs_trycatch = true;
+                }
+                for arg in &efn.args {
+                    let bitcopy = match arg.ty {
+                        Type::RustVec(_) => true,
+                        _ => arg.ty == RustString,
+                    };
+                    if bitcopy {
+                        needs_unsafe_bitcopy = true;
+                        break;
+                    }
+                }
+            }
+            Api::RustFunction(efn) if !out.header => {
+                if efn.throws {
+                    out.include.exception = true;
+                    needs_rust_error = true;
+                }
+                for arg in &efn.args {
+                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                        needs_manually_drop = true;
+                        break;
+                    }
+                }
+                if let Some(ret) = &efn.ret {
+                    if types.needs_indirect_abi(ret) {
+                        needs_maybe_uninit = true;
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge02");
+
+    if needs_rust_string
+        || needs_rust_str
+        || needs_rust_slice
+        || needs_rust_box
+        || needs_rust_vec
+        || needs_rust_fn
+        || needs_rust_error
+        || needs_rust_isize
+        || needs_unsafe_bitcopy
+        || needs_manually_drop
+        || needs_maybe_uninit
+        || needs_trycatch
+    {
+        writeln!(out, "// #include \"rust/cxx.h\"");
+    }
+
+    if needs_rust_string {
+        out.next_section();
+        writeln!(out, "struct unsafe_bitcopy_t;");
+    }
+
+    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
+    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
+    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
+    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
+    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
+    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
+    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
+    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
+
+    if needs_manually_drop {
+        out.next_section();
+        out.include.utility = true;
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union ManuallyDrop {{");
+        writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
+        );
+        writeln!(out, "  ~ManuallyDrop() {{}}");
+        writeln!(out, "}};");
+    }
+
+    if needs_maybe_uninit {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union MaybeUninit {{");
+        writeln!(out, "  T value;");
+        writeln!(out, "  MaybeUninit() {{}}");
+        writeln!(out, "  ~MaybeUninit() {{}}");
+        writeln!(out, "}};");
+    }
+
+    out.end_block("namespace cxxbridge02");
+
+    if needs_trycatch {
+        out.begin_block("namespace behavior");
+        out.include.exception = true;
+        out.include.type_traits = true;
+        out.include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
+        writeln!(out);
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename std::enable_if<");
+        writeln!(
+            out,
+            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
+        );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+        out.end_block("namespace behavior");
+    }
+
+    out.end_block("namespace rust");
+}
+
+fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
+    let section = include::get(section);
+    if needed {
+        out.next_section();
+        for line in section.lines() {
+            if !line.trim_start().starts_with("//") {
+                writeln!(out, "{}", line);
+            }
+        }
+    }
+}
+
+fn write_struct(out: &mut OutFile, strct: &Struct) {
+    for line in strct.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", strct.ident);
+    for field in &strct.fields {
+        write!(out, "  ");
+        write_type_space(out, &field.ty);
+        writeln!(out, "{};", field.ident);
+    }
+    writeln!(out, "}};");
+}
+
+fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "struct {};", ident);
+}
+
+fn write_struct_using(out: &mut OutFile, ident: &Ident) {
+    writeln!(out, "using {} = {};", ident, ident);
+}
+
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+    for line in ety.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "struct {} final {{", ety.ident);
+    writeln!(out, "  {}() = delete;", ety.ident);
+    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
+    for method in methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false);
+        writeln!(out, ";");
+    }
+    writeln!(out, "}};");
+}
+
+fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+    let mut has_cxx_throws = false;
+    for api in apis {
+        if let Api::CxxFunction(efn) = api {
+            if efn.throws {
+                has_cxx_throws = true;
+                break;
+            }
+        }
+    }
+
+    if has_cxx_throws {
+        out.next_section();
+        writeln!(
+            out,
+            "const char *cxxbridge02$exception(const char *, size_t);",
+        );
+    }
+}
+
+fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    if efn.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type_space(out, &efn.ret, types);
+    }
+    let mangled = mangle::extern_fn(&out.namespace, efn);
+    write!(out, "{}(", mangled);
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
+        write!(out, "{} &self", receiver.ty);
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 || efn.receiver.is_some() {
+            write!(out, ", ");
+        }
+        if arg.ty == RustString {
+            write!(out, "const ");
+        } else if let Type::RustVec(_) = arg.ty {
+            write!(out, "const ");
+        }
+        write_extern_arg(out, arg, types);
+    }
+    let indirect_return = indirect_return(efn, types);
+    if indirect_return {
+        if !efn.args.is_empty() {
+            write!(out, ", ");
+        }
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
+        write!(out, "*return$");
+    }
+    writeln!(out, ") noexcept {{");
+    write!(out, "  ");
+    write_return_type(out, &efn.ret);
+    match &efn.receiver {
+        None => write!(out, "(*{}$)(", efn.ident),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        write_type(out, &arg.ty);
+    }
+    write!(out, ")");
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
+    }
+    write!(out, " = ");
+    match &efn.receiver {
+        None => write!(out, "{}", efn.ident),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
+    }
+    writeln!(out, ";");
+    write!(out, "  ");
+    if efn.throws {
+        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "  ::rust::behavior::trycatch(");
+        writeln!(out, "      [&] {{");
+        write!(out, "        ");
+    }
+    if indirect_return {
+        write!(out, "new (return$) ");
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
+        write!(out, "(");
+    } else if efn.ret.is_some() {
+        write!(out, "return ");
+    }
+    match &efn.ret {
+        Some(Type::Ref(_)) => write!(out, "&"),
+        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
+        Some(Type::SliceRefU8(_)) if !indirect_return => {
+            write!(out, "::rust::Slice<uint8_t>::Repr(")
+        }
+        _ => {}
+    }
+    match &efn.receiver {
+        None => write!(out, "{}$(", efn.ident),
+        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
+    }
+    for (i, arg) in efn.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        if let Type::RustBox(_) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "::from_raw({})", arg.ident);
+        } else if let Type::UniquePtr(_) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "({})", arg.ident);
+        } else if arg.ty == RustString {
+            write!(
+                out,
+                "::rust::String(::rust::unsafe_bitcopy, *{})",
+                arg.ident,
+            );
+        } else if let Type::RustVec(_) = arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
+        } else if types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
+            write!(out, "::std::move(*{})", arg.ident);
+        } else {
+            write!(out, "{}", arg.ident);
+        }
+    }
+    write!(out, ")");
+    match &efn.ret {
+        Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
+        Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::CxxVector(_)) => write!(
+            out,
+            " /* Use RVO to convert to r-value and move construct */"
+        ),
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        _ => {}
+    }
+    if indirect_return {
+        write!(out, ")");
+    }
+    writeln!(out, ";");
+    if efn.throws {
+        out.include.cstring = true;
+        writeln!(out, "        throw$.ptr = nullptr;");
+        writeln!(out, "      }},");
+        writeln!(out, "      [&](const char *catch$) noexcept {{");
+        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
+        writeln!(
+            out,
+            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
+        );
+        writeln!(out, "      }});");
+        writeln!(out, "  return throw$;");
+    }
+    writeln!(out, "}}");
+    for arg in &efn.args {
+        if let Type::Fn(f) = &arg.ty {
+            let var = &arg.ident;
+            write_function_pointer_trampoline(out, efn, var, f, types);
+        }
+    }
+}
+
+fn write_function_pointer_trampoline(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    var: &Ident,
+    f: &Signature,
+    types: &Types,
+) {
+    out.next_section();
+    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
+    let indirect_call = true;
+    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
+
+    out.next_section();
+    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
+    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
+}
+
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    let link_name = mangle::extern_fn(&out.namespace, efn);
+    let indirect_call = false;
+    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
+}
+
+fn write_rust_function_decl_impl(
+    out: &mut OutFile,
+    link_name: &Symbol,
+    sig: &Signature,
+    types: &Types,
+    indirect_call: bool,
+) {
+    if sig.throws {
+        write!(out, "::rust::Str::Repr ");
+    } else {
+        write_extern_return_type_space(out, &sig.ret, types);
+    }
+    write!(out, "{}(", link_name);
+    let mut needs_comma = false;
+    if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, "const ");
+        }
+        write!(out, "{} &self", receiver.ty);
+        needs_comma = true;
+    }
+    for arg in &sig.args {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write_extern_arg(out, arg, types);
+        needs_comma = true;
+    }
+    if indirect_return(sig, types) {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write_return_type(out, &sig.ret);
+        write!(out, "*return$");
+        needs_comma = true;
+    }
+    if indirect_call {
+        if needs_comma {
+            write!(out, ", ");
+        }
+        write!(out, "void *");
+    }
+    writeln!(out, ") noexcept;");
+}
+
+fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+    for line in efn.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    let local_name = match &efn.sig.receiver {
+        None => efn.ident.to_string(),
+        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
+    };
+    let invoke = mangle::extern_fn(&out.namespace, efn);
+    let indirect_call = false;
+    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
+}
+
+fn write_rust_function_shim_decl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    indirect_call: bool,
+) {
+    write_return_type(out, &sig.ret);
+    write!(out, "{}(", local_name);
+    for (i, arg) in sig.args.iter().enumerate() {
+        if i > 0 {
+            write!(out, ", ");
+        }
+        write_type_space(out, &arg.ty);
+        write!(out, "{}", arg.ident);
+    }
+    if indirect_call {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "void *extern$");
+    }
+    write!(out, ")");
+    if let Some(receiver) = &sig.receiver {
+        if receiver.mutability.is_none() {
+            write!(out, " const");
+        }
+    }
+    if !sig.throws {
+        write!(out, " noexcept");
+    }
+}
+
+fn write_rust_function_shim_impl(
+    out: &mut OutFile,
+    local_name: &str,
+    sig: &Signature,
+    types: &Types,
+    invoke: &Symbol,
+    indirect_call: bool,
+) {
+    if out.header && sig.receiver.is_some() {
+        // We've already defined this inside the struct.
+        return;
+    }
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
+    if out.header {
+        writeln!(out, ";");
+        return;
+    }
+    writeln!(out, " {{");
+    for arg in &sig.args {
+        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+            out.include.utility = true;
+            write!(out, "  ::rust::ManuallyDrop<");
+            write_type(out, &arg.ty);
+            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
+        }
+    }
+    write!(out, "  ");
+    let indirect_return = indirect_return(sig, types);
+    if indirect_return {
+        write!(out, "::rust::MaybeUninit<");
+        write_type(out, sig.ret.as_ref().unwrap());
+        writeln!(out, "> return$;");
+        write!(out, "  ");
+    } else if let Some(ret) = &sig.ret {
+        write!(out, "return ");
+        match ret {
+            Type::RustBox(_) => {
+                write_type(out, ret);
+                write!(out, "::from_raw(");
+            }
+            Type::UniquePtr(_) => {
+                write_type(out, ret);
+                write!(out, "(");
+            }
+            Type::Ref(_) => write!(out, "*"),
+            _ => {}
+        }
+    }
+    if sig.throws {
+        write!(out, "::rust::Str::Repr error$ = ");
+    }
+    write!(out, "{}(", invoke);
+    if sig.receiver.is_some() {
+        write!(out, "*this");
+    }
+    for (i, arg) in sig.args.iter().enumerate() {
+        if i > 0 || sig.receiver.is_some() {
+            write!(out, ", ");
+        }
+        match &arg.ty {
+            Type::Str(_) => write!(out, "::rust::Str::Repr("),
+            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
+            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+            _ => {}
+        }
+        write!(out, "{}", arg.ident);
+        match &arg.ty {
+            Type::RustBox(_) => write!(out, ".into_raw()"),
+            Type::UniquePtr(_) => write!(out, ".release()"),
+            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
+            _ => {}
+        }
+    }
+    if indirect_return {
+        if !sig.args.is_empty() {
+            write!(out, ", ");
+        }
+        write!(out, "&return$.value");
+    }
+    if indirect_call {
+        if !sig.args.is_empty() || indirect_return {
+            write!(out, ", ");
+        }
+        write!(out, "extern$");
+    }
+    write!(out, ")");
+    if let Some(ret) = &sig.ret {
+        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+            write!(out, ")");
+        }
+    }
+    writeln!(out, ";");
+    if sig.throws {
+        writeln!(out, "  if (error$.ptr) {{");
+        writeln!(out, "    throw ::rust::Error(error$);");
+        writeln!(out, "  }}");
+    }
+    if indirect_return {
+        out.include.utility = true;
+        writeln!(out, "  return ::std::move(return$.value);");
+    }
+    writeln!(out, "}}");
+}
+
+fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
+    match ty {
+        None => write!(out, "void "),
+        Some(ty) => write_type_space(out, ty),
+    }
+}
+
+fn indirect_return(sig: &Signature, types: &Types) -> bool {
+    sig.ret
+        .as_ref()
+        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
+}
+
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::RustBox(ty) | Type::UniquePtr(ty) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Type::Ref(ty) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
+        Type::Str(_) => write!(out, "::rust::Str::Repr"),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
+        _ => write_type(out, ty),
+    }
+}
+
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
+    write_indirect_return_type(out, ty);
+    match ty {
+        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
+        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
+        _ => write_space_after_type(out, ty),
+    }
+}
+
+fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
+    match ty {
+        Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Some(Type::Ref(ty)) => {
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &ty.inner);
+            write!(out, " *");
+        }
+        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
+        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
+        Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
+        _ => write_return_type(out, ty),
+    }
+}
+
+fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
+    match &arg.ty {
+        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
+            write_type_space(out, &ty.inner);
+            write!(out, "*");
+        }
+        Type::Str(_) => write!(out, "::rust::Str::Repr "),
+        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
+        _ => write_type_space(out, &arg.ty),
+    }
+    if types.needs_indirect_abi(&arg.ty) {
+        write!(out, "*");
+    }
+    write!(out, "{}", arg.ident);
+}
+
+fn write_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::Ident(ident) => match Atom::from(ident) {
+            Some(Bool) => write!(out, "bool"),
+            Some(U8) => write!(out, "uint8_t"),
+            Some(U16) => write!(out, "uint16_t"),
+            Some(U32) => write!(out, "uint32_t"),
+            Some(U64) => write!(out, "uint64_t"),
+            Some(Usize) => write!(out, "size_t"),
+            Some(I8) => write!(out, "int8_t"),
+            Some(I16) => write!(out, "int16_t"),
+            Some(I32) => write!(out, "int32_t"),
+            Some(I64) => write!(out, "int64_t"),
+            Some(Isize) => write!(out, "::rust::isize"),
+            Some(F32) => write!(out, "float"),
+            Some(F64) => write!(out, "double"),
+            Some(CxxString) => write!(out, "::std::string"),
+            Some(RustString) => write!(out, "::rust::String"),
+            None => write!(out, "{}", ident),
+        },
+        Type::RustBox(ty) => {
+            write!(out, "::rust::Box<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::RustVec(ty) => {
+            write!(out, "::rust::Vec<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::UniquePtr(ptr) => {
+            write!(out, "::std::unique_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
+        Type::CxxVector(ty) => {
+            write!(out, "::std::vector<");
+            write_type(out, &ty.inner);
+            write!(out, ">");
+        }
+        Type::Ref(r) => {
+            if r.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write_type(out, &r.inner);
+            write!(out, " &");
+        }
+        Type::Slice(_) => {
+            // For now, only U8 slices are supported, which are covered separately below
+            unreachable!()
+        }
+        Type::Str(_) => {
+            write!(out, "::rust::Str");
+        }
+        Type::SliceRefU8(_) => {
+            write!(out, "::rust::Slice<uint8_t>");
+        }
+        Type::Fn(f) => {
+            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
+            match &f.ret {
+                Some(ret) => write_type(out, ret),
+                None => write!(out, "void"),
+            }
+            write!(out, "(");
+            for (i, arg) in f.args.iter().enumerate() {
+                if i > 0 {
+                    write!(out, ", ");
+                }
+                write_type(out, &arg.ty);
+            }
+            write!(out, ")>");
+        }
+        Type::Void(_) => unreachable!(),
+    }
+}
+
+fn write_type_space(out: &mut OutFile, ty: &Type) {
+    write_type(out, ty);
+    write_space_after_type(out, ty);
+}
+
+fn write_space_after_type(out: &mut OutFile, ty: &Type) {
+    match ty {
+        Type::Ident(_)
+        | Type::RustBox(_)
+        | Type::UniquePtr(_)
+        | Type::Str(_)
+        | Type::CxxVector(_)
+        | Type::RustVec(_)
+        | Type::SliceRefU8(_)
+        | Type::Fn(_) => write!(out, " "),
+        Type::Ref(_) => {}
+        Type::Void(_) | Type::Slice(_) => unreachable!(),
+    }
+}
+
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(ident) => {
+            let mut path = String::new();
+            for name in namespace {
+                path += name;
+                path += "::";
+            }
+            path += &ident.to_string();
+            path
+        }
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        _ => unreachable!(),
+    }
+}
+
+// Only called for legal referent types of unique_ptr and element types of
+// std::vector and Vec.
+fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+    match ty {
+        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
+        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        _ => unreachable!(),
+    }
+}
+
+fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
+    fn allow_unique_ptr(ident: &Ident) -> bool {
+        Atom::from(ident).is_none()
+    }
+
+    out.begin_block("extern \"C\"");
+    for ty in types {
+        if let Type::RustBox(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                out.next_section();
+                write_rust_box_extern(out, inner);
+            }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_rust_vec_extern(out, inner);
+                }
+            }
+        } else if let Type::UniquePtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if allow_unique_ptr(inner) {
+                    out.next_section();
+                    write_unique_ptr(out, inner, types);
+                }
+            }
+        } else if let Type::CxxVector(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(inner).is_none() {
+                    out.next_section();
+                    write_cxx_vector(out, ty, inner, types);
+                }
+            }
+        }
+    }
+    out.end_block("extern \"C\"");
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge02");
+    for ty in types {
+        if let Type::RustBox(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                write_rust_box_impl(out, inner);
+            }
+        } else if let Type::RustVec(ty) = ty {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(inner).is_none() {
+                    write_rust_vec_impl(out, inner);
+                }
+            }
+        }
+    }
+    out.end_block("namespace cxxbridge02");
+    out.end_block("namespace rust");
+}
+
+fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    for name in &out.namespace {
+        inner += name;
+        inner += "::";
+    }
+    inner += &ident.to_string();
+    let instance = inner.replace("::", "$");
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
+}
+
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        inner, instance,
+    );
+    writeln!(
+        out,
+        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
+        instance,
+    );
+    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
+}
+
+fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
+    let mut inner = String::new();
+    for name in &out.namespace {
+        inner += name;
+        inner += "::";
+    }
+    inner += &ident.to_string();
+    let instance = inner.replace("::", "$");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
+    writeln!(out, "}}");
+}
+
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "template <>");
+    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
+    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$drop(this);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge02$rust_vec${}$data(this);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
+    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
+    writeln!(out, "}}");
+}
+
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+    let ty = Type::Ident(ident.clone());
+    let instance = to_mangled(&out.namespace, &ty);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+
+    write_unique_ptr_common(out, &ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+}
+
+// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
+fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.utility = true;
+    let inner = to_typename(&out.namespace, ty);
+    let instance = to_mangled(&out.namespace, ty);
+
+    let can_construct_from_value = match ty {
+        Type::Ident(ident) => types.structs.contains_key(ident),
+        _ => false,
+    };
+
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    if can_construct_from_value {
+        writeln!(
+            out,
+            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return ptr.get();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return ptr.release();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  ptr->~unique_ptr();");
+    writeln!(out, "}}");
+}
+
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+    let element = Type::Ident(element.clone());
+    let inner = to_typename(&out.namespace, &element);
+    let instance = to_mangled(&out.namespace, &element);
+
+    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(
+        out,
+        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  return s.size();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return s[pos];");
+    writeln!(out, "}}");
+
+    write_unique_ptr_common(out, vector_ty, types);
+
+    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
+}
diff --git a/gen/write.rs b/gen/write.rs
deleted file mode 100644
index b39d978..0000000
--- a/gen/write.rs
+++ /dev/null
@@ -1,1224 +0,0 @@
-use crate::gen::out::OutFile;
-use crate::gen::{include, Opt};
-use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
-use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
-use proc_macro2::Ident;
-use std::collections::HashMap;
-
-pub(super) fn gen(
-    namespace: Namespace,
-    apis: &[Api],
-    types: &Types,
-    opt: Opt,
-    header: bool,
-) -> OutFile {
-    let mut out_file = OutFile::new(namespace.clone(), header);
-    let out = &mut out_file;
-
-    if header {
-        writeln!(out, "#pragma once");
-    }
-
-    out.include.extend(opt.include);
-    for api in apis {
-        if let Api::Include(include) = api {
-            out.include.insert(include.value());
-        }
-    }
-
-    write_includes(out, types);
-    write_include_cxxbridge(out, apis, types);
-
-    out.next_section();
-    for name in &namespace {
-        writeln!(out, "namespace {} {{", name);
-    }
-
-    out.next_section();
-    for api in apis {
-        match api {
-            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
-            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
-            _ => {}
-        }
-    }
-
-    let mut methods_for_type = HashMap::new();
-    for api in apis {
-        if let Api::RustFunction(efn) = api {
-            if let Some(receiver) = &efn.sig.receiver {
-                methods_for_type
-                    .entry(&receiver.ty)
-                    .or_insert_with(Vec::new)
-                    .push(efn);
-            }
-        }
-    }
-
-    for api in apis {
-        match api {
-            Api::Struct(strct) => {
-                out.next_section();
-                write_struct(out, strct);
-            }
-            Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.ident) {
-                    out.next_section();
-                    write_struct_with_methods(out, ety, methods);
-                }
-            }
-            _ => {}
-        }
-    }
-
-    if !header {
-        out.begin_block("extern \"C\"");
-        write_exception_glue(out, apis);
-        for api in apis {
-            let (efn, write): (_, fn(_, _, _)) = match api {
-                Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
-                Api::RustFunction(efn) => (efn, write_rust_function_decl),
-                _ => continue,
-            };
-            out.next_section();
-            write(out, efn, types);
-        }
-        out.end_block("extern \"C\"");
-    }
-
-    for api in apis {
-        if let Api::RustFunction(efn) = api {
-            out.next_section();
-            write_rust_function_shim(out, efn, types);
-        }
-    }
-
-    out.next_section();
-    for name in namespace.iter().rev() {
-        writeln!(out, "}} // namespace {}", name);
-    }
-
-    if !header {
-        out.next_section();
-        write_generic_instantiations(out, types);
-    }
-
-    out.prepend(out.include.to_string());
-
-    out_file
-}
-
-fn write_includes(out: &mut OutFile, types: &Types) {
-    for ty in types {
-        match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
-                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
-                | Some(I64) => out.include.cstdint = true,
-                Some(Usize) => out.include.cstddef = true,
-                Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
-            },
-            Type::RustBox(_) => out.include.type_traits = true,
-            Type::UniquePtr(_) => out.include.memory = true,
-            Type::CxxVector(_) => out.include.vector = true,
-            Type::SliceRefU8(_) => out.include.cstdint = true,
-            _ => {}
-        }
-    }
-}
-
-fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
-    let mut needs_rust_string = false;
-    let mut needs_rust_str = false;
-    let mut needs_rust_slice = false;
-    let mut needs_rust_box = false;
-    let mut needs_rust_vec = false;
-    let mut needs_rust_fn = false;
-    let mut needs_rust_isize = false;
-    for ty in types {
-        match ty {
-            Type::RustBox(_) => {
-                out.include.type_traits = true;
-                needs_rust_box = true;
-            }
-            Type::RustVec(_) => {
-                out.include.array = true;
-                out.include.type_traits = true;
-                needs_rust_vec = true;
-            }
-            Type::Str(_) => {
-                out.include.cstdint = true;
-                out.include.string = true;
-                needs_rust_str = true;
-            }
-            Type::Fn(_) => {
-                needs_rust_fn = true;
-            }
-            Type::Slice(_) | Type::SliceRefU8(_) => {
-                needs_rust_slice = true;
-            }
-            ty if ty == Isize => {
-                out.include.base_tsd = true;
-                needs_rust_isize = true;
-            }
-            ty if ty == RustString => {
-                out.include.array = true;
-                out.include.cstdint = true;
-                out.include.string = true;
-                needs_rust_string = true;
-            }
-            _ => {}
-        }
-    }
-
-    let mut needs_rust_error = false;
-    let mut needs_unsafe_bitcopy = false;
-    let mut needs_manually_drop = false;
-    let mut needs_maybe_uninit = false;
-    let mut needs_trycatch = false;
-    for api in apis {
-        match api {
-            Api::CxxFunction(efn) if !out.header => {
-                if efn.throws {
-                    needs_trycatch = true;
-                }
-                for arg in &efn.args {
-                    let bitcopy = match arg.ty {
-                        Type::RustVec(_) => true,
-                        _ => arg.ty == RustString,
-                    };
-                    if bitcopy {
-                        needs_unsafe_bitcopy = true;
-                        break;
-                    }
-                }
-            }
-            Api::RustFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.include.exception = true;
-                    needs_rust_error = true;
-                }
-                for arg in &efn.args {
-                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-                        needs_manually_drop = true;
-                        break;
-                    }
-                }
-                if let Some(ret) = &efn.ret {
-                    if types.needs_indirect_abi(ret) {
-                        needs_maybe_uninit = true;
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
-
-    if needs_rust_string
-        || needs_rust_str
-        || needs_rust_slice
-        || needs_rust_box
-        || needs_rust_vec
-        || needs_rust_fn
-        || needs_rust_error
-        || needs_rust_isize
-        || needs_unsafe_bitcopy
-        || needs_manually_drop
-        || needs_maybe_uninit
-        || needs_trycatch
-    {
-        writeln!(out, "// #include \"rust/cxx.h\"");
-    }
-
-    if needs_rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
-
-    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
-    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
-    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
-    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
-    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
-    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
-    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
-    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
-
-    if needs_manually_drop {
-        out.next_section();
-        out.include.utility = true;
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union ManuallyDrop {{");
-        writeln!(out, "  T value;");
-        writeln!(
-            out,
-            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
-        );
-        writeln!(out, "  ~ManuallyDrop() {{}}");
-        writeln!(out, "}};");
-    }
-
-    if needs_maybe_uninit {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union MaybeUninit {{");
-        writeln!(out, "  T value;");
-        writeln!(out, "  MaybeUninit() {{}}");
-        writeln!(out, "  ~MaybeUninit() {{}}");
-        writeln!(out, "}};");
-    }
-
-    out.end_block("namespace cxxbridge02");
-
-    if needs_trycatch {
-        out.begin_block("namespace behavior");
-        out.include.exception = true;
-        out.include.type_traits = true;
-        out.include.utility = true;
-        writeln!(out, "class missing {{}};");
-        writeln!(out, "missing trycatch(...);");
-        writeln!(out);
-        writeln!(out, "template <typename Try, typename Fail>");
-        writeln!(out, "static typename std::enable_if<");
-        writeln!(
-            out,
-            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
-        );
-        writeln!(out, "                 missing>::value>::type");
-        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
-        writeln!(out, "  func();");
-        writeln!(out, "}} catch (const ::std::exception &e) {{");
-        writeln!(out, "  fail(e.what());");
-        writeln!(out, "}}");
-        out.end_block("namespace behavior");
-    }
-
-    out.end_block("namespace rust");
-}
-
-fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
-    let section = include::get(section);
-    if needed {
-        out.next_section();
-        for line in section.lines() {
-            if !line.trim_start().starts_with("//") {
-                writeln!(out, "{}", line);
-            }
-        }
-    }
-}
-
-fn write_struct(out: &mut OutFile, strct: &Struct) {
-    for line in strct.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    writeln!(out, "struct {} final {{", strct.ident);
-    for field in &strct.fields {
-        write!(out, "  ");
-        write_type_space(out, &field.ty);
-        writeln!(out, "{};", field.ident);
-    }
-    writeln!(out, "}};");
-}
-
-fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "struct {};", ident);
-}
-
-fn write_struct_using(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "using {} = {};", ident, ident);
-}
-
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    for line in ety.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    writeln!(out, "struct {} final {{", ety.ident);
-    writeln!(out, "  {}() = delete;", ety.ident);
-    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
-    for method in methods {
-        write!(out, "  ");
-        let sig = &method.sig;
-        let local_name = method.ident.to_string();
-        write_rust_function_shim_decl(out, &local_name, sig, false);
-        writeln!(out, ";");
-    }
-    writeln!(out, "}};");
-}
-
-fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
-    let mut has_cxx_throws = false;
-    for api in apis {
-        if let Api::CxxFunction(efn) = api {
-            if efn.throws {
-                has_cxx_throws = true;
-                break;
-            }
-        }
-    }
-
-    if has_cxx_throws {
-        out.next_section();
-        writeln!(
-            out,
-            "const char *cxxbridge02$exception(const char *, size_t);",
-        );
-    }
-}
-
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    if efn.throws {
-        write!(out, "::rust::Str::Repr ");
-    } else {
-        write_extern_return_type_space(out, &efn.ret, types);
-    }
-    let mangled = mangle::extern_fn(&out.namespace, efn);
-    write!(out, "{}(", mangled);
-    if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, "const ");
-        }
-        write!(out, "{} &self", receiver.ty);
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 || efn.receiver.is_some() {
-            write!(out, ", ");
-        }
-        if arg.ty == RustString {
-            write!(out, "const ");
-        } else if let Type::RustVec(_) = arg.ty {
-            write!(out, "const ");
-        }
-        write_extern_arg(out, arg, types);
-    }
-    let indirect_return = indirect_return(efn, types);
-    if indirect_return {
-        if !efn.args.is_empty() {
-            write!(out, ", ");
-        }
-        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
-        write!(out, "*return$");
-    }
-    writeln!(out, ") noexcept {{");
-    write!(out, "  ");
-    write_return_type(out, &efn.ret);
-    match &efn.receiver {
-        None => write!(out, "(*{}$)(", efn.ident),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        write_type(out, &arg.ty);
-    }
-    write!(out, ")");
-    if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, " const");
-        }
-    }
-    write!(out, " = ");
-    match &efn.receiver {
-        None => write!(out, "{}", efn.ident),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
-    }
-    writeln!(out, ";");
-    write!(out, "  ");
-    if efn.throws {
-        writeln!(out, "::rust::Str::Repr throw$;");
-        writeln!(out, "  ::rust::behavior::trycatch(");
-        writeln!(out, "      [&] {{");
-        write!(out, "        ");
-    }
-    if indirect_return {
-        write!(out, "new (return$) ");
-        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
-        write!(out, "(");
-    } else if efn.ret.is_some() {
-        write!(out, "return ");
-    }
-    match &efn.ret {
-        Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
-        Some(Type::SliceRefU8(_)) if !indirect_return => {
-            write!(out, "::rust::Slice<uint8_t>::Repr(")
-        }
-        _ => {}
-    }
-    match &efn.receiver {
-        None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
-    }
-    for (i, arg) in efn.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        if let Type::RustBox(_) = &arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "::from_raw({})", arg.ident);
-        } else if let Type::UniquePtr(_) = &arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "({})", arg.ident);
-        } else if arg.ty == RustString {
-            write!(
-                out,
-                "::rust::String(::rust::unsafe_bitcopy, *{})",
-                arg.ident,
-            );
-        } else if let Type::RustVec(_) = arg.ty {
-            write_type(out, &arg.ty);
-            write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if types.needs_indirect_abi(&arg.ty) {
-            out.include.utility = true;
-            write!(out, "::std::move(*{})", arg.ident);
-        } else {
-            write!(out, "{}", arg.ident);
-        }
-    }
-    write!(out, ")");
-    match &efn.ret {
-        Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
-        Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::CxxVector(_)) => write!(
-            out,
-            " /* Use RVO to convert to r-value and move construct */"
-        ),
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
-        _ => {}
-    }
-    if indirect_return {
-        write!(out, ")");
-    }
-    writeln!(out, ";");
-    if efn.throws {
-        out.include.cstring = true;
-        writeln!(out, "        throw$.ptr = nullptr;");
-        writeln!(out, "      }},");
-        writeln!(out, "      [&](const char *catch$) noexcept {{");
-        writeln!(out, "        throw$.len = ::std::strlen(catch$);");
-        writeln!(
-            out,
-            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
-        );
-        writeln!(out, "      }});");
-        writeln!(out, "  return throw$;");
-    }
-    writeln!(out, "}}");
-    for arg in &efn.args {
-        if let Type::Fn(f) = &arg.ty {
-            let var = &arg.ident;
-            write_function_pointer_trampoline(out, efn, var, f, types);
-        }
-    }
-}
-
-fn write_function_pointer_trampoline(
-    out: &mut OutFile,
-    efn: &ExternFn,
-    var: &Ident,
-    f: &Signature,
-    types: &Types,
-) {
-    out.next_section();
-    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
-    let indirect_call = true;
-    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
-
-    out.next_section();
-    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
-    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
-}
-
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    let link_name = mangle::extern_fn(&out.namespace, efn);
-    let indirect_call = false;
-    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
-}
-
-fn write_rust_function_decl_impl(
-    out: &mut OutFile,
-    link_name: &Symbol,
-    sig: &Signature,
-    types: &Types,
-    indirect_call: bool,
-) {
-    if sig.throws {
-        write!(out, "::rust::Str::Repr ");
-    } else {
-        write_extern_return_type_space(out, &sig.ret, types);
-    }
-    write!(out, "{}(", link_name);
-    let mut needs_comma = false;
-    if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, "const ");
-        }
-        write!(out, "{} &self", receiver.ty);
-        needs_comma = true;
-    }
-    for arg in &sig.args {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write_extern_arg(out, arg, types);
-        needs_comma = true;
-    }
-    if indirect_return(sig, types) {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write_return_type(out, &sig.ret);
-        write!(out, "*return$");
-        needs_comma = true;
-    }
-    if indirect_call {
-        if needs_comma {
-            write!(out, ", ");
-        }
-        write!(out, "void *");
-    }
-    writeln!(out, ") noexcept;");
-}
-
-fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
-    for line in efn.doc.to_string().lines() {
-        writeln!(out, "//{}", line);
-    }
-    let local_name = match &efn.sig.receiver {
-        None => efn.ident.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
-    };
-    let invoke = mangle::extern_fn(&out.namespace, efn);
-    let indirect_call = false;
-    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
-}
-
-fn write_rust_function_shim_decl(
-    out: &mut OutFile,
-    local_name: &str,
-    sig: &Signature,
-    indirect_call: bool,
-) {
-    write_return_type(out, &sig.ret);
-    write!(out, "{}(", local_name);
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 {
-            write!(out, ", ");
-        }
-        write_type_space(out, &arg.ty);
-        write!(out, "{}", arg.ident);
-    }
-    if indirect_call {
-        if !sig.args.is_empty() {
-            write!(out, ", ");
-        }
-        write!(out, "void *extern$");
-    }
-    write!(out, ")");
-    if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
-            write!(out, " const");
-        }
-    }
-    if !sig.throws {
-        write!(out, " noexcept");
-    }
-}
-
-fn write_rust_function_shim_impl(
-    out: &mut OutFile,
-    local_name: &str,
-    sig: &Signature,
-    types: &Types,
-    invoke: &Symbol,
-    indirect_call: bool,
-) {
-    if out.header && sig.receiver.is_some() {
-        // We've already defined this inside the struct.
-        return;
-    }
-    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
-    if out.header {
-        writeln!(out, ";");
-        return;
-    }
-    writeln!(out, " {{");
-    for arg in &sig.args {
-        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
-            out.include.utility = true;
-            write!(out, "  ::rust::ManuallyDrop<");
-            write_type(out, &arg.ty);
-            writeln!(out, "> {}$(::std::move({0}));", arg.ident);
-        }
-    }
-    write!(out, "  ");
-    let indirect_return = indirect_return(sig, types);
-    if indirect_return {
-        write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
-        writeln!(out, "> return$;");
-        write!(out, "  ");
-    } else if let Some(ret) = &sig.ret {
-        write!(out, "return ");
-        match ret {
-            Type::RustBox(_) => {
-                write_type(out, ret);
-                write!(out, "::from_raw(");
-            }
-            Type::UniquePtr(_) => {
-                write_type(out, ret);
-                write!(out, "(");
-            }
-            Type::Ref(_) => write!(out, "*"),
-            _ => {}
-        }
-    }
-    if sig.throws {
-        write!(out, "::rust::Str::Repr error$ = ");
-    }
-    write!(out, "{}(", invoke);
-    if sig.receiver.is_some() {
-        write!(out, "*this");
-    }
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 || sig.receiver.is_some() {
-            write!(out, ", ");
-        }
-        match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::Str::Repr("),
-            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
-            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
-            _ => {}
-        }
-        write!(out, "{}", arg.ident);
-        match &arg.ty {
-            Type::RustBox(_) => write!(out, ".into_raw()"),
-            Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
-            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
-            _ => {}
-        }
-    }
-    if indirect_return {
-        if !sig.args.is_empty() {
-            write!(out, ", ");
-        }
-        write!(out, "&return$.value");
-    }
-    if indirect_call {
-        if !sig.args.is_empty() || indirect_return {
-            write!(out, ", ");
-        }
-        write!(out, "extern$");
-    }
-    write!(out, ")");
-    if let Some(ret) = &sig.ret {
-        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-            write!(out, ")");
-        }
-    }
-    writeln!(out, ";");
-    if sig.throws {
-        writeln!(out, "  if (error$.ptr) {{");
-        writeln!(out, "    throw ::rust::Error(error$);");
-        writeln!(out, "  }}");
-    }
-    if indirect_return {
-        out.include.utility = true;
-        writeln!(out, "  return ::std::move(return$.value);");
-    }
-    writeln!(out, "}}");
-}
-
-fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
-    match ty {
-        None => write!(out, "void "),
-        Some(ty) => write_type_space(out, ty),
-    }
-}
-
-fn indirect_return(sig: &Signature, types: &Types) -> bool {
-    sig.ret
-        .as_ref()
-        .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
-}
-
-fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Type::Ref(ty) => {
-            if ty.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &ty.inner);
-            write!(out, " *");
-        }
-        Type::Str(_) => write!(out, "::rust::Str::Repr"),
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
-        _ => write_type(out, ty),
-    }
-}
-
-fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
-    write_indirect_return_type(out, ty);
-    match ty {
-        Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
-        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
-        _ => write_space_after_type(out, ty),
-    }
-}
-
-fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
-    match ty {
-        Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Some(Type::Ref(ty)) => {
-            if ty.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &ty.inner);
-            write!(out, " *");
-        }
-        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
-        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
-        _ => write_return_type(out, ty),
-    }
-}
-
-fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
-    match &arg.ty {
-        Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
-            write_type_space(out, &ty.inner);
-            write!(out, "*");
-        }
-        Type::Str(_) => write!(out, "::rust::Str::Repr "),
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        _ => write_type_space(out, &arg.ty),
-    }
-    if types.needs_indirect_abi(&arg.ty) {
-        write!(out, "*");
-    }
-    write!(out, "{}", arg.ident);
-}
-
-fn write_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
-            None => write!(out, "{}", ident),
-        },
-        Type::RustBox(ty) => {
-            write!(out, "::rust::Box<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::RustVec(ty) => {
-            write!(out, "::rust::Vec<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::UniquePtr(ptr) => {
-            write!(out, "::std::unique_ptr<");
-            write_type(out, &ptr.inner);
-            write!(out, ">");
-        }
-        Type::CxxVector(ty) => {
-            write!(out, "::std::vector<");
-            write_type(out, &ty.inner);
-            write!(out, ">");
-        }
-        Type::Ref(r) => {
-            if r.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type(out, &r.inner);
-            write!(out, " &");
-        }
-        Type::Slice(_) => {
-            // For now, only U8 slices are supported, which are covered separately below
-            unreachable!()
-        }
-        Type::Str(_) => {
-            write!(out, "::rust::Str");
-        }
-        Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<uint8_t>");
-        }
-        Type::Fn(f) => {
-            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
-            match &f.ret {
-                Some(ret) => write_type(out, ret),
-                None => write!(out, "void"),
-            }
-            write!(out, "(");
-            for (i, arg) in f.args.iter().enumerate() {
-                if i > 0 {
-                    write!(out, ", ");
-                }
-                write_type(out, &arg.ty);
-            }
-            write!(out, ")>");
-        }
-        Type::Void(_) => unreachable!(),
-    }
-}
-
-fn write_type_space(out: &mut OutFile, ty: &Type) {
-    write_type(out, ty);
-    write_space_after_type(out, ty);
-}
-
-fn write_space_after_type(out: &mut OutFile, ty: &Type) {
-    match ty {
-        Type::Ident(_)
-        | Type::RustBox(_)
-        | Type::UniquePtr(_)
-        | Type::Str(_)
-        | Type::CxxVector(_)
-        | Type::RustVec(_)
-        | Type::SliceRefU8(_)
-        | Type::Fn(_) => write!(out, " "),
-        Type::Ref(_) => {}
-        Type::Void(_) | Type::Slice(_) => unreachable!(),
-    }
-}
-
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_typename(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(ident) => {
-            let mut path = String::new();
-            for name in namespace {
-                path += name;
-                path += "::";
-            }
-            path += &ident.to_string();
-            path
-        }
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
-        _ => unreachable!(),
-    }
-}
-
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
-    match ty {
-        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
-        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
-        _ => unreachable!(),
-    }
-}
-
-fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
-    fn allow_unique_ptr(ident: &Ident) -> bool {
-        Atom::from(ident).is_none()
-    }
-
-    out.begin_block("extern \"C\"");
-    for ty in types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                out.next_section();
-                write_rust_box_extern(out, inner);
-            }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    out.next_section();
-                    write_rust_vec_extern(out, inner);
-                }
-            }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if allow_unique_ptr(inner) {
-                    out.next_section();
-                    write_unique_ptr(out, inner, types);
-                }
-            }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() {
-                    out.next_section();
-                    write_cxx_vector(out, ty, inner, types);
-                }
-            }
-        }
-    }
-    out.end_block("extern \"C\"");
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
-    for ty in types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, inner);
-            }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    write_rust_vec_impl(out, inner);
-                }
-            }
-        }
-    }
-    out.end_block("namespace cxxbridge02");
-    out.end_block("namespace rust");
-}
-
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
-
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
-    writeln!(
-        out,
-        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
-}
-
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
-    writeln!(
-        out,
-        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
-        instance, inner,
-    );
-    writeln!(
-        out,
-        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
-        inner, instance,
-    );
-    writeln!(
-        out,
-        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
-        instance,
-    );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
-}
-
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += name;
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
-    writeln!(out, "}}");
-}
-
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "template <>");
-    writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge02$rust_vec${}$drop(this);",
-        instance,
-    );
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge02$rust_vec${}$data(this);",
-        instance,
-    );
-    writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
-    writeln!(out, "}}");
-}
-
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
-    let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&out.namespace, &ty);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-
-    write_unique_ptr_common(out, &ty, types);
-
-    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-}
-
-// Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
-fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
-    out.include.utility = true;
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
-
-    let can_construct_from_value = match ty {
-        Type::Ident(ident) => types.structs.contains_key(ident),
-        _ => false,
-    };
-
-    writeln!(
-        out,
-        "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
-        inner,
-    );
-    writeln!(
-        out,
-        "static_assert(alignof(::std::unique_ptr<{}>) == alignof(void *), \"\");",
-        inner,
-    );
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
-    writeln!(out, "}}");
-    if can_construct_from_value {
-        writeln!(
-            out,
-            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
-            instance, inner, inner,
-        );
-        writeln!(
-            out,
-            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
-        );
-        writeln!(out, "}}");
-    }
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
-        instance, inner, inner,
-    );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return ptr.get();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return ptr.release();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  ptr->~unique_ptr();");
-    writeln!(out, "}}");
-}
-
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
-
-    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
-    writeln!(
-        out,
-        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
-        instance, inner,
-    );
-    writeln!(out, "  return s.size();");
-    writeln!(out, "}}");
-    writeln!(
-        out,
-        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
-        inner, instance, inner,
-    );
-    writeln!(out, "  return s[pos];");
-    writeln!(out, "}}");
-
-    write_unique_ptr_common(out, vector_ty, types);
-
-    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
-}
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 82401ee..c7c48ec 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["README.md"]
 
 [lib]
 proc-macro = true
diff --git a/macro/README.md b/macro/README.md
new file mode 100644
index 0000000..b9c1779
--- /dev/null
+++ b/macro/README.md
@@ -0,0 +1,3 @@
+This directory contains CXX's Rust code generator, which is a procedural macro.
+Users won't depend on this crate directly. Instead they'll invoke its macro
+through the reexport in the main `cxx` crate.
diff --git a/src/error.rs b/src/error.rs
deleted file mode 100644
index 740ab94..0000000
--- a/src/error.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-use std::error::Error as StdError;
-use std::fmt::{self, Display};
-use std::io;
-
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
-
-#[derive(Debug)]
-pub(super) enum Error {
-    MissingOutDir,
-    TargetDir,
-    Io(io::Error),
-}
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
-            Error::TargetDir => write!(f, "failed to locate target dir"),
-            Error::Io(err) => err.fmt(f),
-        }
-    }
-}
-
-impl StdError for Error {
-    fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        match self {
-            Error::Io(err) => Some(err),
-            _ => None,
-        }
-    }
-}
-
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
-    }
-}
diff --git a/src/gen b/src/gen
deleted file mode 120000
index 334e0fb..0000000
--- a/src/gen
+++ /dev/null
@@ -1 +0,0 @@
-../gen
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index cff1e88..7e8e9ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -224,8 +224,7 @@
 //! // build.rs
 //!
 //! fn main() {
-//!     cxx::Build::new()
-//!         .bridge("src/main.rs")  // returns a cc::Build
+//!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
 //!         .file("../demo-cxx/demo.cc")
 //!         .flag("-std=c++11")
 //!         .compile("cxxbridge-demo");
@@ -363,18 +362,14 @@ mod concat;
 
 mod cxx_string;
 mod cxx_vector;
-mod error;
 mod exception;
 mod function;
-mod gen;
 mod opaque;
-mod paths;
 mod result;
 mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
-mod syntax;
 mod unique_ptr;
 mod unwind;
 
@@ -398,107 +393,3 @@ pub mod private {
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
-
-use crate::error::Result;
-use crate::gen::Opt;
-use anyhow::anyhow;
-use std::fs;
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-/// The CXX code generator for constructing and compiling C++ code.
-///
-/// This is intended to be used from Cargo build scripts to execute CXX's
-/// C++ code generator, set up any additional compiler flags depending on
-/// the use case, and make the C++ compiler invocation.
-///
-/// <br>
-///
-/// # Example
-///
-/// Example of a canonical Cargo build script that builds a CXX bridge:
-///
-/// ```no_run
-/// // build.rs
-///
-/// fn main() {
-///     cxx::Build::new()
-///         .bridge("src/main.rs")
-///         .file("../demo-cxx/demo.cc")
-///         .flag("-std=c++11")
-///         .compile("cxxbridge-demo");
-///
-///     println!("cargo:rerun-if-changed=src/main.rs");
-///     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-///     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
-/// }
-/// ```
-///
-/// A runnable working setup with this build script is shown in the
-/// *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
-///
-/// [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
-///
-/// <br>
-///
-/// # Alternatives
-///
-/// For use in non-Cargo builds like Bazel or Buck, CXX provides an
-/// alternate way of invoking the C++ code generator as a standalone command
-/// line tool. The tool is packaged as the `cxxbridge-cmd` crate.
-///
-/// ```bash
-/// $ cargo install cxxbridge-cmd  # or build it from the repo
-///
-/// $ cxxbridge src/main.rs --header > path/to/mybridge.h
-/// $ cxxbridge src/main.rs > path/to/mybridge.cc
-/// ```
-#[must_use]
-pub struct Build {
-    _private: (),
-}
-
-impl Build {
-    /// Begin with a [`cc::Build`] in its default configuration.
-    pub fn new() -> Self {
-        Build { _private: () }
-    }
-
-    /// This returns a [`cc::Build`] on which you should continue to set up
-    /// any additional source files or compiler flags, and lastly call its
-    /// [`compile`] method to execute the C++ build.
-    ///
-    /// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
-    #[must_use]
-    pub fn bridge(&self, rust_source_file: impl AsRef<Path>) -> cc::Build {
-        match try_generate_bridge(rust_source_file.as_ref()) {
-            Ok(build) => build,
-            Err(err) => {
-                let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
-                process::exit(1);
-            }
-        }
-    }
-}
-
-fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
-    let header = gen::do_generate_header(rust_source_file, Opt::default());
-    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
-    fs::create_dir_all(header_path.parent().unwrap())?;
-    fs::write(&header_path, header)?;
-    paths::symlink_header(&header_path, rust_source_file);
-
-    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
-    let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
-    fs::write(&bridge_path, bridge)?;
-    let mut build = paths::cc_build();
-    build.file(&bridge_path);
-
-    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
-    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
-    let _ = fs::remove_file(cxx_h);
-    let _ = fs::write(cxx_h, gen::include::HEADER);
-
-    Ok(build)
-}
diff --git a/src/paths.rs b/src/paths.rs
deleted file mode 100644
index ca183d9..0000000
--- a/src/paths.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-use crate::error::{Error, Result};
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
-
-fn out_dir() -> Result<PathBuf> {
-    env::var_os("OUT_DIR")
-        .map(PathBuf::from)
-        .ok_or(Error::MissingOutDir)
-}
-
-pub(crate) fn cc_build() -> cc::Build {
-    try_cc_build().unwrap_or_default()
-}
-
-fn try_cc_build() -> Result<cc::Build> {
-    let mut build = cc::Build::new();
-    build.include(include_dir()?);
-    build.include(target_dir()?.parent().unwrap());
-    Ok(build)
-}
-
-// Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(path: &Path, original: &Path) {
-    let _ = try_symlink_header(path, original);
-}
-
-fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(original)?;
-    let ref dst = include_dir()?.join(suffix);
-
-    fs::create_dir_all(dst.parent().unwrap())?;
-    let _ = fs::remove_file(dst);
-    symlink_or_copy(path, dst)?;
-
-    let mut file_name = dst.file_name().unwrap().to_os_string();
-    file_name.push(".h");
-    let ref dst2 = dst.with_file_name(file_name);
-    symlink_or_copy(path, dst2)?;
-
-    Ok(())
-}
-
-fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
-    let target_dir = target_dir()?;
-    let mut outer = target_dir.parent().unwrap();
-    let original = canonicalize(original)?;
-    loop {
-        if let Ok(suffix) = original.strip_prefix(outer) {
-            return Ok(suffix.to_owned());
-        }
-        match outer.parent() {
-            Some(parent) => outer = parent,
-            None => return Ok(original.components().skip(1).collect()),
-        }
-    }
-}
-
-pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
-    let mut file_name = path.file_name().unwrap().to_owned();
-    file_name.push(ext);
-
-    let out_dir = out_dir()?;
-    let rel = relative_to_parent_of_target_dir(path)?;
-    Ok(out_dir.join(rel).with_file_name(file_name))
-}
-
-pub(crate) fn include_dir() -> Result<PathBuf> {
-    let target_dir = target_dir()?;
-    Ok(target_dir.join("cxxbridge"))
-}
-
-fn target_dir() -> Result<PathBuf> {
-    let mut dir = out_dir().and_then(canonicalize)?;
-    loop {
-        if dir.ends_with("target") {
-            return Ok(dir);
-        }
-        if !dir.pop() {
-            return Err(Error::TargetDir);
-        }
-    }
-}
-
-#[cfg(not(windows))]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    Ok(fs::canonicalize(path)?)
-}
-
-#[cfg(windows)]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
-    // unable to handle in includes. Use a poor approximation instead.
-    // https://github.com/rust-lang/rust/issues/42869
-    // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(env::current_dir()?.join(path))
-}
-
-#[cfg(unix)]
-use std::os::unix::fs::symlink as symlink_or_copy;
-
-#[cfg(windows)]
-fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
-    use std::os::windows::fs::symlink_file;
-
-    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
-    // require Developer Mode. If it fails, fall back to copying the file.
-    if symlink_file(src, dst).is_err() {
-        fs::copy(src, dst)?;
-    }
-    Ok(())
-}
-
-#[cfg(not(any(unix, windows)))]
-use std::fs::copy as symlink_or_copy;
diff --git a/src/syntax b/src/syntax
deleted file mode 120000
index f400712..0000000
--- a/src/syntax
+++ /dev/null
@@ -1 +0,0 @@
-../syntax
\ No newline at end of file
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
index c84df61..c2d8227 100644
--- a/tests/ffi/Cargo.toml
+++ b/tests/ffi/Cargo.toml
@@ -11,4 +11,4 @@ path = "lib.rs"
 cxx = { path = "../.." }
 
 [build-dependencies]
-cxx = { path = "../.." }
+cxx-build = { path = "../../gen/build" }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 5c1bec3..b970362 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -3,8 +3,7 @@ fn main() {
         return;
     }
 
-    cxx::Build::new()
-        .bridge("lib.rs")
+    cxx_build::bridge("lib.rs")
         .file("tests.cc")
         .flag("-std=c++11")
         .compile("cxx-test-suite");
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 0bd470b..f4068d9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -67,17 +67,25 @@ dependencies = [
 name = "cxx"
 version = "0.2.12"
 dependencies = [
- "anyhow",
  "cc",
- "codespan-reporting",
+ "cxx-build",
  "cxx-test-suite",
  "cxxbridge-macro",
  "link-cplusplus",
+ "rustversion",
+ "trybuild",
+]
+
+[[package]]
+name = "cxx-build"
+version = "0.2.12"
+dependencies = [
+ "anyhow",
+ "cc",
+ "codespan-reporting",
  "proc-macro2",
  "quote",
- "rustversion",
  "syn",
- "trybuild",
 ]
 
 [[package]]
@@ -85,6 +93,7 @@ name = "cxx-test-suite"
 version = "0.0.0"
 dependencies = [
  "cxx",
+ "cxx-build",
 ]
 
 [[package]]
@@ -104,6 +113,7 @@ name = "cxxbridge-demo"
 version = "0.0.0"
 dependencies = [
  "cxx",
+ "cxx-build",
 ]
 
 [[package]]

From 6960162922c22b26404793810d89edb898628b9a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:49:50 +0000
Subject: [PATCH 486/2232] Bump namespace to cxxbridge03


---

diff --git a/Cargo.toml b/Cargo.toml
index ea97712..ad40cad 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "cxx"
 version = "0.2.12" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge02"
+links = "cxxbridge03"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
diff --git a/build.rs b/build.rs
index 5173658..1f3b6eb 100644
--- a/build.rs
+++ b/build.rs
@@ -2,7 +2,7 @@ fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
         .flag("-std=c++11")
-        .compile("cxxbridge02");
+        .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index b39d978..8869849 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -218,7 +218,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
+    out.begin_block("inline namespace cxxbridge03");
 
     if needs_rust_string
         || needs_rust_str
@@ -241,15 +241,15 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    write_header_section(out, needs_rust_string, "CXXBRIDGE02_RUST_STRING");
-    write_header_section(out, needs_rust_str, "CXXBRIDGE02_RUST_STR");
-    write_header_section(out, needs_rust_slice, "CXXBRIDGE02_RUST_SLICE");
-    write_header_section(out, needs_rust_box, "CXXBRIDGE02_RUST_BOX");
-    write_header_section(out, needs_rust_vec, "CXXBRIDGE02_RUST_VEC");
-    write_header_section(out, needs_rust_fn, "CXXBRIDGE02_RUST_FN");
-    write_header_section(out, needs_rust_error, "CXXBRIDGE02_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE02_RUST_ISIZE");
-    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE02_RUST_BITCOPY");
+    write_header_section(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
+    write_header_section(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
+    write_header_section(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
+    write_header_section(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
+    write_header_section(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
+    write_header_section(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
+    write_header_section(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
+    write_header_section(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
+    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();
@@ -275,7 +275,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace cxxbridge02");
+    out.end_block("namespace cxxbridge03");
 
     if needs_trycatch {
         out.begin_block("namespace behavior");
@@ -368,7 +368,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
         out.next_section();
         writeln!(
             out,
-            "const char *cxxbridge02$exception(const char *, size_t);",
+            "const char *cxxbridge03$exception(const char *, size_t);",
         );
     }
 }
@@ -506,7 +506,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = cxxbridge02$exception(catch$, throw$.len);",
+            "        throw$.ptr = cxxbridge03$exception(catch$, throw$.len);",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -977,7 +977,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("extern \"C\"");
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge02");
+    out.begin_block("inline namespace cxxbridge03");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -991,7 +991,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block("namespace cxxbridge02");
+    out.end_block("namespace cxxbridge03");
     out.end_block("namespace rust");
 }
 
@@ -1004,19 +1004,19 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE03_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE03_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge02$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge03$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge02$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge03$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE03_RUST_BOX_{}", instance);
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
@@ -1024,34 +1024,34 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE03_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE03_RUST_VEC_{}", instance);
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge03$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge02$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge03$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge02$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        "size_t cxxbridge03$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge02$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        "const {} *cxxbridge03$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
     writeln!(
         out,
-        "size_t cxxbridge02$rust_vec${}$stride() noexcept;",
+        "size_t cxxbridge03$rust_vec${}$stride() noexcept;",
         instance,
     );
-    writeln!(out, "#endif // CXXBRIDGE02_RUST_VEC_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE03_RUST_VEC_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
@@ -1065,12 +1065,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$uninit(this);", instance);
+    writeln!(out, "  cxxbridge03$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$box${}$drop(this);", instance);
+    writeln!(out, "  cxxbridge03$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 
@@ -1081,35 +1081,35 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge02$rust_vec${}$new(this);", instance);
+    writeln!(out, "  cxxbridge03$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge02$rust_vec${}$drop(this);",
+        "  return cxxbridge03$rust_vec${}$drop(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$len(this);", instance);
+    writeln!(out, "  return cxxbridge03$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge02$rust_vec${}$data(this);",
+        "  return cxxbridge03$rust_vec${}$data(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge02$rust_vec${}$stride();", instance);
+    writeln!(out, "  return cxxbridge03$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
 }
 
@@ -1117,12 +1117,12 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     let ty = Type::Ident(ident.clone());
     let instance = to_mangled(&out.namespace, &ty);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE03_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE03_UNIQUE_PTR_{}", instance);
 
     write_unique_ptr_common(out, &ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE02_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE03_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
@@ -1148,7 +1148,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(
         out,
-        "void cxxbridge02$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge03$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
@@ -1156,7 +1156,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     if can_construct_from_value {
         writeln!(
             out,
-            "void cxxbridge02$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            "void cxxbridge03$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
         writeln!(
@@ -1168,28 +1168,28 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     }
     writeln!(
         out,
-        "void cxxbridge02$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge03$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge02$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge03$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge02$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge03$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge02$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge03$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
@@ -1201,18 +1201,18 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE02_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE03_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE03_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge02$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge03$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} &cxxbridge02$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} &cxxbridge03$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return s[pos];");
@@ -1220,5 +1220,5 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
 
     write_unique_ptr_common(out, vector_ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE02_VECTOR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE03_VECTOR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index 1e33618..7762719 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -13,18 +13,18 @@
 #endif
 
 namespace rust {
-inline namespace cxxbridge02 {
+inline namespace cxxbridge03 {
 
-#ifndef CXXBRIDGE02_RUST_BITCOPY
-#define CXXBRIDGE02_RUST_BITCOPY
+#ifndef CXXBRIDGE03_RUST_BITCOPY
+#define CXXBRIDGE03_RUST_BITCOPY
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
 };
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE02_RUST_BITCOPY
+#endif // CXXBRIDGE03_RUST_BITCOPY
 
-#ifndef CXXBRIDGE02_RUST_STRING
-#define CXXBRIDGE02_RUST_STRING
+#ifndef CXXBRIDGE03_RUST_STRING
+#define CXXBRIDGE03_RUST_STRING
 class String final {
 public:
   String() noexcept;
@@ -52,10 +52,10 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE02_RUST_STRING
+#endif // CXXBRIDGE03_RUST_STRING
 
-#ifndef CXXBRIDGE02_RUST_STR
-#define CXXBRIDGE02_RUST_STR
+#ifndef CXXBRIDGE03_RUST_STR
+#define CXXBRIDGE03_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -88,10 +88,10 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE02_RUST_STR
+#endif // CXXBRIDGE03_RUST_STR
 
-#ifndef CXXBRIDGE02_RUST_SLICE
-#define CXXBRIDGE02_RUST_SLICE
+#ifndef CXXBRIDGE03_RUST_SLICE
+#define CXXBRIDGE03_RUST_SLICE
 template <typename T>
 class Slice final {
 public:
@@ -124,10 +124,10 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE02_RUST_SLICE
+#endif // CXXBRIDGE03_RUST_SLICE
 
-#ifndef CXXBRIDGE02_RUST_BOX
-#define CXXBRIDGE02_RUST_BOX
+#ifndef CXXBRIDGE03_RUST_BOX
+#define CXXBRIDGE03_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -204,10 +204,10 @@ private:
   void drop() noexcept;
   T *ptr;
 };
-#endif // CXXBRIDGE02_RUST_BOX
+#endif // CXXBRIDGE03_RUST_BOX
 
-#ifndef CXXBRIDGE02_RUST_VEC
-#define CXXBRIDGE02_RUST_VEC
+#ifndef CXXBRIDGE03_RUST_VEC
+#define CXXBRIDGE03_RUST_VEC
 template <typename T>
 class Vec final {
 public:
@@ -289,10 +289,10 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE02_RUST_VEC
+#endif // CXXBRIDGE03_RUST_VEC
 
-#ifndef CXXBRIDGE02_RUST_FN
-#define CXXBRIDGE02_RUST_FN
+#ifndef CXXBRIDGE03_RUST_FN
+#define CXXBRIDGE03_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -309,10 +309,10 @@ private:
 
 template <typename Signature>
 using TryFn = Fn<Signature, true>;
-#endif // CXXBRIDGE02_RUST_FN
+#endif // CXXBRIDGE03_RUST_FN
 
-#ifndef CXXBRIDGE02_RUST_ERROR
-#define CXXBRIDGE02_RUST_ERROR
+#ifndef CXXBRIDGE03_RUST_ERROR
+#define CXXBRIDGE03_RUST_ERROR
 class Error final : std::exception {
 public:
   Error(const Error &);
@@ -324,16 +324,16 @@ public:
 private:
   Str::Repr msg;
 };
-#endif // CXXBRIDGE02_RUST_ERROR
+#endif // CXXBRIDGE03_RUST_ERROR
 
-#ifndef CXXBRIDGE02_RUST_ISIZE
-#define CXXBRIDGE02_RUST_ISIZE
+#ifndef CXXBRIDGE03_RUST_ISIZE
+#define CXXBRIDGE03_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
-#endif // CXXBRIDGE02_RUST_ISIZE
+#endif // CXXBRIDGE03_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -359,5 +359,5 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 
-} // namespace cxxbridge02
+} // namespace cxxbridge03
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 27d75fe..15a091b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -517,7 +517,7 @@ fn expand_rust_function_shim_impl(
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge02$box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge03$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
@@ -546,7 +546,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge02$rust_vec${}{}$", namespace, elem);
+    let link_prefix = format!("cxxbridge03$rust_vec${}{}$", namespace, elem);
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -592,7 +592,7 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
 
 fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
     let name = ident.to_string();
-    let prefix = format!("cxxbridge02$unique_ptr${}{}$", namespace, ident);
+    let prefix = format!("cxxbridge03$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -665,10 +665,10 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
 
 fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let name = elem.to_string();
-    let prefix = format!("cxxbridge02$std$vector${}{}$", namespace, elem);
+    let prefix = format!("cxxbridge03$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge02$unique_ptr$std$vector${}{}$", namespace, elem);
+    let unique_ptr_prefix = format!("cxxbridge03$unique_ptr$std$vector${}{}$", namespace, elem);
     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/src/cxx.cc b/src/cxx.cc
index 8409772..5f7ac6a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -17,72 +17,72 @@ static void panic [[noreturn]] (const char *msg) {
 }
 
 extern "C" {
-const char *cxxbridge02$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge03$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge02$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge03$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
 // rust::String
-void cxxbridge02$string$new(rust::String *self) noexcept;
-void cxxbridge02$string$clone(rust::String *self,
+void cxxbridge03$string$new(rust::String *self) noexcept;
+void cxxbridge03$string$clone(rust::String *self,
                               const rust::String &other) noexcept;
-bool cxxbridge02$string$from(rust::String *self, const char *ptr,
+bool cxxbridge03$string$from(rust::String *self, const char *ptr,
                              size_t len) noexcept;
-void cxxbridge02$string$drop(rust::String *self) noexcept;
-const char *cxxbridge02$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge02$string$len(const rust::String *self) noexcept;
+void cxxbridge03$string$drop(rust::String *self) noexcept;
+const char *cxxbridge03$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge03$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge02$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge03$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge02 {
+inline namespace cxxbridge03 {
 
-String::String() noexcept { cxxbridge02$string$new(this); }
+String::String() noexcept { cxxbridge03$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge02$string$clone(this, other);
+  cxxbridge03$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge02$string$new(&other);
+  cxxbridge03$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge02$string$drop(this); }
+String::~String() noexcept { cxxbridge03$string$drop(this); }
 
 String::String(const std::string &s) {
   auto ptr = s.data();
   auto len = s.length();
-  if (!cxxbridge02$string$from(this, ptr, len)) {
+  if (!cxxbridge03$string$from(this, ptr, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String::String(const char *s) {
   auto len = std::strlen(s);
-  if (!cxxbridge02$string$from(this, s, len)) {
+  if (!cxxbridge03$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge02$string$drop(this);
-    cxxbridge02$string$clone(this, other);
+    cxxbridge03$string$drop(this);
+    cxxbridge03$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge02$string$drop(this);
+    cxxbridge03$string$drop(this);
     this->repr = other.repr;
-    cxxbridge02$string$new(&other);
+    cxxbridge03$string$new(&other);
   }
   return *this;
 }
@@ -92,12 +92,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge02$string$ptr(this);
+  return cxxbridge03$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge02$string$len(this); }
+size_t String::size() const noexcept { return cxxbridge03$string$len(this); }
 
-size_t String::length() const noexcept { return cxxbridge02$string$len(this); }
+size_t String::length() const noexcept { return cxxbridge03$string$len(this); }
 
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
@@ -112,13 +112,13 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 Str::Str(const Str &) noexcept = default;
 
 Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
 Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
-  if (!cxxbridge02$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
@@ -148,7 +148,7 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
 }
 
 extern "C" {
-const char *cxxbridge02$error(const char *ptr, size_t len) {
+const char *cxxbridge03$error(const char *ptr, size_t len) {
   char *copy = new char[len];
   strncpy(copy, ptr, len);
   return copy;
@@ -158,7 +158,7 @@ const char *cxxbridge02$error(const char *ptr, size_t len) {
 Error::Error(Str::Repr msg) noexcept : msg(msg) {}
 
 Error::Error(const Error &other) {
-  this->msg.ptr = cxxbridge02$error(other.msg.ptr, other.msg.len);
+  this->msg.ptr = cxxbridge03$error(other.msg.ptr, other.msg.len);
   this->msg.len = other.msg.len;
 }
 
@@ -173,96 +173,96 @@ Error::~Error() noexcept { delete[] this->msg.ptr; }
 
 const char *Error::what() const noexcept { return this->msg.ptr; }
 
-} // namespace cxxbridge02
+} // namespace cxxbridge03
 } // namespace rust
 
 extern "C" {
-void cxxbridge02$unique_ptr$std$string$null(
+void cxxbridge03$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge02$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+void cxxbridge03$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge02$unique_ptr$std$string$get(
+const std::string *cxxbridge03$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge02$unique_ptr$std$string$release(
+std::string *cxxbridge03$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge02$unique_ptr$std$string$drop(
+void cxxbridge03$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
 } // extern "C"
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  size_t cxxbridge02$std$vector$##RUST_TYPE##$size(                            \
+  size_t cxxbridge03$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge02$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE *cxxbridge03$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
   const std::vector<CXX_TYPE>                                                  \
-      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
+      *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
           const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
   std::vector<CXX_TYPE>                                                        \
-      *cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$release(                \
+      *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$release(                \
           std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
-  void cxxbridge02$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
   }
 
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
-  void cxxbridge02$rust_vec$##RUST_TYPE##$new(                                 \
+  void cxxbridge03$rust_vec$##RUST_TYPE##$new(                                 \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  void cxxbridge02$rust_vec$##RUST_TYPE##$drop(                                \
+  void cxxbridge03$rust_vec$##RUST_TYPE##$drop(                                \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  size_t cxxbridge02$rust_vec$##RUST_TYPE##$len(                               \
+  size_t cxxbridge03$rust_vec$##RUST_TYPE##$len(                               \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  const CXX_TYPE *cxxbridge02$rust_vec$##RUST_TYPE##$data(                     \
+  const CXX_TYPE *cxxbridge03$rust_vec$##RUST_TYPE##$data(                     \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  size_t cxxbridge02$rust_vec$##RUST_TYPE##$stride() noexcept;
+  size_t cxxbridge03$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
   Vec<CXX_TYPE>::Vec() noexcept {                                              \
-    cxxbridge02$rust_vec$##RUST_TYPE##$new(this);                              \
+    cxxbridge03$rust_vec$##RUST_TYPE##$new(this);                              \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::drop() noexcept {                                        \
-    return cxxbridge02$rust_vec$##RUST_TYPE##$drop(this);                      \
+    return cxxbridge03$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::size() const noexcept {                                \
-    return cxxbridge02$rust_vec$##RUST_TYPE##$len(this);                       \
+    return cxxbridge03$rust_vec$##RUST_TYPE##$len(this);                       \
   }                                                                            \
   template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
-    return cxxbridge02$rust_vec$##RUST_TYPE##$data(this);                      \
+    return cxxbridge03$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
-    return cxxbridge02$rust_vec$##RUST_TYPE##$stride();                        \
+    return cxxbridge03$rust_vec$##RUST_TYPE##$stride();                        \
   }
 
 // Usize and isize are the same type as one of the below.
@@ -289,7 +289,7 @@ FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge02 {
+inline namespace cxxbridge03 {
 FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
-} // namespace cxxbridge02
+} // namespace cxxbridge03
 } // namespace rust
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 54fad27..ffd0c5c 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -4,9 +4,9 @@ use std::slice;
 use std::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge02$cxx_string$data"]
+    #[link_name = "cxxbridge03$cxx_string$data"]
     fn string_data(_: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge02$cxx_string$length"]
+    #[link_name = "cxxbridge03$cxx_string$length"]
     fn string_length(_: &CxxString) -> usize;
 }
 
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 695fcad..0d952f9 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -137,7 +137,7 @@ macro_rules! impl_vector_element_for_primitive {
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$size")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -146,7 +146,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$std$vector$", stringify!($ty), "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -155,7 +155,7 @@ macro_rules! impl_vector_element_for_primitive {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -166,7 +166,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -177,7 +177,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -186,7 +186,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -195,7 +195,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge02$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
diff --git a/src/exception.rs b/src/exception.rs
index c436196..52f0cf6 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -21,7 +21,7 @@ impl Exception {
     }
 }
 
-#[export_name = "cxxbridge02$exception"]
+#[export_name = "cxxbridge03$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
     let slice = slice::from_raw_parts(ptr, len);
     let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
diff --git a/src/result.rs b/src/result.rs
index 296efea..0373bd8 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -32,7 +32,7 @@ unsafe fn to_c_error(msg: String) -> Result {
     let len = msg.len();
 
     extern "C" {
-        #[link_name = "cxxbridge02$error"]
+        #[link_name = "cxxbridge03$error"]
         fn error(ptr: *const u8, len: usize) -> *const u8;
     }
 
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 184e2c1..fe11473 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -25,7 +25,7 @@ impl RustStr {
     }
 }
 
-#[export_name = "cxxbridge02$str$valid"]
+#[export_name = "cxxbridge03$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 3fba2f5..6f3e64b 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -30,17 +30,17 @@ impl RustString {
     }
 }
 
-#[export_name = "cxxbridge02$string$new"]
+#[export_name = "cxxbridge03$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge02$string$clone"]
+#[export_name = "cxxbridge03$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge02$string$from"]
+#[export_name = "cxxbridge03$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -56,17 +56,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge02$string$drop"]
+#[export_name = "cxxbridge03$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge02$string$ptr"]
+#[export_name = "cxxbridge03$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge02$string$len"]
+#[export_name = "cxxbridge03$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index d5de489..c17310d 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -47,31 +47,31 @@ macro_rules! rust_vec_shims_for_primitive {
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$new")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec::new());
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$drop")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$len")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$data")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge02$rust_vec$", stringify!($ty), "$stride")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 98b4b7d..34a1f0e 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -174,15 +174,15 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge02$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge03$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge02$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge03$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge02$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge03$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge02$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge03$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge02$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge03$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 1380704..c9392db 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -3,7 +3,7 @@ use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::ExternFn;
 use proc_macro2::Ident;
 
-const CXXBRIDGE: &str = "cxxbridge02";
+const CXXBRIDGE: &str = "cxxbridge03";
 
 macro_rules! join {
     ($($segment:expr),*) => {
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index fa8e587..066d238 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -4,7 +4,7 @@ use quote::ToTokens;
 use std::fmt::{self, Display, Write};
 
 // A mangled symbol consisting of segments separated by '$'.
-// For example: cxxbridge02$string$new
+// For example: cxxbridge03$string$new
 pub struct Symbol(String);
 
 impl Display for Symbol {

From c1d23a07ff5e18687e2a90e1ee578fe97361237d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:51:55 +0000
Subject: [PATCH 487/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 54a1e85..3500cb0 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.2/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.3/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
diff --git a/third-party/BUILD b/third-party/BUILD
index c6ce473..b6605e4 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -36,7 +36,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.2/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.3/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f4068d9..b778e5b 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -55,9 +55,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.2"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4efca5ddfdf45cee2eedd9dadbe7a5fa90a5536af6f580f1814267b2a4d6107f"
+checksum = "d5680df8512a0e825b9edc41b619ec88b367644d394b4d862a04b4d6387c65da"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -266,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.51"
+version = "1.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9"
+checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd"
 dependencies = [
  "itoa",
  "ryu",

From cc9ece5186a3a06becdfac2d42e5c86252d277f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:57:05 +0000
Subject: [PATCH 488/2232] Document the line that needs to go in build-dependencies


---

diff --git a/README.md b/README.md
index 59bcdac..78a62a2 100644
--- a/README.md
+++ b/README.md
@@ -215,6 +215,13 @@ set up any additional source files and compiler flags as normal.
 
 [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
 
+```toml
+# Cargo.toml
+
+[build-dependencies]
+cxx-build = "0.2"
+```
+
 ```rust
 // build.rs
 
diff --git a/src/lib.rs b/src/lib.rs
index 7e8e9ec..f97ab96 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -220,6 +220,13 @@
 //!
 //! [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
 //!
+//! ```toml
+//! # Cargo.toml
+//!
+//! [build-dependencies]
+//! cxx-build = "0.2"
+//! ```
+//!
 //! ```no_run
 //! // build.rs
 //!

From 63a4384af71e9920bd7e1bcc59b1d80f2380192c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 01:57:39 +0000
Subject: [PATCH 489/2232] Release 0.3.0


---

diff --git a/Cargo.toml b/Cargo.toml
index ad40cad..f5e5b9f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.2.12" # remember to update html_root_url
+version = "0.3.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -15,14 +15,14 @@ exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 travis-ci = { repository = "dtolnay/cxx" }
 
 [dependencies]
-cxxbridge-macro = { version = "=0.2.12", path = "macro" }
+cxxbridge-macro = { version = "=0.3.0", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.2.12", path = "gen/build" }
+cxx-build = { version = "=0.3.0", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.21", features = ["diff"] }
diff --git a/README.md b/README.md
index 78a62a2..f1cf00f 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ can be 100% safe.
 
 ```toml
 [dependencies]
-cxx = "0.2"
+cxx = "0.3"
 ```
 
 *Compiler support: requires rustc 1.42+*<br>
@@ -219,7 +219,7 @@ set up any additional source files and compiler flags as normal.
 # Cargo.toml
 
 [build-dependencies]
-cxx-build = "0.2"
+cxx-build = "0.3"
 ```
 
 ```rust
@@ -307,11 +307,11 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.2/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3552524..869f543 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.2.12"
+version = "0.3.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 742d54b..9927d3f 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.2.12"
+version = "0.3.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index c7c48ec..51fba71 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.2.12"
+version = "0.3.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -20,7 +20,7 @@ quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.2", path = ".." }
+cxx = { version = "0.3", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index f97ab96..37fc5ef 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -224,7 +224,7 @@
 //! # Cargo.toml
 //!
 //! [build-dependencies]
-//! cxx-build = "0.2"
+//! cxx-build = "0.3"
 //! ```
 //!
 //! ```no_run
@@ -343,7 +343,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.2.12")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.0")]
 #![deny(improper_ctypes)]
 #![allow(
     clippy::cognitive_complexity,
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b778e5b..f4e5903 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.2.12"
+version = "0.3.0"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.2.12"
+version = "0.3.0"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.2.12"
+version = "0.3.0"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.2.12"
+version = "0.3.0"
 dependencies = [
  "cxx",
  "proc-macro2",

From a5ca1164b7e457641a01fcf0911ced8929d1efa9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 05:03:27 +0000
Subject: [PATCH 490/2232] Pin bazel CI to stable 1.43.0


---

diff --git a/WORKSPACE b/WORKSPACE
index 501bde0..4269fbc 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,15 +24,13 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_43_beta_linux",
+    name = "rust_1_43_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    iso_date = "2020-04-19",
-    version = "beta",
+    version = "1.43.0",
 )
 
 rust_repository_set(
-    name = "rust_1_43_beta_darwin",
+    name = "rust_1_43_darwin",
     exec_triple = "x86_64-apple-darwin",
-    iso_date = "2020-04-19",
-    version = "beta",
+    version = "1.43.0",
 )

From 74dd379f093a2955d7657dffb7d5acfa9e9aeaaa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 14:45:24 +0000
Subject: [PATCH 491/2232] Format PR 157 with clang-format


---

diff --git a/include/cxx.h b/include/cxx.h
index 7762719..d870442 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -237,8 +237,8 @@ public:
   public:
     using difference_type = ptrdiff_t;
     using value_type = typename std::add_const<T>::type;
-    using pointer = typename std::add_pointer<
-        typename std::add_const<T>::type>::type;
+    using pointer =
+        typename std::add_pointer<typename std::add_const<T>::type>::type;
     using reference = typename std::add_lvalue_reference<
         typename std::add_const<T>::type>::type;
     using iterator_category = std::forward_iterator_tag;

From 3c90cd2ef80e799c249436f4679aa3c12d1f2b91 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 14:45:34 +0000
Subject: [PATCH 492/2232] Move Rust symbols required by C++ to a separate Buck target


Closes #168.

---

diff --git a/BUCK b/BUCK
index 2339f71..acf3a4c 100644
--- a/BUCK
+++ b/BUCK
@@ -1,7 +1,8 @@
 rust_library(
     name = "cxx",
-    srcs = glob(["src/**"]),
+    srcs = glob(["src/**"], exclude = ["src/symbols/**"]),
     visibility = ["PUBLIC"],
+    rustc_flags = ["--cfg", "no_export_symbols"],
     deps = [
         ":core",
         ":macro",
@@ -33,6 +34,13 @@ cxx_library(
         "cxx.h": "include/cxx.h",
     },
     exported_linker_flags = ["-lstdc++"],
+    deps = [":symbols"],
+)
+
+rust_library(
+    name = "symbols",
+    srcs = glob(["src/macros/**", "src/symbols/**"]),
+    crate_root = "src/symbols/lib.rs",
 )
 
 rust_library(
diff --git a/src/assert.rs b/src/assert.rs
deleted file mode 100644
index 738e5bb..0000000
--- a/src/assert.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-macro_rules! const_assert_eq {
-    ($left:expr, $right:expr $(,)?) => {
-        const _: [(); $left] = [(); $right];
-    };
-}
diff --git a/src/concat.rs b/src/concat.rs
deleted file mode 100644
index e67e50d..0000000
--- a/src/concat.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-macro_rules! attr {
-    (#[$name:ident = $value:expr] $($rest:tt)*) => {
-        #[$name = $value]
-        $($rest)*
-    };
-}
diff --git a/src/exception.rs b/src/exception.rs
index 52f0cf6..125e484 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,5 +1,4 @@
 use std::fmt::{self, Debug, Display};
-use std::slice;
 
 /// Exception thrown from an `extern "C"` function.
 #[derive(Debug)]
@@ -20,10 +19,3 @@ impl Exception {
         &self.what
     }
 }
-
-#[export_name = "cxxbridge03$exception"]
-unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
-    let slice = slice::from_raw_parts(ptr, len);
-    let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
-    Box::leak(boxed).as_ptr()
-}
diff --git a/src/lib.rs b/src/lib.rs
index 37fc5ef..86318c8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,9 +363,7 @@
 extern crate link_cplusplus;
 
 #[macro_use]
-mod assert;
-#[macro_use]
-mod concat;
+mod macros;
 
 mod cxx_string;
 mod cxx_vector;
@@ -380,6 +378,9 @@ mod rust_vec;
 mod unique_ptr;
 mod unwind;
 
+#[cfg(not(no_export_symbols))]
+mod symbols;
+
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
diff --git a/src/macros/assert.rs b/src/macros/assert.rs
new file mode 100644
index 0000000..738e5bb
--- /dev/null
+++ b/src/macros/assert.rs
@@ -0,0 +1,5 @@
+macro_rules! const_assert_eq {
+    ($left:expr, $right:expr $(,)?) => {
+        const _: [(); $left] = [(); $right];
+    };
+}
diff --git a/src/macros/concat.rs b/src/macros/concat.rs
new file mode 100644
index 0000000..e67e50d
--- /dev/null
+++ b/src/macros/concat.rs
@@ -0,0 +1,6 @@
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
diff --git a/src/macros/mod.rs b/src/macros/mod.rs
new file mode 100644
index 0000000..d12d96b
--- /dev/null
+++ b/src/macros/mod.rs
@@ -0,0 +1,4 @@
+#[macro_use]
+mod assert;
+#[macro_use]
+mod concat;
diff --git a/src/rust_str.rs b/src/rust_str.rs
index fe11473..b944ede 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -25,10 +25,4 @@ impl RustStr {
     }
 }
 
-#[export_name = "cxxbridge03$str$valid"]
-unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
-    let slice = slice::from_raw_parts(ptr, len);
-    str::from_utf8(slice).is_ok()
-}
-
 const_assert_eq!(mem::size_of::<Option<RustStr>>(), mem::size_of::<RustStr>());
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 6f3e64b..a923ced 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -1,7 +1,4 @@
-use std::mem::{self, ManuallyDrop, MaybeUninit};
-use std::ptr;
-use std::slice;
-use std::str;
+use std::mem;
 
 #[repr(C)]
 pub struct RustString {
@@ -30,46 +27,5 @@ impl RustString {
     }
 }
 
-#[export_name = "cxxbridge03$string$new"]
-unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
-    ptr::write(this.as_mut_ptr(), String::new());
-}
-
-#[export_name = "cxxbridge03$string$clone"]
-unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
-    ptr::write(this.as_mut_ptr(), other.clone());
-}
-
-#[export_name = "cxxbridge03$string$from"]
-unsafe extern "C" fn string_from(
-    this: &mut MaybeUninit<String>,
-    ptr: *const u8,
-    len: usize,
-) -> bool {
-    let slice = slice::from_raw_parts(ptr, len);
-    match str::from_utf8(slice) {
-        Ok(s) => {
-            ptr::write(this.as_mut_ptr(), s.to_owned());
-            true
-        }
-        Err(_) => false,
-    }
-}
-
-#[export_name = "cxxbridge03$string$drop"]
-unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
-    ManuallyDrop::drop(this);
-}
-
-#[export_name = "cxxbridge03$string$ptr"]
-unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
-    this.as_ptr()
-}
-
-#[export_name = "cxxbridge03$string$len"]
-unsafe extern "C" fn string_len(this: &String) -> usize {
-    this.len()
-}
-
 const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<String>());
 const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<String>());
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index c17310d..4c5035d 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,6 +1,3 @@
-use std::mem;
-use std::ptr;
-
 #[repr(C)]
 pub struct RustVec<T> {
     repr: Vec<T>,
@@ -39,54 +36,3 @@ impl<T> RustVec<T> {
         self.repr.as_ptr()
     }
 }
-
-macro_rules! rust_vec_shims_for_primitive {
-    ($ty:ident) => {
-        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
-        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
-
-        const _: () = {
-            attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
-                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
-                    ptr::write(this, RustVec::new());
-                }
-            }
-            attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
-                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
-                    ptr::drop_in_place(this);
-                }
-            }
-            attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
-                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
-                    (*this).len()
-                }
-            }
-            attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
-                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
-                    (*this).as_ptr()
-                }
-            }
-            attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
-                unsafe extern "C" fn __stride() -> usize {
-                    mem::size_of::<$ty>()
-                }
-            }
-        };
-    };
-}
-
-rust_vec_shims_for_primitive!(u8);
-rust_vec_shims_for_primitive!(u16);
-rust_vec_shims_for_primitive!(u32);
-rust_vec_shims_for_primitive!(u64);
-rust_vec_shims_for_primitive!(i8);
-rust_vec_shims_for_primitive!(i16);
-rust_vec_shims_for_primitive!(i32);
-rust_vec_shims_for_primitive!(i64);
-rust_vec_shims_for_primitive!(f32);
-rust_vec_shims_for_primitive!(f64);
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
new file mode 100644
index 0000000..849db3b
--- /dev/null
+++ b/src/symbols/exception.rs
@@ -0,0 +1,8 @@
+use std::slice;
+
+#[export_name = "cxxbridge03$exception"]
+unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
+    let slice = slice::from_raw_parts(ptr, len);
+    let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
+    Box::leak(boxed).as_ptr()
+}
diff --git a/src/symbols/lib.rs b/src/symbols/lib.rs
new file mode 100644
index 0000000..2c052ec
--- /dev/null
+++ b/src/symbols/lib.rs
@@ -0,0 +1,5 @@
+#[path = "../macros/mod.rs"]
+#[macro_use]
+mod macros;
+
+include!("mod.rs");
diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs
new file mode 100644
index 0000000..a9d158d
--- /dev/null
+++ b/src/symbols/mod.rs
@@ -0,0 +1,4 @@
+mod exception;
+mod rust_str;
+mod rust_string;
+mod rust_vec;
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
new file mode 100644
index 0000000..6dc04ac
--- /dev/null
+++ b/src/symbols/rust_str.rs
@@ -0,0 +1,8 @@
+use std::slice;
+use std::str;
+
+#[export_name = "cxxbridge03$str$valid"]
+unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
+    let slice = slice::from_raw_parts(ptr, len);
+    str::from_utf8(slice).is_ok()
+}
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
new file mode 100644
index 0000000..63d4ba7
--- /dev/null
+++ b/src/symbols/rust_string.rs
@@ -0,0 +1,45 @@
+use std::mem::{ManuallyDrop, MaybeUninit};
+use std::ptr;
+use std::slice;
+use std::str;
+
+#[export_name = "cxxbridge03$string$new"]
+unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
+    ptr::write(this.as_mut_ptr(), String::new());
+}
+
+#[export_name = "cxxbridge03$string$clone"]
+unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
+    ptr::write(this.as_mut_ptr(), other.clone());
+}
+
+#[export_name = "cxxbridge03$string$from"]
+unsafe extern "C" fn string_from(
+    this: &mut MaybeUninit<String>,
+    ptr: *const u8,
+    len: usize,
+) -> bool {
+    let slice = slice::from_raw_parts(ptr, len);
+    match str::from_utf8(slice) {
+        Ok(s) => {
+            ptr::write(this.as_mut_ptr(), s.to_owned());
+            true
+        }
+        Err(_) => false,
+    }
+}
+
+#[export_name = "cxxbridge03$string$drop"]
+unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
+    ManuallyDrop::drop(this);
+}
+
+#[export_name = "cxxbridge03$string$ptr"]
+unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
+    this.as_ptr()
+}
+
+#[export_name = "cxxbridge03$string$len"]
+unsafe extern "C" fn string_len(this: &String) -> usize {
+    this.len()
+}
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
new file mode 100644
index 0000000..712a9e8
--- /dev/null
+++ b/src/symbols/rust_vec.rs
@@ -0,0 +1,65 @@
+use std::mem;
+use std::ptr;
+
+#[repr(C)]
+pub struct RustVec<T> {
+    repr: Vec<T>,
+}
+
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
+
+macro_rules! rust_vec_shims_for_primitive {
+    ($ty:ident) => {
+        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
+        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
+
+        const _: () = {
+            attr! {
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
+                unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
+                    ptr::write(this, RustVec { repr: Vec::new() });
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
+                unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
+                    ptr::drop_in_place(this);
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
+                unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
+                    (*this).repr.len()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
+                unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
+                    (*this).repr.as_ptr()
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
+                unsafe extern "C" fn __stride() -> usize {
+                    mem::size_of::<$ty>()
+                }
+            }
+        };
+    };
+}
+
+rust_vec_shims_for_primitive!(u8);
+rust_vec_shims_for_primitive!(u16);
+rust_vec_shims_for_primitive!(u32);
+rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(i8);
+rust_vec_shims_for_primitive!(i16);
+rust_vec_shims_for_primitive!(i32);
+rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(f32);
+rust_vec_shims_for_primitive!(f64);

From 4ee9ecabbdcc283a901a13ffd57c2c4eb64ffcd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 14:48:25 +0000
Subject: [PATCH 493/2232] Re-enable Buck CI


---

diff --git a/.travis.yml b/.travis.yml
index 0243407..f65f7f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -62,7 +62,3 @@ matrix:
       rust: 1.42.0
       script:
         - cargo run --manifest-path demo-rs/Cargo.toml
-
-  # https://github.com/dtolnay/cxx/pull/167
-  allow_failures:
-    - name: Buck

From 7997d07818aaebf990bc79bcb27ee4a64d5e757d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 14:55:08 +0000
Subject: [PATCH 494/2232] Avoid second lib.rs in the same src directory


This was throwing off the Bazel build because it didn't know which one
to make the crate root.

---

diff --git a/BUCK b/BUCK
index acf3a4c..241d7b3 100644
--- a/BUCK
+++ b/BUCK
@@ -40,7 +40,7 @@ cxx_library(
 rust_library(
     name = "symbols",
     srcs = glob(["src/macros/**", "src/symbols/**"]),
-    crate_root = "src/symbols/lib.rs",
+    crate_root = "src/symbols/symbols.rs",
 )
 
 rust_library(
diff --git a/src/symbols/lib.rs b/src/symbols/lib.rs
deleted file mode 100644
index 2c052ec..0000000
--- a/src/symbols/lib.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[path = "../macros/mod.rs"]
-#[macro_use]
-mod macros;
-
-include!("mod.rs");
diff --git a/src/symbols/symbols.rs b/src/symbols/symbols.rs
new file mode 100644
index 0000000..2c052ec
--- /dev/null
+++ b/src/symbols/symbols.rs
@@ -0,0 +1,5 @@
+#[path = "../macros/mod.rs"]
+#[macro_use]
+mod macros;
+
+include!("mod.rs");

From f336b3b3435258570e85f626063f4ed8740bd92a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 15:45:54 +0000
Subject: [PATCH 495/2232] Add support for rust::Vec<bool>


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 5f7ac6a..eb86d3d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -266,7 +266,7 @@ void cxxbridge03$unique_ptr$std$string$drop(
   }
 
 // Usize and isize are the same type as one of the below.
-#define FOR_EACH_SIZED_PRIMITIVE(MACRO)                                        \
+#define FOR_EACH_NUMERIC(MACRO)                                                \
   MACRO(u8, uint8_t)                                                           \
   MACRO(u16, uint16_t)                                                         \
   MACRO(u32, uint32_t)                                                         \
@@ -278,18 +278,22 @@ void cxxbridge03$unique_ptr$std$string$drop(
   MACRO(f32, float)                                                            \
   MACRO(f64, double)
 
-#define FOR_EACH_PRIMITIVE(MACRO)                                              \
-  FOR_EACH_SIZED_PRIMITIVE(MACRO)                                              \
+#define FOR_EACH_STD_VECTOR(MACRO)                                             \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(usize, size_t)                                                         \
   MACRO(isize, rust::isize)
 
+#define FOR_EACH_RUST_VEC(MACRO)                                               \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
+  MACRO(bool, bool)
+
 extern "C" {
-FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
-FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
+FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
+FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
 inline namespace cxxbridge03 {
-FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
+FOR_EACH_RUST_VEC(RUST_VEC_OPS)
 } // namespace cxxbridge03
 } // namespace rust
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 712a9e8..9ce87ab 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -53,6 +53,7 @@ macro_rules! rust_vec_shims_for_primitive {
     };
 }
 
+rust_vec_shims_for_primitive!(bool);
 rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
 rust_vec_shims_for_primitive!(u32);

From d776519a75a5e26e3259f8008ea228f83193cdf8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Apr 30 2020 15:55:43 +0000
Subject: [PATCH 496/2232] Merge pull request #169 from dtolnay/vecbool


Add support for rust::Vec<bool>
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 5f7ac6a..eb86d3d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -266,7 +266,7 @@ void cxxbridge03$unique_ptr$std$string$drop(
   }
 
 // Usize and isize are the same type as one of the below.
-#define FOR_EACH_SIZED_PRIMITIVE(MACRO)                                        \
+#define FOR_EACH_NUMERIC(MACRO)                                                \
   MACRO(u8, uint8_t)                                                           \
   MACRO(u16, uint16_t)                                                         \
   MACRO(u32, uint32_t)                                                         \
@@ -278,18 +278,22 @@ void cxxbridge03$unique_ptr$std$string$drop(
   MACRO(f32, float)                                                            \
   MACRO(f64, double)
 
-#define FOR_EACH_PRIMITIVE(MACRO)                                              \
-  FOR_EACH_SIZED_PRIMITIVE(MACRO)                                              \
+#define FOR_EACH_STD_VECTOR(MACRO)                                             \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(usize, size_t)                                                         \
   MACRO(isize, rust::isize)
 
+#define FOR_EACH_RUST_VEC(MACRO)                                               \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
+  MACRO(bool, bool)
+
 extern "C" {
-FOR_EACH_PRIMITIVE(STD_VECTOR_OPS)
-FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_EXTERNS)
+FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
+FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
 inline namespace cxxbridge03 {
-FOR_EACH_SIZED_PRIMITIVE(RUST_VEC_OPS)
+FOR_EACH_RUST_VEC(RUST_VEC_OPS)
 } // namespace cxxbridge03
 } // namespace rust
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 712a9e8..9ce87ab 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -53,6 +53,7 @@ macro_rules! rust_vec_shims_for_primitive {
     };
 }
 
+rust_vec_shims_for_primitive!(bool);
 rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
 rust_vec_shims_for_primitive!(u32);

From c03402aee567f6594de660c77f7ca3daf0862d5f Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: Apr 30 2020 21:12:37 +0000
Subject: [PATCH 497/2232] Support C-style enums


This adds support for passing C-style enums between Rust and C++.

We use the Rust representation for enums suggested by dtolnay in #132.
Note that as this does not use real enums, Rust code cannot treat them
as normal enums, e.g., by converting them to integers.  But common
uses such as pattern matching remain unchanged.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8869849..eb72ba4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,7 @@ use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -64,6 +64,10 @@ pub(super) fn gen(
                 out.next_section();
                 write_struct(out, strct);
             }
+            Api::Enum(enm) => {
+                out.next_section();
+                write_enum(out, enm);
+            }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
                     out.next_section();
@@ -353,6 +357,22 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     writeln!(out, "}};");
 }
 
+fn write_enum(out: &mut OutFile, enm: &Enum) {
+    for line in enm.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "enum class {} : uint32_t {{", enm.ident);
+    for variant in &enm.variants {
+        write!(out, "  ");
+        write!(out, "{}", variant.ident);
+        if let Some(discriminant) = &variant.discriminant {
+            write!(out, " = {}", discriminant);
+        }
+        writeln!(out, ",");
+    }
+    writeln!(out, "}};");
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 15a091b..788a156 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -36,6 +36,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         match api {
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => expanded.extend(expand_cxx_type(ety)),
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(namespace, efn, types));
@@ -123,6 +124,34 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     }
 }
 
+fn expand_enum(enm: &Enum) -> TokenStream {
+    let ident = &enm.ident;
+    let doc = &enm.doc;
+    let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
+        // This span on the pub makes "private type in public interface" errors
+        // appear in the right place.
+        let vis = Token![pub](variant.ident.span());
+        let variant_ident = &variant.ident;
+        let discriminant = match variant.discriminant {
+            None => *next_discriminant,
+            Some(val) => val,
+        };
+        *next_discriminant = discriminant + 1;
+        Some(quote!(  #vis const #variant_ident: Self = #ident(#discriminant)))
+    });
+    quote! {
+        #doc
+        #[derive(Copy, Clone, PartialEq, Eq)]
+        #[repr(transparent)]
+        pub struct #ident(u32);
+
+        #[allow(non_upper_case_globals)]
+        impl #ident {
+            #(#variants;)*
+        }
+    }
+}
+
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     let doc = &ety.doc;
diff --git a/syntax/check.rs b/syntax/check.rs
index 3e121b5..321fb1a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,9 +1,11 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{
-    error, ident, Api, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+    error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
+    Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
+use std::collections::HashSet;
 use std::fmt::Display;
 use syn::{Error, Result};
 
@@ -41,6 +43,7 @@ fn do_typecheck(cx: &mut Check) {
     for api in cx.apis {
         match api {
             Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
@@ -68,6 +71,7 @@ impl Check<'_> {
 fn check_type_ident(cx: &mut Check, ident: &Ident) {
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
+        && !cx.types.enums.contains_key(ident)
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
@@ -188,6 +192,28 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
     }
 }
 
+fn check_api_enum(cx: &mut Check, enm: &Enum) {
+    check_reserved_name(cx, &enm.ident);
+
+    if enm.variants.is_empty() {
+        let span = span_for_enum_error(enm);
+        cx.error(span, "enums without any variants are not supported");
+    }
+
+    let mut discriminants = HashSet::new();
+    enm.variants.iter().fold(0, |next_discriminant, variant| {
+        let discriminant = match variant.discriminant {
+            None => next_discriminant,
+            Some(val) => val,
+        };
+        if !discriminants.insert(discriminant) {
+            let msg = format!("discriminant value `{}` already exists", discriminant);
+            cx.error(span_for_enum_error(enm), msg);
+        }
+        discriminant + 1
+    });
+}
+
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
     check_reserved_name(cx, &ty.ident);
 }
@@ -320,6 +346,13 @@ fn span_for_struct_error(strct: &Struct) -> TokenStream {
     quote!(#struct_token #brace_token)
 }
 
+fn span_for_enum_error(enm: &Enum) -> TokenStream {
+    let enum_token = enm.enum_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(enm.brace_token.span);
+    quote!(#enum_token #brace_token)
+}
+
 fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
     let ampersand = receiver.ampersand;
     let lifetime = &receiver.lifetime;
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 84be4cb..d5bb33f 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -23,6 +23,12 @@ pub(crate) fn check_all(apis: &[Api], errors: &mut Vec<Error>) {
                     errors.extend(check(&field.ident).err());
                 }
             }
+            Api::Enum(enm) => {
+                errors.extend(check(&enm.ident).err());
+                for variant in &enm.variants {
+                    errors.extend(check(&variant.ident).err());
+                }
+            }
             Api::CxxType(ety) | Api::RustType(ety) => {
                 errors.extend(check(&ety.ident).err());
             }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index a4b0ac4..9b1a7e5 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -29,6 +29,7 @@ pub use self::types::Types;
 pub enum Api {
     Include(LitStr),
     Struct(Struct),
+    Enum(Enum),
     CxxType(ExternType),
     CxxFunction(ExternFn),
     RustType(ExternType),
@@ -50,6 +51,14 @@ pub struct Struct {
     pub fields: Vec<Var>,
 }
 
+pub struct Enum {
+    pub doc: Doc,
+    pub enum_token: Token![enum],
+    pub ident: Ident,
+    pub brace_token: Brace,
+    pub variants: Vec<Variant>,
+}
+
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
@@ -83,6 +92,11 @@ pub struct Receiver {
     pub shorthand: bool,
 }
 
+pub struct Variant {
+    pub ident: Ident,
+    pub discriminant: Option<u32>,
+}
+
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a425c56..995b21f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,14 +1,15 @@
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, Struct,
-    Ty1, Type, Var,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Var, Variant,
 };
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Ident,
-    Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token,
-    Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat, PathArguments,
+    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Variant as RustVariant,
 };
 
 pub mod kw {
@@ -23,6 +24,10 @@ pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
                 let strct = parse_struct(item)?;
                 apis.push(strct);
             }
+            Item::Enum(item) => {
+                let enm = parse_enum(item)?;
+                apis.push(enm);
+            }
             Item::ForeignMod(foreign_mod) => {
                 let functions = parse_foreign_mod(foreign_mod)?;
                 apis.extend(functions);
@@ -78,6 +83,75 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     }))
 }
 
+fn parse_enum(item: ItemEnum) -> Result<Api> {
+    let generics = &item.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        let enum_token = item.enum_token;
+        let ident = &item.ident;
+        let where_clause = &generics.where_clause;
+        let span = quote!(#enum_token #ident #generics #where_clause);
+        return Err(Error::new_spanned(
+            span,
+            "enums with generic parameters are not allowed",
+        ));
+    }
+
+    let mut doc = Doc::new();
+    attrs::parse(&item.attrs, &mut doc, None)?;
+
+    for variant in &item.variants {
+        match &variant.fields {
+            Fields::Unit => {}
+            _ => {
+                return Err(Error::new_spanned(
+                    variant,
+                    "enums with data are not allowed",
+                ))
+            }
+        }
+    }
+
+    Ok(Api::Enum(Enum {
+        doc,
+        enum_token: item.enum_token,
+        ident: item.ident,
+        brace_token: item.brace_token,
+        variants: item
+            .variants
+            .into_iter()
+            .map(parse_variant)
+            .collect::<Result<_>>()?,
+    }))
+}
+
+fn parse_variant(variant: RustVariant) -> Result<Variant> {
+    match &variant.discriminant {
+        None => Ok(Variant {
+            ident: variant.ident,
+            discriminant: None,
+        }),
+        Some((
+            _,
+            Expr::Lit(ExprLit {
+                lit: Lit::Int(n), ..
+            }),
+        )) => match n.base10_digits().parse() {
+            Ok(val) => Ok(Variant {
+                ident: variant.ident,
+                discriminant: Some(val),
+            }),
+            Err(_) => Err(Error::new_spanned(
+                variant,
+                "cannot parse enum discriminant as an integer",
+            )),
+        },
+        _ => Err(Error::new_spanned(
+            variant,
+            "enums with non-integer literal discriminants are not supported",
+        )),
+    }
+}
+
 fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let lang = parse_lang(foreign_mod.abi)?;
     let api_type = match lang {
diff --git a/syntax/types.rs b/syntax/types.rs
index f3aaa16..bb5a843 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, ExternType, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type};
 use proc_macro2::Ident;
 use quote::quote;
 use std::collections::BTreeMap as Map;
@@ -9,6 +9,7 @@ use syn::{Error, Result};
 pub struct Types<'a> {
     pub all: Set<'a, Type>,
     pub structs: Map<Ident, &'a Struct>,
+    pub enums: Map<Ident, &'a Enum>,
     pub cxx: Set<'a, Ident>,
     pub rust: Set<'a, Ident>,
 }
@@ -17,6 +18,7 @@ impl<'a> Types<'a> {
     pub fn collect(apis: &'a [Api]) -> Result<Self> {
         let mut all = Set::new();
         let mut structs = Map::new();
+        let mut enums = Map::new();
         let mut cxx = Set::new();
         let mut rust = Set::new();
 
@@ -46,7 +48,11 @@ impl<'a> Types<'a> {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_struct(strct));
                     }
                     structs.insert(strct.ident.clone(), strct);
@@ -54,16 +60,35 @@ impl<'a> Types<'a> {
                         visit(&mut all, &field.ty);
                     }
                 }
+                Api::Enum(enm) => {
+                    let ident = &enm.ident;
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
+                        return Err(duplicate_enum(enm));
+                    }
+                    enums.insert(enm.ident.clone(), enm);
+                }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_type(ety));
                     }
                     cxx.insert(ident);
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_type(ety));
                     }
                     rust.insert(ident);
@@ -82,6 +107,7 @@ impl<'a> Types<'a> {
         Ok(Types {
             all,
             structs,
+            enums,
             cxx,
             rust,
         })
@@ -126,6 +152,13 @@ fn duplicate_struct(strct: &Struct) -> Error {
     Error::new_spanned(range, "duplicate type")
 }
 
+fn duplicate_enum(enm: &Enum) -> Error {
+    let enum_token = enm.enum_token;
+    let ident = &enm.ident;
+    let range = quote!(#enum_token #ident);
+    Error::new_spanned(range, "duplicate type")
+}
+
 fn duplicate_type(ety: &ExternType) -> Error {
     let type_token = ety.type_token;
     let ident = &ety.ident;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 01dc404..0162c9b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -13,6 +13,12 @@ pub mod ffi {
         z: usize,
     }
 
+    enum Enum {
+        AVal,
+        BVal = 2020,
+        CVal,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 
@@ -36,6 +42,7 @@ pub mod ffi {
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
+        fn c_return_enum(n: u32) -> Enum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -57,6 +64,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         fn c_take_callback(callback: fn(String) -> usize);
+        fn c_take_enum(e: Enum);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
@@ -92,6 +100,7 @@ pub mod ffi {
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
         fn r_return_sum(_: usize, _: usize) -> usize;
+        fn r_return_enum(n: u32) -> Enum;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -105,6 +114,7 @@ pub mod ffi {
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_rust_vec(v: Vec<u8>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
+        fn r_take_enum(e: Enum);
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
@@ -198,6 +208,16 @@ fn r_return_sum(n1: usize, n2: usize) -> usize {
     n1 + n2
 }
 
+fn r_return_enum(n: u32) -> ffi::Enum {
+    if n <= 0 {
+        ffi::Enum::AVal
+    } else if n <= 2020 {
+        ffi::Enum::BVal
+    } else {
+        ffi::Enum::CVal
+    }
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
@@ -247,6 +267,10 @@ fn r_take_ref_rust_vec(v: &Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_enum(e: ffi::Enum) {
+    let _ = e;
+}
+
 fn r_try_return_void() -> Result<(), Error> {
     Ok(())
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2b5431f..71c90b0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -106,6 +106,16 @@ size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
 
+Enum c_return_enum(uint32_t n) {
+  if (n <= static_cast<uint32_t>(Enum::AVal)) {
+    return Enum::AVal;
+  } else if (n <= static_cast<uint32_t>(Enum::BVal)) {
+    return Enum::BVal;
+  } else {
+    return Enum::CVal;
+  }
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -238,6 +248,12 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
 
+void c_take_enum(Enum e) {
+  if (e == Enum::AVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
@@ -295,6 +311,9 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(*r_return_unique_ptr_string() == "2020");
   ASSERT(r_return_identity(2020) == 2020);
   ASSERT(r_return_sum(2020, 1) == 2021);
+  ASSERT(r_return_enum(0) == Enum::AVal);
+  ASSERT(r_return_enum(1) == Enum::BVal);
+  ASSERT(r_return_enum(2021) == Enum::CVal);
 
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
@@ -306,6 +325,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
+  r_take_enum(Enum::AVal);
 
   ASSERT(r_try_return_primitive() == 2020);
   try {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index da8ca56..d3b7d38 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -7,6 +7,7 @@ namespace tests {
 
 struct R;
 struct Shared;
+enum class Enum : uint32_t;
 
 class C {
 public:
@@ -40,6 +41,7 @@ rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
+Enum c_return_enum(uint32_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -61,6 +63,7 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
+void c_take_enum(Enum e);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index d6850aa..1156d5d 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -51,6 +51,18 @@ fn test_c_return() {
     );
     assert_eq!(2020, ffi::c_return_identity(2020));
     assert_eq!(2021, ffi::c_return_sum(2020, 1));
+    match ffi::c_return_enum(0) {
+        ffi::Enum::AVal => {}
+        _ => assert!(false),
+    }
+    match ffi::c_return_enum(1) {
+        ffi::Enum::BVal => {}
+        _ => assert!(false),
+    }
+    match ffi::c_return_enum(2021) {
+        ffi::Enum::CVal => {}
+        _ => assert!(false),
+    }
 }
 
 #[test]
@@ -106,6 +118,7 @@ fn test_c_take() {
     ]));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    check!(ffi::c_take_enum(ffi::Enum::AVal));
 }
 
 #[test]
diff --git a/tests/ui/data_enums.rs b/tests/ui/data_enums.rs
new file mode 100644
index 0000000..aa23200
--- /dev/null
+++ b/tests/ui/data_enums.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        Field(u64),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/data_enums.stderr b/tests/ui/data_enums.stderr
new file mode 100644
index 0000000..118514e
--- /dev/null
+++ b/tests/ui/data_enums.stderr
@@ -0,0 +1,5 @@
+error: enums with data are not allowed
+ --> $DIR/data_enums.rs:4:9
+  |
+4 |         Field(u64),
+  |         ^^^^^^^^^^
diff --git a/tests/ui/duplicate_enum_discriminants.rs b/tests/ui/duplicate_enum_discriminants.rs
new file mode 100644
index 0000000..ec3d61a
--- /dev/null
+++ b/tests/ui/duplicate_enum_discriminants.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        V1 = 10,
+        V2 = 10,
+    }
+
+    enum B {
+        V1 = 10,
+        V2,
+        V3 = 11,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
new file mode 100644
index 0000000..f5a879f
--- /dev/null
+++ b/tests/ui/duplicate_enum_discriminants.stderr
@@ -0,0 +1,18 @@
+error: discriminant value `10` already exists
+ --> $DIR/duplicate_enum_discriminants.rs:3:5
+  |
+3 | /     enum A {
+4 | |         V1 = 10,
+5 | |         V2 = 10,
+6 | |     }
+  | |_____^
+
+error: discriminant value `11` already exists
+  --> $DIR/duplicate_enum_discriminants.rs:8:5
+   |
+8  | /     enum B {
+9  | |         V1 = 10,
+10 | |         V2,
+11 | |         V3 = 11,
+12 | |     }
+   | |_____^
diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs
new file mode 100644
index 0000000..a9ad533
--- /dev/null
+++ b/tests/ui/empty_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
new file mode 100644
index 0000000..c73578a
--- /dev/null
+++ b/tests/ui/empty_enum.stderr
@@ -0,0 +1,7 @@
+error: enums without any variants are not supported
+ --> $DIR/empty_enum.rs:3:5
+  |
+3 | /     enum A {
+4 | |
+5 | |     }
+  | |_____^
diff --git a/tests/ui/enum_match_without_wildcard.rs b/tests/ui/enum_match_without_wildcard.rs
new file mode 100644
index 0000000..1a11942
--- /dev/null
+++ b/tests/ui/enum_match_without_wildcard.rs
@@ -0,0 +1,16 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        FieldA,
+        FieldB,
+    }
+}
+
+fn main() {}
+
+fn matcher(a: ffi::A) -> u32 {
+    match a {
+        ffi::A::FieldA => 2020,
+        ffi::A::FieldB => 2021,
+    }
+}
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
new file mode 100644
index 0000000..11d132d
--- /dev/null
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -0,0 +1,10 @@
+error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
+  --> $DIR/enum_match_without_wildcard.rs:12:11
+   |
+1  | #[cxx::bridge]
+   | -------------- `ffi::A` defined here
+...
+12 |     match a {
+   |           ^ pattern `A(2u32..=std::u32::MAX)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
diff --git a/tests/ui/generic_enum.rs b/tests/ui/generic_enum.rs
new file mode 100644
index 0000000..808856e
--- /dev/null
+++ b/tests/ui/generic_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A<T> {
+        Field,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/generic_enum.stderr b/tests/ui/generic_enum.stderr
new file mode 100644
index 0000000..bf267f7
--- /dev/null
+++ b/tests/ui/generic_enum.stderr
@@ -0,0 +1,5 @@
+error: enums with generic parameters are not allowed
+ --> $DIR/generic_enum.rs:3:5
+  |
+3 |     enum A<T> {
+  |     ^^^^^^^^^
diff --git a/tests/ui/non_integer_discriminant_enum.rs b/tests/ui/non_integer_discriminant_enum.rs
new file mode 100644
index 0000000..388b463
--- /dev/null
+++ b/tests/ui/non_integer_discriminant_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        Field = 2020 + 1,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/non_integer_discriminant_enum.stderr b/tests/ui/non_integer_discriminant_enum.stderr
new file mode 100644
index 0000000..7f70f25
--- /dev/null
+++ b/tests/ui/non_integer_discriminant_enum.stderr
@@ -0,0 +1,5 @@
+error: enums with non-integer literal discriminants are not supported
+ --> $DIR/non_integer_discriminant_enum.rs:4:9
+  |
+4 |         Field = 2020 + 1,
+  |         ^^^^^^^^^^^^^^^^

From 2b12b3211355d11a2e1b3089bb1c1e25b71347a7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:03:25 +0000
Subject: [PATCH 498/2232] Update PR 170 compiletests at nightly rustc


---

diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 11d132d..12b8429 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -8,3 +8,4 @@ error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
    |           ^ pattern `A(2u32..=std::u32::MAX)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `ffi::A`

From 02d58bb5932f50258e83515037fd27563e167285 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:49:50 +0000
Subject: [PATCH 499/2232] Merge pull request #170 from jgalenson/enums


Support C-style enums
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8869849..eb72ba4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,7 @@ use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -64,6 +64,10 @@ pub(super) fn gen(
                 out.next_section();
                 write_struct(out, strct);
             }
+            Api::Enum(enm) => {
+                out.next_section();
+                write_enum(out, enm);
+            }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
                     out.next_section();
@@ -353,6 +357,22 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     writeln!(out, "}};");
 }
 
+fn write_enum(out: &mut OutFile, enm: &Enum) {
+    for line in enm.doc.to_string().lines() {
+        writeln!(out, "//{}", line);
+    }
+    writeln!(out, "enum class {} : uint32_t {{", enm.ident);
+    for variant in &enm.variants {
+        write!(out, "  ");
+        write!(out, "{}", variant.ident);
+        if let Some(discriminant) = &variant.discriminant {
+            write!(out, " = {}", discriminant);
+        }
+        writeln!(out, ",");
+    }
+    writeln!(out, "}};");
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 15a091b..788a156 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, ExternFn, ExternType, Signature, Struct, Type, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -36,6 +36,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         match api {
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => expanded.extend(expand_cxx_type(ety)),
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(namespace, efn, types));
@@ -123,6 +124,34 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     }
 }
 
+fn expand_enum(enm: &Enum) -> TokenStream {
+    let ident = &enm.ident;
+    let doc = &enm.doc;
+    let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
+        // This span on the pub makes "private type in public interface" errors
+        // appear in the right place.
+        let vis = Token![pub](variant.ident.span());
+        let variant_ident = &variant.ident;
+        let discriminant = match variant.discriminant {
+            None => *next_discriminant,
+            Some(val) => val,
+        };
+        *next_discriminant = discriminant + 1;
+        Some(quote!(  #vis const #variant_ident: Self = #ident(#discriminant)))
+    });
+    quote! {
+        #doc
+        #[derive(Copy, Clone, PartialEq, Eq)]
+        #[repr(transparent)]
+        pub struct #ident(u32);
+
+        #[allow(non_upper_case_globals)]
+        impl #ident {
+            #(#variants;)*
+        }
+    }
+}
+
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     let doc = &ety.doc;
diff --git a/syntax/check.rs b/syntax/check.rs
index 3e121b5..321fb1a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,9 +1,11 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::{
-    error, ident, Api, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type, Types,
+    error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
+    Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
+use std::collections::HashSet;
 use std::fmt::Display;
 use syn::{Error, Result};
 
@@ -41,6 +43,7 @@ fn do_typecheck(cx: &mut Check) {
     for api in cx.apis {
         match api {
             Api::Struct(strct) => check_api_struct(cx, strct),
+            Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
@@ -68,6 +71,7 @@ impl Check<'_> {
 fn check_type_ident(cx: &mut Check, ident: &Ident) {
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
+        && !cx.types.enums.contains_key(ident)
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
@@ -188,6 +192,28 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
     }
 }
 
+fn check_api_enum(cx: &mut Check, enm: &Enum) {
+    check_reserved_name(cx, &enm.ident);
+
+    if enm.variants.is_empty() {
+        let span = span_for_enum_error(enm);
+        cx.error(span, "enums without any variants are not supported");
+    }
+
+    let mut discriminants = HashSet::new();
+    enm.variants.iter().fold(0, |next_discriminant, variant| {
+        let discriminant = match variant.discriminant {
+            None => next_discriminant,
+            Some(val) => val,
+        };
+        if !discriminants.insert(discriminant) {
+            let msg = format!("discriminant value `{}` already exists", discriminant);
+            cx.error(span_for_enum_error(enm), msg);
+        }
+        discriminant + 1
+    });
+}
+
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
     check_reserved_name(cx, &ty.ident);
 }
@@ -320,6 +346,13 @@ fn span_for_struct_error(strct: &Struct) -> TokenStream {
     quote!(#struct_token #brace_token)
 }
 
+fn span_for_enum_error(enm: &Enum) -> TokenStream {
+    let enum_token = enm.enum_token;
+    let mut brace_token = Group::new(Delimiter::Brace, TokenStream::new());
+    brace_token.set_span(enm.brace_token.span);
+    quote!(#enum_token #brace_token)
+}
+
 fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
     let ampersand = receiver.ampersand;
     let lifetime = &receiver.lifetime;
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 84be4cb..d5bb33f 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -23,6 +23,12 @@ pub(crate) fn check_all(apis: &[Api], errors: &mut Vec<Error>) {
                     errors.extend(check(&field.ident).err());
                 }
             }
+            Api::Enum(enm) => {
+                errors.extend(check(&enm.ident).err());
+                for variant in &enm.variants {
+                    errors.extend(check(&variant.ident).err());
+                }
+            }
             Api::CxxType(ety) | Api::RustType(ety) => {
                 errors.extend(check(&ety.ident).err());
             }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index a4b0ac4..9b1a7e5 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -29,6 +29,7 @@ pub use self::types::Types;
 pub enum Api {
     Include(LitStr),
     Struct(Struct),
+    Enum(Enum),
     CxxType(ExternType),
     CxxFunction(ExternFn),
     RustType(ExternType),
@@ -50,6 +51,14 @@ pub struct Struct {
     pub fields: Vec<Var>,
 }
 
+pub struct Enum {
+    pub doc: Doc,
+    pub enum_token: Token![enum],
+    pub ident: Ident,
+    pub brace_token: Brace,
+    pub variants: Vec<Variant>,
+}
+
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
@@ -83,6 +92,11 @@ pub struct Receiver {
     pub shorthand: bool,
 }
 
+pub struct Variant {
+    pub ident: Ident,
+    pub discriminant: Option<u32>,
+}
+
 pub enum Type {
     Ident(Ident),
     RustBox(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a425c56..995b21f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,14 +1,15 @@
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, Struct,
-    Ty1, Type, Var,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Var, Variant,
 };
 use quote::{format_ident, quote};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Ident,
-    Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token,
-    Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat, PathArguments,
+    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    Variant as RustVariant,
 };
 
 pub mod kw {
@@ -23,6 +24,10 @@ pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
                 let strct = parse_struct(item)?;
                 apis.push(strct);
             }
+            Item::Enum(item) => {
+                let enm = parse_enum(item)?;
+                apis.push(enm);
+            }
             Item::ForeignMod(foreign_mod) => {
                 let functions = parse_foreign_mod(foreign_mod)?;
                 apis.extend(functions);
@@ -78,6 +83,75 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     }))
 }
 
+fn parse_enum(item: ItemEnum) -> Result<Api> {
+    let generics = &item.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        let enum_token = item.enum_token;
+        let ident = &item.ident;
+        let where_clause = &generics.where_clause;
+        let span = quote!(#enum_token #ident #generics #where_clause);
+        return Err(Error::new_spanned(
+            span,
+            "enums with generic parameters are not allowed",
+        ));
+    }
+
+    let mut doc = Doc::new();
+    attrs::parse(&item.attrs, &mut doc, None)?;
+
+    for variant in &item.variants {
+        match &variant.fields {
+            Fields::Unit => {}
+            _ => {
+                return Err(Error::new_spanned(
+                    variant,
+                    "enums with data are not allowed",
+                ))
+            }
+        }
+    }
+
+    Ok(Api::Enum(Enum {
+        doc,
+        enum_token: item.enum_token,
+        ident: item.ident,
+        brace_token: item.brace_token,
+        variants: item
+            .variants
+            .into_iter()
+            .map(parse_variant)
+            .collect::<Result<_>>()?,
+    }))
+}
+
+fn parse_variant(variant: RustVariant) -> Result<Variant> {
+    match &variant.discriminant {
+        None => Ok(Variant {
+            ident: variant.ident,
+            discriminant: None,
+        }),
+        Some((
+            _,
+            Expr::Lit(ExprLit {
+                lit: Lit::Int(n), ..
+            }),
+        )) => match n.base10_digits().parse() {
+            Ok(val) => Ok(Variant {
+                ident: variant.ident,
+                discriminant: Some(val),
+            }),
+            Err(_) => Err(Error::new_spanned(
+                variant,
+                "cannot parse enum discriminant as an integer",
+            )),
+        },
+        _ => Err(Error::new_spanned(
+            variant,
+            "enums with non-integer literal discriminants are not supported",
+        )),
+    }
+}
+
 fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let lang = parse_lang(foreign_mod.abi)?;
     let api_type = match lang {
diff --git a/syntax/types.rs b/syntax/types.rs
index f3aaa16..bb5a843 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, ExternType, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type};
 use proc_macro2::Ident;
 use quote::quote;
 use std::collections::BTreeMap as Map;
@@ -9,6 +9,7 @@ use syn::{Error, Result};
 pub struct Types<'a> {
     pub all: Set<'a, Type>,
     pub structs: Map<Ident, &'a Struct>,
+    pub enums: Map<Ident, &'a Enum>,
     pub cxx: Set<'a, Ident>,
     pub rust: Set<'a, Ident>,
 }
@@ -17,6 +18,7 @@ impl<'a> Types<'a> {
     pub fn collect(apis: &'a [Api]) -> Result<Self> {
         let mut all = Set::new();
         let mut structs = Map::new();
+        let mut enums = Map::new();
         let mut cxx = Set::new();
         let mut rust = Set::new();
 
@@ -46,7 +48,11 @@ impl<'a> Types<'a> {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_struct(strct));
                     }
                     structs.insert(strct.ident.clone(), strct);
@@ -54,16 +60,35 @@ impl<'a> Types<'a> {
                         visit(&mut all, &field.ty);
                     }
                 }
+                Api::Enum(enm) => {
+                    let ident = &enm.ident;
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
+                        return Err(duplicate_enum(enm));
+                    }
+                    enums.insert(enm.ident.clone(), enm);
+                }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_type(ety));
                     }
                     cxx.insert(ident);
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.ident;
-                    if structs.contains_key(ident) || cxx.contains(ident) || rust.contains(ident) {
+                    if structs.contains_key(ident)
+                        || enums.contains_key(ident)
+                        || cxx.contains(ident)
+                        || rust.contains(ident)
+                    {
                         return Err(duplicate_type(ety));
                     }
                     rust.insert(ident);
@@ -82,6 +107,7 @@ impl<'a> Types<'a> {
         Ok(Types {
             all,
             structs,
+            enums,
             cxx,
             rust,
         })
@@ -126,6 +152,13 @@ fn duplicate_struct(strct: &Struct) -> Error {
     Error::new_spanned(range, "duplicate type")
 }
 
+fn duplicate_enum(enm: &Enum) -> Error {
+    let enum_token = enm.enum_token;
+    let ident = &enm.ident;
+    let range = quote!(#enum_token #ident);
+    Error::new_spanned(range, "duplicate type")
+}
+
 fn duplicate_type(ety: &ExternType) -> Error {
     let type_token = ety.type_token;
     let ident = &ety.ident;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 01dc404..0162c9b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -13,6 +13,12 @@ pub mod ffi {
         z: usize,
     }
 
+    enum Enum {
+        AVal,
+        BVal = 2020,
+        CVal,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 
@@ -36,6 +42,7 @@ pub mod ffi {
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
+        fn c_return_enum(n: u32) -> Enum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -57,6 +64,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         fn c_take_callback(callback: fn(String) -> usize);
+        fn c_take_enum(e: Enum);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
@@ -92,6 +100,7 @@ pub mod ffi {
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
         fn r_return_sum(_: usize, _: usize) -> usize;
+        fn r_return_enum(n: u32) -> Enum;
 
         fn r_take_primitive(n: usize);
         fn r_take_shared(shared: Shared);
@@ -105,6 +114,7 @@ pub mod ffi {
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_rust_vec(v: Vec<u8>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
+        fn r_take_enum(e: Enum);
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
@@ -198,6 +208,16 @@ fn r_return_sum(n1: usize, n2: usize) -> usize {
     n1 + n2
 }
 
+fn r_return_enum(n: u32) -> ffi::Enum {
+    if n <= 0 {
+        ffi::Enum::AVal
+    } else if n <= 2020 {
+        ffi::Enum::BVal
+    } else {
+        ffi::Enum::CVal
+    }
+}
+
 fn r_take_primitive(n: usize) {
     assert_eq!(n, 2020);
 }
@@ -247,6 +267,10 @@ fn r_take_ref_rust_vec(v: &Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_enum(e: ffi::Enum) {
+    let _ = e;
+}
+
 fn r_try_return_void() -> Result<(), Error> {
     Ok(())
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2b5431f..71c90b0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -106,6 +106,16 @@ size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
 
+Enum c_return_enum(uint32_t n) {
+  if (n <= static_cast<uint32_t>(Enum::AVal)) {
+    return Enum::AVal;
+  } else if (n <= static_cast<uint32_t>(Enum::BVal)) {
+    return Enum::BVal;
+  } else {
+    return Enum::CVal;
+  }
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -238,6 +248,12 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
 
+void c_take_enum(Enum e) {
+  if (e == Enum::AVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
@@ -295,6 +311,9 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(*r_return_unique_ptr_string() == "2020");
   ASSERT(r_return_identity(2020) == 2020);
   ASSERT(r_return_sum(2020, 1) == 2021);
+  ASSERT(r_return_enum(0) == Enum::AVal);
+  ASSERT(r_return_enum(1) == Enum::BVal);
+  ASSERT(r_return_enum(2021) == Enum::CVal);
 
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
@@ -306,6 +325,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
+  r_take_enum(Enum::AVal);
 
   ASSERT(r_try_return_primitive() == 2020);
   try {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index da8ca56..d3b7d38 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -7,6 +7,7 @@ namespace tests {
 
 struct R;
 struct Shared;
+enum class Enum : uint32_t;
 
 class C {
 public:
@@ -40,6 +41,7 @@ rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
+Enum c_return_enum(uint32_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -61,6 +63,7 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
+void c_take_enum(Enum e);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index d6850aa..1156d5d 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -51,6 +51,18 @@ fn test_c_return() {
     );
     assert_eq!(2020, ffi::c_return_identity(2020));
     assert_eq!(2021, ffi::c_return_sum(2020, 1));
+    match ffi::c_return_enum(0) {
+        ffi::Enum::AVal => {}
+        _ => assert!(false),
+    }
+    match ffi::c_return_enum(1) {
+        ffi::Enum::BVal => {}
+        _ => assert!(false),
+    }
+    match ffi::c_return_enum(2021) {
+        ffi::Enum::CVal => {}
+        _ => assert!(false),
+    }
 }
 
 #[test]
@@ -106,6 +118,7 @@ fn test_c_take() {
     ]));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    check!(ffi::c_take_enum(ffi::Enum::AVal));
 }
 
 #[test]
diff --git a/tests/ui/data_enums.rs b/tests/ui/data_enums.rs
new file mode 100644
index 0000000..aa23200
--- /dev/null
+++ b/tests/ui/data_enums.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        Field(u64),
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/data_enums.stderr b/tests/ui/data_enums.stderr
new file mode 100644
index 0000000..118514e
--- /dev/null
+++ b/tests/ui/data_enums.stderr
@@ -0,0 +1,5 @@
+error: enums with data are not allowed
+ --> $DIR/data_enums.rs:4:9
+  |
+4 |         Field(u64),
+  |         ^^^^^^^^^^
diff --git a/tests/ui/duplicate_enum_discriminants.rs b/tests/ui/duplicate_enum_discriminants.rs
new file mode 100644
index 0000000..ec3d61a
--- /dev/null
+++ b/tests/ui/duplicate_enum_discriminants.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        V1 = 10,
+        V2 = 10,
+    }
+
+    enum B {
+        V1 = 10,
+        V2,
+        V3 = 11,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
new file mode 100644
index 0000000..f5a879f
--- /dev/null
+++ b/tests/ui/duplicate_enum_discriminants.stderr
@@ -0,0 +1,18 @@
+error: discriminant value `10` already exists
+ --> $DIR/duplicate_enum_discriminants.rs:3:5
+  |
+3 | /     enum A {
+4 | |         V1 = 10,
+5 | |         V2 = 10,
+6 | |     }
+  | |_____^
+
+error: discriminant value `11` already exists
+  --> $DIR/duplicate_enum_discriminants.rs:8:5
+   |
+8  | /     enum B {
+9  | |         V1 = 10,
+10 | |         V2,
+11 | |         V3 = 11,
+12 | |     }
+   | |_____^
diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs
new file mode 100644
index 0000000..a9ad533
--- /dev/null
+++ b/tests/ui/empty_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
new file mode 100644
index 0000000..c73578a
--- /dev/null
+++ b/tests/ui/empty_enum.stderr
@@ -0,0 +1,7 @@
+error: enums without any variants are not supported
+ --> $DIR/empty_enum.rs:3:5
+  |
+3 | /     enum A {
+4 | |
+5 | |     }
+  | |_____^
diff --git a/tests/ui/enum_match_without_wildcard.rs b/tests/ui/enum_match_without_wildcard.rs
new file mode 100644
index 0000000..1a11942
--- /dev/null
+++ b/tests/ui/enum_match_without_wildcard.rs
@@ -0,0 +1,16 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        FieldA,
+        FieldB,
+    }
+}
+
+fn main() {}
+
+fn matcher(a: ffi::A) -> u32 {
+    match a {
+        ffi::A::FieldA => 2020,
+        ffi::A::FieldB => 2021,
+    }
+}
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
new file mode 100644
index 0000000..12b8429
--- /dev/null
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -0,0 +1,11 @@
+error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
+  --> $DIR/enum_match_without_wildcard.rs:12:11
+   |
+1  | #[cxx::bridge]
+   | -------------- `ffi::A` defined here
+...
+12 |     match a {
+   |           ^ pattern `A(2u32..=std::u32::MAX)` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `ffi::A`
diff --git a/tests/ui/generic_enum.rs b/tests/ui/generic_enum.rs
new file mode 100644
index 0000000..808856e
--- /dev/null
+++ b/tests/ui/generic_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A<T> {
+        Field,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/generic_enum.stderr b/tests/ui/generic_enum.stderr
new file mode 100644
index 0000000..bf267f7
--- /dev/null
+++ b/tests/ui/generic_enum.stderr
@@ -0,0 +1,5 @@
+error: enums with generic parameters are not allowed
+ --> $DIR/generic_enum.rs:3:5
+  |
+3 |     enum A<T> {
+  |     ^^^^^^^^^
diff --git a/tests/ui/non_integer_discriminant_enum.rs b/tests/ui/non_integer_discriminant_enum.rs
new file mode 100644
index 0000000..388b463
--- /dev/null
+++ b/tests/ui/non_integer_discriminant_enum.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    enum A {
+        Field = 2020 + 1,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/non_integer_discriminant_enum.stderr b/tests/ui/non_integer_discriminant_enum.stderr
new file mode 100644
index 0000000..7f70f25
--- /dev/null
+++ b/tests/ui/non_integer_discriminant_enum.stderr
@@ -0,0 +1,5 @@
+error: enums with non-integer literal discriminants are not supported
+ --> $DIR/non_integer_discriminant_enum.rs:4:9
+  |
+4 |         Field = 2020 + 1,
+  |         ^^^^^^^^^^^^^^^^

From d7984c2b7f52aa0ded0d991e12b3eaba46bdad86 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:50:10 +0000
Subject: [PATCH 500/2232] Touch up PR 170


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 788a156..472c079 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -128,16 +128,12 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
     let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
-        // This span on the pub makes "private type in public interface" errors
-        // appear in the right place.
-        let vis = Token![pub](variant.ident.span());
         let variant_ident = &variant.ident;
-        let discriminant = match variant.discriminant {
-            None => *next_discriminant,
-            Some(val) => val,
-        };
+        let discriminant = variant.discriminant.unwrap_or(*next_discriminant);
         *next_discriminant = discriminant + 1;
-        Some(quote!(  #vis const #variant_ident: Self = #ident(#discriminant)))
+        Some(quote! {
+            pub const #variant_ident: Self = #ident(#discriminant);
+        })
     });
     quote! {
         #doc
@@ -147,7 +143,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 
         #[allow(non_upper_case_globals)]
         impl #ident {
-            #(#variants;)*
+            #(#variants)*
         }
     }
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 321fb1a..7ddcea3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -202,10 +202,7 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 
     let mut discriminants = HashSet::new();
     enm.variants.iter().fold(0, |next_discriminant, variant| {
-        let discriminant = match variant.discriminant {
-            None => next_discriminant,
-            Some(val) => val,
-        };
+        let discriminant = variant.discriminant.unwrap_or(next_discriminant);
         if !discriminants.insert(discriminant) {
             let msg = format!("discriminant value `{}` already exists", discriminant);
             cx.error(span_for_enum_error(enm), msg);
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 995b21f..a0dddbd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -96,8 +96,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         ));
     }
 
-    let mut doc = Doc::new();
-    attrs::parse(&item.attrs, &mut doc, None)?;
+    let doc = attrs::parse_doc(&item.attrs)?;
 
     for variant in &item.variants {
         match &variant.fields {
@@ -105,7 +104,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
             _ => {
                 return Err(Error::new_spanned(
                     variant,
-                    "enums with data are not allowed",
+                    "enums with data are not supported yet",
                 ))
             }
         }
@@ -135,7 +134,7 @@ fn parse_variant(variant: RustVariant) -> Result<Variant> {
             Expr::Lit(ExprLit {
                 lit: Lit::Int(n), ..
             }),
-        )) => match n.base10_digits().parse() {
+        )) => match n.base10_parse() {
             Ok(val) => Ok(Variant {
                 ident: variant.ident,
                 discriminant: Some(val),
@@ -147,7 +146,7 @@ fn parse_variant(variant: RustVariant) -> Result<Variant> {
         },
         _ => Err(Error::new_spanned(
             variant,
-            "enums with non-integer literal discriminants are not supported",
+            "enums with non-integer literal discriminants are not supported yet",
         )),
     }
 }
diff --git a/tests/ui/data_enums.stderr b/tests/ui/data_enums.stderr
index 118514e..c78bce5 100644
--- a/tests/ui/data_enums.stderr
+++ b/tests/ui/data_enums.stderr
@@ -1,4 +1,4 @@
-error: enums with data are not allowed
+error: enums with data are not supported yet
  --> $DIR/data_enums.rs:4:9
   |
 4 |         Field(u64),
diff --git a/tests/ui/non_integer_discriminant_enum.stderr b/tests/ui/non_integer_discriminant_enum.stderr
index 7f70f25..926fd90 100644
--- a/tests/ui/non_integer_discriminant_enum.stderr
+++ b/tests/ui/non_integer_discriminant_enum.stderr
@@ -1,4 +1,4 @@
-error: enums with non-integer literal discriminants are not supported
+error: enums with non-integer literal discriminants are not supported yet
  --> $DIR/non_integer_discriminant_enum.rs:4:9
   |
 4 |         Field = 2020 + 1,

From 9beba146b77ba2e34656f38a7ed1dcfe698cd598 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:51:50 +0000
Subject: [PATCH 501/2232] Avoid relying on ADL for std::back_inserter


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 71c90b0..b7f8e6d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -237,7 +237,7 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   // requirements for std::iterator_traits.
   // https://en.cppreference.com/w/cpp/iterator/iterator_traits
   std::vector<uint8_t> cxx_v;
-  std::copy(v.begin(), v.end(), back_inserter(cxx_v));
+  std::copy(v.begin(), v.end(), std::back_inserter(cxx_v));
   uint8_t sum = std::accumulate(cxx_v.begin(), cxx_v.end(), 0);
   if (sum == 200) {
     cxx_test_suite_set_correct();

From f5aeea2e4c95200cfcbdcf37a49ea45e02b9a55d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:51:51 +0000
Subject: [PATCH 502/2232] Touch up a variable name in vector test


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b7f8e6d..9751969 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -236,9 +236,9 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
   // requirements for std::iterator_traits.
   // https://en.cppreference.com/w/cpp/iterator/iterator_traits
-  std::vector<uint8_t> cxx_v;
-  std::copy(v.begin(), v.end(), std::back_inserter(cxx_v));
-  uint8_t sum = std::accumulate(cxx_v.begin(), cxx_v.end(), 0);
+  std::vector<uint8_t> stdv;
+  std::copy(v.begin(), v.end(), std::back_inserter(stdv));
+  uint8_t sum = std::accumulate(stdv.begin(), stdv.end(), 0);
   if (sum == 200) {
     cxx_test_suite_set_correct();
   }

From 4037de267a30082b67cb9584718ebbabc83d4c0c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:51:51 +0000
Subject: [PATCH 503/2232] Use a better constant string idiom in test


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9751969..21637d8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -10,7 +10,7 @@ extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept;
 
 namespace tests {
 
-const char *SLICE_DATA = "2020";
+static constexpr char SLICE_DATA[] = "2020";
 
 C::C(size_t n) : n(n) {}
 
@@ -51,7 +51,8 @@ rust::Str c_return_str(const Shared &shared) {
 
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared) {
   (void)shared;
-  return rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA), 5);
+  return rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA),
+                              sizeof(SLICE_DATA));
 }
 
 rust::String c_return_rust_string() { return "2020"; }
@@ -320,8 +321,8 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(
-      rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA), 5));
+  r_take_sliceu8(rust::Slice<uint8_t>(
+      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA)));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));

From 63f92e8283800e532ea3a4dd017aae73bbf31f34 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:55:23 +0000
Subject: [PATCH 504/2232] Preserve Span of namespace segments


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index eb72ba4..8b554d8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -938,7 +938,7 @@ fn to_typename(namespace: &Namespace, ty: &Type) -> String {
         Type::Ident(ident) => {
             let mut path = String::new();
             for name in namespace {
-                path += name;
+                path += &name.to_string();
                 path += "::";
             }
             path += &ident.to_string();
@@ -1018,7 +1018,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
 fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     let mut inner = String::new();
     for name in &out.namespace {
-        inner += name;
+        inner += &name.to_string();
         inner += "::";
     }
     inner += &ident.to_string();
@@ -1077,7 +1077,7 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     let mut inner = String::new();
     for name in &out.namespace {
-        inner += name;
+        inner += &name.to_string();
         inner += "::";
     }
     inner += &ident.to_string();
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index d26bb9e..5230eb6 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -3,7 +3,7 @@ use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
 use syn::parse::{Parse, ParseStream, Result};
-use syn::{Path, Token};
+use syn::{Ident, Path, Token};
 
 mod kw {
     syn::custom_keyword!(namespace);
@@ -11,7 +11,7 @@ mod kw {
 
 #[derive(Clone)]
 pub struct Namespace {
-    segments: Vec<String>,
+    segments: Vec<Ident>,
 }
 
 impl Namespace {
@@ -21,7 +21,7 @@ impl Namespace {
         }
     }
 
-    pub fn iter(&self) -> Iter<String> {
+    pub fn iter(&self) -> Iter<Ident> {
         self.segments.iter()
     }
 }
@@ -35,7 +35,7 @@ impl Parse for Namespace {
             let path = input.call(Path::parse_mod_style)?;
             for segment in path.segments {
                 ident::check(&segment.ident)?;
-                segments.push(segment.ident.to_string());
+                segments.push(segment.ident);
             }
             input.parse::<Option<Token![,]>>()?;
         }
@@ -46,8 +46,7 @@ impl Parse for Namespace {
 impl Display for Namespace {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for segment in self {
-            f.write_str(segment)?;
-            f.write_str("$")?;
+            write!(f, "{}$", segment)?;
         }
         Ok(())
     }
@@ -60,8 +59,8 @@ impl IdentFragment for Namespace {
 }
 
 impl<'a> IntoIterator for &'a Namespace {
-    type Item = &'a String;
-    type IntoIter = Iter<'a, String>;
+    type Item = &'a Ident;
+    type IntoIter = Iter<'a, Ident>;
     fn into_iter(self) -> Self::IntoIter {
         self.iter()
     }

From 9dcb8339f0b9786872da3bd3c891153074a75ffc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:55:23 +0000
Subject: [PATCH 505/2232] Do not abort parser on namespace ident checks


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 928c6ec..be46533 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -43,10 +43,11 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     match (|| -> Result<_> {
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
+        let namespace = bridge.namespace;
         let apis = syntax::parse_items(bridge.module)?;
         let types = Types::collect(&apis)?;
-        check::typecheck(&apis, &types)?;
-        let out = write::gen(bridge.namespace, &apis, &types, opt, header);
+        check::typecheck(&namespace, &apis, &types)?;
+        let out = write::gen(namespace, &apis, &types, opt, header);
         Ok(out)
     })() {
         Ok(out) => out.content(),
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 472c079..2e1873c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -16,7 +16,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     ))?;
     let apis = syntax::parse_items(content.1)?;
     let ref types = Types::collect(&apis)?;
-    check::typecheck(&apis, types)?;
+    check::typecheck(namespace, &apis, types)?;
 
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
diff --git a/syntax/check.rs b/syntax/check.rs
index 7ddcea3..c2ee1d1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,4 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{
     error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
     Types,
@@ -10,14 +11,16 @@ use std::fmt::Display;
 use syn::{Error, Result};
 
 struct Check<'a> {
+    namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
     errors: &'a mut Vec<Error>,
 }
 
-pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
+pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> Result<()> {
     let mut errors = Vec::new();
     let mut cx = Check {
+        namespace,
         apis,
         types,
         errors: &mut errors,
@@ -27,6 +30,10 @@ pub(crate) fn typecheck(apis: &[Api], types: &Types) -> Result<()> {
 }
 
 fn do_typecheck(cx: &mut Check) {
+    for segment in cx.namespace {
+        cx.errors.extend(ident::check(segment).err());
+    }
+
     for ty in cx.types {
         match ty {
             Type::Ident(ident) => check_type_ident(cx, ident),
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 5230eb6..e2dce18 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,4 +1,3 @@
-use crate::syntax::ident;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
@@ -34,7 +33,6 @@ impl Parse for Namespace {
             input.parse::<Token![=]>()?;
             let path = input.call(Path::parse_mod_style)?;
             for segment in path.segments {
-                ident::check(&segment.ident)?;
                 segments.push(segment.ident);
             }
             input.parse::<Option<Token![,]>>()?;

From a83301ce5b751c5dca1b72b8e82f8b4378b2e800 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:55:23 +0000
Subject: [PATCH 506/2232] Update ident checker's error reporting to match type checker's


---

diff --git a/syntax/check.rs b/syntax/check.rs
index c2ee1d1..33ca5bb 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -10,7 +10,7 @@ use std::collections::HashSet;
 use std::fmt::Display;
 use syn::{Error, Result};
 
-struct Check<'a> {
+pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
@@ -31,8 +31,9 @@ pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> R
 
 fn do_typecheck(cx: &mut Check) {
     for segment in cx.namespace {
-        cx.errors.extend(ident::check(segment).err());
+        ident::check(cx, segment);
     }
+    ident::check_all(cx, cx.apis);
 
     for ty in cx.types {
         match ty {
@@ -65,12 +66,10 @@ fn do_typecheck(cx: &mut Check) {
             check_multiple_arg_lifetimes(cx, efn);
         }
     }
-
-    ident::check_all(cx.apis, cx.errors);
 }
 
 impl Check<'_> {
-    fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
+    pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
         self.errors.push(Error::new_spanned(sp, msg));
     }
 }
diff --git a/syntax/ident.rs b/syntax/ident.rs
index d5bb33f..0694e32 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,41 +1,40 @@
+use crate::syntax::check::Check;
 use crate::syntax::{error, Api};
 use proc_macro2::Ident;
-use syn::{Error, Result};
 
-pub(crate) fn check(ident: &Ident) -> Result<()> {
+pub(crate) fn check(cx: &mut Check, ident: &Ident) {
     let s = ident.to_string();
+    if s.starts_with("cxxbridge") {
+        cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
+    }
     if s.contains("__") {
-        Err(Error::new(ident.span(), error::DOUBLE_UNDERSCORE.msg))
-    } else if s.starts_with("cxxbridge") {
-        Err(Error::new(ident.span(), error::CXXBRIDGE_RESERVED.msg))
-    } else {
-        Ok(())
+        cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
     }
 }
 
-pub(crate) fn check_all(apis: &[Api], errors: &mut Vec<Error>) {
+pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
     for api in apis {
         match api {
             Api::Include(_) => {}
             Api::Struct(strct) => {
-                errors.extend(check(&strct.ident).err());
+                check(cx, &strct.ident);
                 for field in &strct.fields {
-                    errors.extend(check(&field.ident).err());
+                    check(cx, &field.ident);
                 }
             }
             Api::Enum(enm) => {
-                errors.extend(check(&enm.ident).err());
+                check(cx, &enm.ident);
                 for variant in &enm.variants {
-                    errors.extend(check(&variant.ident).err());
+                    check(cx, &variant.ident);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                errors.extend(check(&ety.ident).err());
+                check(cx, &ety.ident);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                errors.extend(check(&efn.ident).err());
+                check(cx, &efn.ident);
                 for arg in &efn.args {
-                    errors.extend(check(&arg.ident).err());
+                    check(cx, &arg.ident);
                 }
             }
         }

From 6b6423edfb3a9e09bfdcc370c7760ead17bdf9c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:55:23 +0000
Subject: [PATCH 507/2232] Really check everything in check_all


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 33ca5bb..a99e982 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -30,10 +30,7 @@ pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> R
 }
 
 fn do_typecheck(cx: &mut Check) {
-    for segment in cx.namespace {
-        ident::check(cx, segment);
-    }
-    ident::check_all(cx, cx.apis);
+    ident::check_all(cx, cx.namespace, cx.apis);
 
     for ty in cx.types {
         match ty {
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 0694e32..cec424c 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,8 +1,9 @@
 use crate::syntax::check::Check;
+use crate::syntax::namespace::Namespace;
 use crate::syntax::{error, Api};
 use proc_macro2::Ident;
 
-pub(crate) fn check(cx: &mut Check, ident: &Ident) {
+fn check(cx: &mut Check, ident: &Ident) {
     let s = ident.to_string();
     if s.starts_with("cxxbridge") {
         cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
@@ -12,7 +13,11 @@ pub(crate) fn check(cx: &mut Check, ident: &Ident) {
     }
 }
 
-pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
+pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
+    for segment in namespace {
+        check(cx, segment);
+    }
+
     for api in apis {
         match api {
             Api::Include(_) => {}

From b3fcf7b7246975eebd030a264bb3021ca983c8f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 05:58:31 +0000
Subject: [PATCH 508/2232] Fix warning about get_unchecked returning a C-incompatible reference


    out/tests/ffi/lib.rs.cc:1011:22: warning: 'cxxbridge03$std$vector$tests$Shared$get_unchecked' has C-linkage specified, but returns user-defined type 'const tests::Shared &' which is incompatible with C [-Wreturn-type-c-linkage]
    const tests::Shared &cxxbridge03$std$vector$tests$Shared$get_unchecked(const ::std::vector<tests::Shared> &s, size_t pos) noexcept {
                         ^
    out/tests/ffi/lib.rs.cc:1038:17: warning: 'cxxbridge03$std$vector$tests$C$get_unchecked' has C-linkage specified, but returns user-defined type 'const tests::C &' which is incompatible with C [-Wreturn-type-c-linkage]
    const tests::C &cxxbridge03$std$vector$tests$C$get_unchecked(const ::std::vector<tests::C> &s, size_t pos) noexcept {
                    ^
    2 warnings generated.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8b554d8..e227ce1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1232,10 +1232,10 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} &cxxbridge03$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge03$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
-    writeln!(out, "  return s[pos];");
+    writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
     write_unique_ptr_common(out, vector_ty, types);

From c4ddb4d172e2d048bd13b2840a8af75e90f2e3f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 17:00:17 +0000
Subject: [PATCH 509/2232] Add tests for by-value-not-supported errors


---

diff --git a/syntax/error.rs b/syntax/error.rs
index f52d651..f2cb8d1 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -44,7 +44,7 @@ pub static CXX_STRING_BY_VALUE: Error = Error {
 pub static CXX_TYPE_BY_VALUE: Error = Error {
     msg: "C++ type by value is not supported",
     label: None,
-    note: Some("hint: wrap it in a Box<> or UniquePtr<>"),
+    note: Some("hint: wrap it in a UniquePtr<>"),
 };
 
 pub static DOUBLE_UNDERSCORE: Error = Error {
diff --git a/tests/ui/by_value_not_supported.rs b/tests/ui/by_value_not_supported.rs
new file mode 100644
index 0000000..3ff950a
--- /dev/null
+++ b/tests/ui/by_value_not_supported.rs
@@ -0,0 +1,22 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        c: C,
+        r: R,
+        s: CxxString,
+    }
+
+    extern "C" {
+        type C;
+    }
+
+    extern "Rust" {
+        type R;
+
+        fn f(c: C) -> C;
+        fn g(r: R) -> R;
+        fn h(s: CxxString) -> CxxString;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
new file mode 100644
index 0000000..1ff8dbf
--- /dev/null
+++ b/tests/ui/by_value_not_supported.stderr
@@ -0,0 +1,53 @@
+error: using C++ type by value is not supported
+ --> $DIR/by_value_not_supported.rs:4:9
+  |
+4 |         c: C,
+  |         ^^^^
+
+error: using opaque Rust type by value is not supported
+ --> $DIR/by_value_not_supported.rs:5:9
+  |
+5 |         r: R,
+  |         ^^^^
+
+error: using C++ string by value is not supported
+ --> $DIR/by_value_not_supported.rs:6:9
+  |
+6 |         s: CxxString,
+  |         ^^^^^^^^^^^^
+
+error: passing C++ type by value is not supported
+  --> $DIR/by_value_not_supported.rs:16:14
+   |
+16 |         fn f(c: C) -> C;
+   |              ^^^^
+
+error: returning C++ type by value is not supported
+  --> $DIR/by_value_not_supported.rs:16:23
+   |
+16 |         fn f(c: C) -> C;
+   |                       ^
+
+error: passing opaque Rust type by value is not supported
+  --> $DIR/by_value_not_supported.rs:17:14
+   |
+17 |         fn g(r: R) -> R;
+   |              ^^^^
+
+error: returning opaque Rust type by value is not supported
+  --> $DIR/by_value_not_supported.rs:17:23
+   |
+17 |         fn g(r: R) -> R;
+   |                       ^
+
+error: passing C++ string by value is not supported
+  --> $DIR/by_value_not_supported.rs:18:14
+   |
+18 |         fn h(s: CxxString) -> CxxString;
+   |              ^^^^^^^^^^^^
+
+error: returning C++ string by value is not supported
+  --> $DIR/by_value_not_supported.rs:18:31
+   |
+18 |         fn h(s: CxxString) -> CxxString;
+   |                               ^^^^^^^^^

From 04fa0967e2014980c4ae017e5d6cad69fc2934f6 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 01 2020 17:00:31 +0000
Subject: [PATCH 510/2232] Properly handle enum discriminant overflows.


This both checks for enum values that are illegal due to overflow and
ensures we do not overflow on valid enums.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2e1873c..a3c8d1a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -127,14 +127,19 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
-    let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
-        let variant_ident = &variant.ident;
-        let discriminant = variant.discriminant.unwrap_or(*next_discriminant);
-        *next_discriminant = discriminant + 1;
-        Some(quote! {
-            pub const #variant_ident: Self = #ident(#discriminant);
-        })
-    });
+    let variants = enm
+        .variants
+        .iter()
+        .scan(None, |prev_discriminant, variant| {
+            let variant_ident = &variant.ident;
+            let discriminant = variant
+                .discriminant
+                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+            *prev_discriminant = Some(discriminant);
+            Some(quote! {
+                pub const #variant_ident: Self = #ident(#discriminant);
+            })
+        });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
diff --git a/syntax/check.rs b/syntax/check.rs
index a99e982..06bf65b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -204,14 +204,23 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
     }
 
     let mut discriminants = HashSet::new();
-    enm.variants.iter().fold(0, |next_discriminant, variant| {
-        let discriminant = variant.discriminant.unwrap_or(next_discriminant);
-        if !discriminants.insert(discriminant) {
-            let msg = format!("discriminant value `{}` already exists", discriminant);
-            cx.error(span_for_enum_error(enm), msg);
-        }
-        discriminant + 1
-    });
+    enm.variants
+        .iter()
+        .fold(None, |prev_discriminant, variant| {
+            if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+                let msg = format!("overflowed on value after {}", prev_discriminant.unwrap());
+                cx.error(span_for_enum_error(enm), msg);
+                return None;
+            }
+            let discriminant = variant
+                .discriminant
+                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+            if !discriminants.insert(discriminant) {
+                let msg = format!("discriminant value `{}` already exists", discriminant);
+                cx.error(span_for_enum_error(enm), msg);
+            }
+            Some(discriminant)
+        });
 }
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
diff --git a/tests/ui/enum_overflows.rs b/tests/ui/enum_overflows.rs
new file mode 100644
index 0000000..3f351f0
--- /dev/null
+++ b/tests/ui/enum_overflows.rs
@@ -0,0 +1,17 @@
+#[cxx::bridge]
+mod ffi {
+    enum Good1 {
+        A = 0xffffffff,
+    }
+    enum Good2 {
+        B = 0xffffffff,
+        C = 2020,
+    }
+    enum Bad {
+        D = 0xfffffffe,
+        E,
+        F,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
new file mode 100644
index 0000000..3d1b370
--- /dev/null
+++ b/tests/ui/enum_overflows.stderr
@@ -0,0 +1,9 @@
+error: overflowed on value after 4294967295
+  --> $DIR/enum_overflows.rs:10:5
+   |
+10 | /     enum Bad {
+11 | |         D = 0xfffffffe,
+12 | |         E,
+13 | |         F,
+14 | |     }
+   | |_____^

From 57d81a12fb3e792be0fd1251868ce9676102b1aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 17:13:24 +0000
Subject: [PATCH 511/2232] Merge pull request #180 from jgalenson/enums


Properly handle enum discriminant overflows.
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2e1873c..a3c8d1a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -127,14 +127,19 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
-    let variants = enm.variants.iter().scan(0, |next_discriminant, variant| {
-        let variant_ident = &variant.ident;
-        let discriminant = variant.discriminant.unwrap_or(*next_discriminant);
-        *next_discriminant = discriminant + 1;
-        Some(quote! {
-            pub const #variant_ident: Self = #ident(#discriminant);
-        })
-    });
+    let variants = enm
+        .variants
+        .iter()
+        .scan(None, |prev_discriminant, variant| {
+            let variant_ident = &variant.ident;
+            let discriminant = variant
+                .discriminant
+                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+            *prev_discriminant = Some(discriminant);
+            Some(quote! {
+                pub const #variant_ident: Self = #ident(#discriminant);
+            })
+        });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
diff --git a/syntax/check.rs b/syntax/check.rs
index a99e982..06bf65b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -204,14 +204,23 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
     }
 
     let mut discriminants = HashSet::new();
-    enm.variants.iter().fold(0, |next_discriminant, variant| {
-        let discriminant = variant.discriminant.unwrap_or(next_discriminant);
-        if !discriminants.insert(discriminant) {
-            let msg = format!("discriminant value `{}` already exists", discriminant);
-            cx.error(span_for_enum_error(enm), msg);
-        }
-        discriminant + 1
-    });
+    enm.variants
+        .iter()
+        .fold(None, |prev_discriminant, variant| {
+            if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+                let msg = format!("overflowed on value after {}", prev_discriminant.unwrap());
+                cx.error(span_for_enum_error(enm), msg);
+                return None;
+            }
+            let discriminant = variant
+                .discriminant
+                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+            if !discriminants.insert(discriminant) {
+                let msg = format!("discriminant value `{}` already exists", discriminant);
+                cx.error(span_for_enum_error(enm), msg);
+            }
+            Some(discriminant)
+        });
 }
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
diff --git a/tests/ui/enum_overflows.rs b/tests/ui/enum_overflows.rs
new file mode 100644
index 0000000..3f351f0
--- /dev/null
+++ b/tests/ui/enum_overflows.rs
@@ -0,0 +1,17 @@
+#[cxx::bridge]
+mod ffi {
+    enum Good1 {
+        A = 0xffffffff,
+    }
+    enum Good2 {
+        B = 0xffffffff,
+        C = 2020,
+    }
+    enum Bad {
+        D = 0xfffffffe,
+        E,
+        F,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
new file mode 100644
index 0000000..3d1b370
--- /dev/null
+++ b/tests/ui/enum_overflows.stderr
@@ -0,0 +1,9 @@
+error: overflowed on value after 4294967295
+  --> $DIR/enum_overflows.rs:10:5
+   |
+10 | /     enum Bad {
+11 | |         D = 0xfffffffe,
+12 | |         E,
+13 | |         F,
+14 | |     }
+   | |_____^

From 8adb223f3e05971c621e92b853841ba699aca419 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 17:14:27 +0000
Subject: [PATCH 512/2232] Restore support for rustc 1.42


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 06bf65b..0ea53df 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -8,6 +8,7 @@ use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::collections::HashSet;
 use std::fmt::Display;
+use std::u32;
 use syn::{Error, Result};
 
 pub(crate) struct Check<'a> {

From 1ba09e1422394e1869f26fad34e93c31ab899782 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 17:14:41 +0000
Subject: [PATCH 513/2232] Sort errors reported by line number


---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 2e8ecc4..b91c166 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -57,6 +57,7 @@ impl From<syn::Error> for Error {
 pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
     match error {
         Error::Syn(syn_error) => {
+            let syn_error = sort_syn_errors(syn_error);
             let writer = StandardStream::stderr(ColorChoice::Auto);
             let ref mut stderr = writer.lock();
             for error in syn_error {
@@ -69,6 +70,15 @@ pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
     process::exit(1);
 }
 
+fn sort_syn_errors(error: syn::Error) -> Vec<syn::Error> {
+    let mut errors: Vec<_> = error.into_iter().collect();
+    errors.sort_by_key(|e| {
+        let start = e.span().start();
+        (start.line, start.column)
+    });
+    errors
+}
+
 fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
     let span = error.span();
     let start = span.start();

From e720e852c1733cca64e0abcae36bd56d5bc92799 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 17:35:45 +0000
Subject: [PATCH 514/2232] Merge pull request #181 from dtolnay/sort


Sort errors reported by line number
---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 2e8ecc4..b91c166 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -57,6 +57,7 @@ impl From<syn::Error> for Error {
 pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
     match error {
         Error::Syn(syn_error) => {
+            let syn_error = sort_syn_errors(syn_error);
             let writer = StandardStream::stderr(ColorChoice::Auto);
             let ref mut stderr = writer.lock();
             for error in syn_error {
@@ -69,6 +70,15 @@ pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
     process::exit(1);
 }
 
+fn sort_syn_errors(error: syn::Error) -> Vec<syn::Error> {
+    let mut errors: Vec<_> = error.into_iter().collect();
+    errors.sort_by_key(|e| {
+        let start = e.span().start();
+        (start.line, start.column)
+    });
+    errors
+}
+
 fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, error: syn::Error) {
     let span = error.span();
     let start = span.start();

From db1ec312835f0aa8929660622360db2b322d0614 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 01 2020 21:00:48 +0000
Subject: [PATCH 515/2232] Expose the enum value to Rust as a field


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index a3c8d1a..19cde4f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -137,14 +137,16 @@ fn expand_enum(enm: &Enum) -> TokenStream {
                 .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
             *prev_discriminant = Some(discriminant);
             Some(quote! {
-                pub const #variant_ident: Self = #ident(#discriminant);
+                pub const #variant_ident: Self = #ident { repr: #discriminant };
             })
         });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
         #[repr(transparent)]
-        pub struct #ident(u32);
+        pub struct #ident {
+            pub repr: u32,
+        }
 
         #[allow(non_upper_case_globals)]
         impl #ident {
diff --git a/tests/test.rs b/tests/test.rs
index 1156d5d..b8593c5 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -52,15 +52,15 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_identity(2020));
     assert_eq!(2021, ffi::c_return_sum(2020, 1));
     match ffi::c_return_enum(0) {
-        ffi::Enum::AVal => {}
+        enm @ ffi::Enum::AVal => assert_eq!(0, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_enum(1) {
-        ffi::Enum::BVal => {}
+        enm @ ffi::Enum::BVal => assert_eq!(2020, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_enum(2021) {
-        ffi::Enum::CVal => {}
+        enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
 }
@@ -160,6 +160,13 @@ fn test_c_method_calls() {
     assert_eq!(old_value, unique_ptr.get2())
 }
 
+#[test]
+fn test_enum_representations() {
+    assert_eq!(0, ffi::Enum::AVal.repr);
+    assert_eq!(2020, ffi::Enum::BVal.repr);
+    assert_eq!(2021, ffi::Enum::CVal.repr);
+}
+
 #[no_mangle]
 extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
     Box::into_raw(Box::new(2020usize))
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 12b8429..93a8957 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2u32..=std::u32::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A(2u32..=std::u32::MAX)` not covered
+   |           ^ pattern `A { repr: 2u32..=std::u32::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`

From 18cd7572131a0bf86d23eeca40ad436b7c6f35ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 21:26:15 +0000
Subject: [PATCH 516/2232] Merge pull request #182 from jgalenson/enums


Expose the enum value to Rust as a field
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index a3c8d1a..19cde4f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -137,14 +137,16 @@ fn expand_enum(enm: &Enum) -> TokenStream {
                 .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
             *prev_discriminant = Some(discriminant);
             Some(quote! {
-                pub const #variant_ident: Self = #ident(#discriminant);
+                pub const #variant_ident: Self = #ident { repr: #discriminant };
             })
         });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
         #[repr(transparent)]
-        pub struct #ident(u32);
+        pub struct #ident {
+            pub repr: u32,
+        }
 
         #[allow(non_upper_case_globals)]
         impl #ident {
diff --git a/tests/test.rs b/tests/test.rs
index 1156d5d..b8593c5 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -52,15 +52,15 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_identity(2020));
     assert_eq!(2021, ffi::c_return_sum(2020, 1));
     match ffi::c_return_enum(0) {
-        ffi::Enum::AVal => {}
+        enm @ ffi::Enum::AVal => assert_eq!(0, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_enum(1) {
-        ffi::Enum::BVal => {}
+        enm @ ffi::Enum::BVal => assert_eq!(2020, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_enum(2021) {
-        ffi::Enum::CVal => {}
+        enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
 }
@@ -160,6 +160,13 @@ fn test_c_method_calls() {
     assert_eq!(old_value, unique_ptr.get2())
 }
 
+#[test]
+fn test_enum_representations() {
+    assert_eq!(0, ffi::Enum::AVal.repr);
+    assert_eq!(2020, ffi::Enum::BVal.repr);
+    assert_eq!(2021, ffi::Enum::CVal.repr);
+}
+
 #[no_mangle]
 extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
     Box::into_raw(Box::new(2020usize))
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 12b8429..93a8957 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A(2u32..=std::u32::MAX)` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2u32..=std::u32::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A(2u32..=std::u32::MAX)` not covered
+   |           ^ pattern `A { repr: 2u32..=std::u32::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`

From 761a5fc7fdafc7cc8d52c7f68f843b3facc00478 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 23:02:02 +0000
Subject: [PATCH 517/2232] Support building C++ code generator with panic=abort


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 869f543..548dc85 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -14,7 +14,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 9927d3f..20fa12e 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0", features = ["full"] }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index be46533..58a78b1 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -41,6 +41,7 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Err(err) => format_err(path, "", Error::Io(err)),
     };
     match (|| -> Result<_> {
+        proc_macro2::fallback::force();
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
         let namespace = bridge.namespace;
diff --git a/third-party/BUCK b/third-party/BUCK
index 3500cb0..bf772cf 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -99,7 +99,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.3/src/**"]),
+    srcs = glob(["vendor/quote-1.0.4/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
diff --git a/third-party/BUILD b/third-party/BUILD
index b6605e4..140fec8 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -104,7 +104,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.3/src/**"]),
+    srcs = glob(["vendor/quote-1.0.4/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f4e5903..b79fae2 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -211,18 +211,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
+checksum = "9dd1c38e7b0b6b61bcfbdc08c801f3c3066e884bd8e6764bdd2e5971da1d7c4d"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
+checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
 dependencies = [
  "proc-macro2",
 ]

From 7bdd9b51db743ca487f0dbd8681cd5a3b15d69f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 01 2020 23:16:23 +0000
Subject: [PATCH 518/2232] Merge pull request #184 from dtolnay/fallback


Support building C++ code generator with panic=abort
---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 869f543..548dc85 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -14,7 +14,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 9927d3f..20fa12e 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0", features = ["full"] }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index be46533..58a78b1 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -41,6 +41,7 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Err(err) => format_err(path, "", Error::Io(err)),
     };
     match (|| -> Result<_> {
+        proc_macro2::fallback::force();
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
         let namespace = bridge.namespace;
diff --git a/third-party/BUCK b/third-party/BUCK
index 3500cb0..bf772cf 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -99,7 +99,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.3/src/**"]),
+    srcs = glob(["vendor/quote-1.0.4/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
diff --git a/third-party/BUILD b/third-party/BUILD
index b6605e4..140fec8 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.10/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -104,7 +104,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.3/src/**"]),
+    srcs = glob(["vendor/quote-1.0.4/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f4e5903..b79fae2 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -211,18 +211,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
+checksum = "9dd1c38e7b0b6b61bcfbdc08c801f3c3066e884bd8e6764bdd2e5971da1d7c4d"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
+checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
 dependencies = [
  "proc-macro2",
 ]

From b3f66461cd849f8a0451d42ef25614691e4871d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 02 2020 00:29:12 +0000
Subject: [PATCH 519/2232] Update past yanked version of proc-macro2


1.0.11 was yanked.

---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 548dc85..f120099 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -14,7 +14,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0", features = ["full"] }
 
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 20fa12e..99bff36 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ travis-ci = { repository = "dtolnay/cxx" }
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.11", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0", features = ["full"] }
diff --git a/third-party/BUCK b/third-party/BUCK
index bf772cf..2de784b 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.12/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
diff --git a/third-party/BUILD b/third-party/BUILD
index 140fec8..4d8fd9f 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.11/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.12/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b79fae2..3397192 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -211,9 +211,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.11"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dd1c38e7b0b6b61bcfbdc08c801f3c3066e884bd8e6764bdd2e5971da1d7c4d"
+checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
 dependencies = [
  "unicode-xid",
 ]

From 0d366c754bbca757a229186dff511796425f5617 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 02 2020 03:51:38 +0000
Subject: [PATCH 520/2232] Remove CI badge from Cargo.toml


Support for badges has been deprecated by crates.io.

---

diff --git a/Cargo.toml b/Cargo.toml
index f5e5b9f..1455e55 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,6 @@ documentation = "https://docs.rs/cxx"
 readme = "README.md"
 exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
 [dependencies]
 cxxbridge-macro = { version = "=0.3.0", path = "macro" }
 link-cplusplus = "1.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index f120099..1cbcced 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -7,9 +7,6 @@ license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
 
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
 [dependencies]
 anyhow = "1.0"
 cc = "1.0.49"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 99bff36..57f2e39 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -11,9 +11,6 @@ repository = "https://github.com/dtolnay/cxx"
 name = "cxxbridge"
 path = "src/main.rs"
 
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 51fba71..4c2d423 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -11,9 +11,6 @@ exclude = ["README.md"]
 [lib]
 proc-macro = true
 
-[badges]
-travis-ci = { repository = "dtolnay/cxx" }
-
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0"

From 193ce8171ad946650b3c488d5d8b2cd25a965314 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 03 2020 04:20:14 +0000
Subject: [PATCH 521/2232] Enable GitHub Actions


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..06cedb4
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,87 @@
+name: test
+
+on:
+  push:
+  pull_request:
+  schedule: [cron: "40 1 * * *"]
+
+jobs:
+  test:
+    name: ${{matrix.name || format('Rust {0}', matrix.rust)}}
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - rust: 1.43.0
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+    steps:
+      - name: Enable symlinks (windows)
+        if: matrix.os == 'windows'
+        run: git config --global core.symlinks true
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo test
+
+  msrv:
+    name: Rust 1.42.0
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@1.42.0
+      - run: cargo run --manifest-path demo-rs/Cargo.toml
+
+  buck:
+    name: Buck
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@stable
+      - uses: actions/setup-java@v1
+        with:
+          java-version: 8
+          java-package: jre
+      - name: Install Buck
+        run: |
+          mkdir bin
+          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/v2019.10.17.01/buck-v2019.10.17.01.pex
+          chmod +x bin/buck
+          echo ::add-path::bin
+      - name: Vendor dependencies
+        run: |
+          cp third-party/Cargo.lock .
+          cargo vendor --versioned-dirs --locked third-party/vendor
+      - run: buck build :cxx#check --verbose=0
+      - run: buck run demo-rs --verbose=0
+      - run: buck test ... --verbose=0
+
+  bazel:
+    name: Bazel
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Bazel
+        run: |
+          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+          chmod +x install.sh
+          ./install.sh --user
+      - name: Vendor dependencies
+        run: |
+          cp third-party/Cargo.lock .
+          cargo vendor --versioned-dirs --locked third-party/vendor
+      - run: bazel run demo-rs --verbose_failures --noshow_progress
+      - run: bazel test ... --verbose_failures --noshow_progress

From 2c61f66ecd5a314db6716f9e32db576df6b2ae8e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 03 2020 04:34:42 +0000
Subject: [PATCH 522/2232] Merge pull request #185 from dtolnay/actions


Enable GitHub Actions
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..06cedb4
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,87 @@
+name: test
+
+on:
+  push:
+  pull_request:
+  schedule: [cron: "40 1 * * *"]
+
+jobs:
+  test:
+    name: ${{matrix.name || format('Rust {0}', matrix.rust)}}
+    runs-on: ${{matrix.os || 'ubuntu'}}-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - rust: nightly
+          - rust: beta
+          - rust: stable
+          - rust: 1.43.0
+          - name: macOS
+            rust: nightly
+            os: macos
+          - name: Windows (gnu)
+            rust: nightly-x86_64-pc-windows-gnu
+            os: windows
+          - name: Windows (msvc)
+            rust: nightly-x86_64-pc-windows-msvc
+            os: windows
+    steps:
+      - name: Enable symlinks (windows)
+        if: matrix.os == 'windows'
+        run: git config --global core.symlinks true
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: ${{matrix.rust}}
+      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo test
+
+  msrv:
+    name: Rust 1.42.0
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@1.42.0
+      - run: cargo run --manifest-path demo-rs/Cargo.toml
+
+  buck:
+    name: Buck
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@stable
+      - uses: actions/setup-java@v1
+        with:
+          java-version: 8
+          java-package: jre
+      - name: Install Buck
+        run: |
+          mkdir bin
+          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/v2019.10.17.01/buck-v2019.10.17.01.pex
+          chmod +x bin/buck
+          echo ::add-path::bin
+      - name: Vendor dependencies
+        run: |
+          cp third-party/Cargo.lock .
+          cargo vendor --versioned-dirs --locked third-party/vendor
+      - run: buck build :cxx#check --verbose=0
+      - run: buck run demo-rs --verbose=0
+      - run: buck test ... --verbose=0
+
+  bazel:
+    name: Bazel
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install Bazel
+        run: |
+          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+          chmod +x install.sh
+          ./install.sh --user
+      - name: Vendor dependencies
+        run: |
+          cp third-party/Cargo.lock .
+          cargo vendor --versioned-dirs --locked third-party/vendor
+      - run: bazel run demo-rs --verbose_failures --noshow_progress
+      - run: bazel test ... --verbose_failures --noshow_progress

From 96a826b8f09f4064642aaca2d125a9d2e4554267 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:17:12 +0000
Subject: [PATCH 523/2232] Check function signature restrictions in a more appropriate place


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0ea53df..5d442ce 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -55,15 +55,6 @@ fn do_typecheck(cx: &mut Check) {
             _ => {}
         }
     }
-
-    for api in cx.apis {
-        if let Api::CxxFunction(efn) = api {
-            check_mut_return_restriction(cx, efn);
-        }
-        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            check_multiple_arg_lifetimes(cx, efn);
-        }
-    }
 }
 
 impl Check<'_> {
@@ -282,6 +273,12 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(ty, "returning a function pointer is not implemented yet");
         }
     }
+
+    if efn.lang == Lang::Cxx {
+        check_mut_return_restriction(cx, efn);
+    }
+
+    check_multiple_arg_lifetimes(cx, efn);
 }
 
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {

From ab91445c1dcc617219f130e60da480ea4f015ba2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:31:28 +0000
Subject: [PATCH 524/2232] Check type name duplication more compactly


---

diff --git a/syntax/set.rs b/syntax/set.rs
index ca816cf..688d1c0 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -18,10 +18,12 @@ where
         }
     }
 
-    pub fn insert(&mut self, value: &'a T) {
-        if self.set.insert(value) {
+    pub fn insert(&mut self, value: &'a T) -> bool {
+        let new = self.set.insert(value);
+        if new {
             self.vec.push(value);
         }
+        new
     }
 
     pub fn contains(&self, value: &T) -> bool {
diff --git a/syntax/types.rs b/syntax/types.rs
index bb5a843..11db1b7 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,7 @@ use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type};
 use proc_macro2::Ident;
 use quote::quote;
-use std::collections::BTreeMap as Map;
+use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
 use syn::{Error, Result};
 
 pub struct Types<'a> {
@@ -43,16 +43,12 @@ impl<'a> Types<'a> {
             }
         }
 
+        let mut type_names = UnorderedSet::new();
         for api in apis {
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
-                    let ident = &strct.ident;
-                    if structs.contains_key(ident)
-                        || enums.contains_key(ident)
-                        || cxx.contains(ident)
-                        || rust.contains(ident)
-                    {
+                    if !type_names.insert(&strct.ident) {
                         return Err(duplicate_struct(strct));
                     }
                     structs.insert(strct.ident.clone(), strct);
@@ -61,37 +57,22 @@ impl<'a> Types<'a> {
                     }
                 }
                 Api::Enum(enm) => {
-                    let ident = &enm.ident;
-                    if structs.contains_key(ident)
-                        || enums.contains_key(ident)
-                        || cxx.contains(ident)
-                        || rust.contains(ident)
-                    {
+                    if !type_names.insert(&enm.ident) {
                         return Err(duplicate_enum(enm));
                     }
                     enums.insert(enm.ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
-                    let ident = &ety.ident;
-                    if structs.contains_key(ident)
-                        || enums.contains_key(ident)
-                        || cxx.contains(ident)
-                        || rust.contains(ident)
-                    {
+                    if !type_names.insert(&ety.ident) {
                         return Err(duplicate_type(ety));
                     }
-                    cxx.insert(ident);
+                    cxx.insert(&ety.ident);
                 }
                 Api::RustType(ety) => {
-                    let ident = &ety.ident;
-                    if structs.contains_key(ident)
-                        || enums.contains_key(ident)
-                        || cxx.contains(ident)
-                        || rust.contains(ident)
-                    {
+                    if !type_names.insert(&ety.ident) {
                         return Err(duplicate_type(ety));
                     }
-                    rust.insert(ident);
+                    rust.insert(&ety.ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     for arg in &efn.args {

From d932041745a3cd9fd314c4bc266ba1cae2532bcf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:31:56 +0000
Subject: [PATCH 525/2232] Catch function name collisions


---

diff --git a/syntax/types.rs b/syntax/types.rs
index 11db1b7..e09b5cf 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type};
 use proc_macro2::Ident;
 use quote::quote;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -44,6 +44,7 @@ impl<'a> Types<'a> {
         }
 
         let mut type_names = UnorderedSet::new();
+        let mut function_names = UnorderedSet::new();
         for api in apis {
             match api {
                 Api::Include(_) => {}
@@ -75,6 +76,9 @@ impl<'a> Types<'a> {
                     rust.insert(&ety.ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    if !function_names.insert((&efn.receiver, &efn.ident)) {
+                        return Err(duplicate_function(efn));
+                    }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);
                     }
@@ -146,3 +150,7 @@ fn duplicate_type(ety: &ExternType) -> Error {
     let range = quote!(#type_token #ident);
     Error::new_spanned(range, "duplicate type")
 }
+
+fn duplicate_function(efn: &ExternFn) -> Error {
+    Error::new_spanned(efn, "duplicate function")
+}

From 83496ebf335d1df433b5047902478af7ae89411d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:36:53 +0000
Subject: [PATCH 526/2232] Move error reporting span computation to tokens.rs


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 13cbfcf..934c85b 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,5 +1,7 @@
 use crate::syntax::atom::Atom::*;
-use crate::syntax::{Derive, ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type, Var};
+use crate::syntax::{
+    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type, Var,
+};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::Token;
@@ -76,6 +78,30 @@ impl ToTokens for Derive {
     }
 }
 
+impl ToTokens for ExternType {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        // Notional token range for error reporting purposes.
+        self.type_token.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}
+
+impl ToTokens for Struct {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        // Notional token range for error reporting purposes.
+        self.struct_token.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}
+
+impl ToTokens for Enum {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        // Notional token range for error reporting purposes.
+        self.enum_token.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
diff --git a/syntax/types.rs b/syntax/types.rs
index e09b5cf..f0ef3a8 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -2,7 +2,6 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type};
 use proc_macro2::Ident;
-use quote::quote;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
 use syn::{Error, Result};
 
@@ -131,24 +130,15 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
 }
 
 fn duplicate_struct(strct: &Struct) -> Error {
-    let struct_token = strct.struct_token;
-    let ident = &strct.ident;
-    let range = quote!(#struct_token #ident);
-    Error::new_spanned(range, "duplicate type")
+    Error::new_spanned(strct, "duplicate type")
 }
 
 fn duplicate_enum(enm: &Enum) -> Error {
-    let enum_token = enm.enum_token;
-    let ident = &enm.ident;
-    let range = quote!(#enum_token #ident);
-    Error::new_spanned(range, "duplicate type")
+    Error::new_spanned(enm, "duplicate type")
 }
 
 fn duplicate_type(ety: &ExternType) -> Error {
-    let type_token = ety.type_token;
-    let ident = &ety.ident;
-    let range = quote!(#type_token #ident);
-    Error::new_spanned(range, "duplicate type")
+    Error::new_spanned(ety, "duplicate type")
 }
 
 fn duplicate_function(efn: &ExternFn) -> Error {

From 7bc2edd7340d72de67af83729f23c3245e9654cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:41:53 +0000
Subject: [PATCH 527/2232] Include conflicting name in duplicate name error message


---

diff --git a/syntax/types.rs b/syntax/types.rs
index f0ef3a8..4842507 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, Struct, Type};
 use proc_macro2::Ident;
+use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
 use syn::{Error, Result};
 
@@ -48,35 +49,40 @@ impl<'a> Types<'a> {
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
-                    if !type_names.insert(&strct.ident) {
-                        return Err(duplicate_struct(strct));
+                    let ident = &strct.ident;
+                    if !type_names.insert(ident) {
+                        return Err(duplicate_name(strct, ident));
                     }
-                    structs.insert(strct.ident.clone(), strct);
+                    structs.insert(ident.clone(), strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
                 }
                 Api::Enum(enm) => {
-                    if !type_names.insert(&enm.ident) {
-                        return Err(duplicate_enum(enm));
+                    let ident = &enm.ident;
+                    if !type_names.insert(ident) {
+                        return Err(duplicate_name(enm, ident));
                     }
-                    enums.insert(enm.ident.clone(), enm);
+                    enums.insert(ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
-                    if !type_names.insert(&ety.ident) {
-                        return Err(duplicate_type(ety));
+                    let ident = &ety.ident;
+                    if !type_names.insert(ident) {
+                        return Err(duplicate_name(ety, ident));
                     }
-                    cxx.insert(&ety.ident);
+                    cxx.insert(ident);
                 }
                 Api::RustType(ety) => {
-                    if !type_names.insert(&ety.ident) {
-                        return Err(duplicate_type(ety));
+                    let ident = &ety.ident;
+                    if !type_names.insert(ident) {
+                        return Err(duplicate_name(ety, ident));
                     }
-                    rust.insert(&ety.ident);
+                    rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    if !function_names.insert((&efn.receiver, &efn.ident)) {
-                        return Err(duplicate_function(efn));
+                    let ident = &efn.ident;
+                    if !function_names.insert((&efn.receiver, ident)) {
+                        return Err(duplicate_name(efn, ident));
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);
@@ -129,18 +135,7 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
-fn duplicate_struct(strct: &Struct) -> Error {
-    Error::new_spanned(strct, "duplicate type")
-}
-
-fn duplicate_enum(enm: &Enum) -> Error {
-    Error::new_spanned(enm, "duplicate type")
-}
-
-fn duplicate_type(ety: &ExternType) -> Error {
-    Error::new_spanned(ety, "duplicate type")
-}
-
-fn duplicate_function(efn: &ExternFn) -> Error {
-    Error::new_spanned(efn, "duplicate function")
+fn duplicate_name(sp: impl ToTokens, ident: &Ident) -> Error {
+    let msg = format!("the name `{}` is defined multiple times", ident);
+    Error::new_spanned(sp, msg)
 }

From 2ec14632c091bcb459b83b953f465a96c5030ff9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 07:53:12 +0000
Subject: [PATCH 528/2232] Be consistent about certain variable names always meaning a reference


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 58a78b1..c7b3c3c 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -44,11 +44,11 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         proc_macro2::fallback::force();
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
-        let namespace = bridge.namespace;
-        let apis = syntax::parse_items(bridge.module)?;
-        let types = Types::collect(&apis)?;
-        check::typecheck(&namespace, &apis, &types)?;
-        let out = write::gen(namespace, &apis, &types, opt, header);
+        let ref namespace = bridge.namespace;
+        let ref apis = syntax::parse_items(bridge.module)?;
+        let ref types = Types::collect(apis)?;
+        check::typecheck(namespace, apis, types)?;
+        let out = write::gen(namespace, apis, types, opt, header);
         Ok(out)
     })() {
         Ok(out) => out.content(),
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e227ce1..8ce3813 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -8,7 +8,7 @@ use proc_macro2::Ident;
 use std::collections::HashMap;
 
 pub(super) fn gen(
-    namespace: Namespace,
+    namespace: &Namespace,
     apis: &[Api],
     types: &Types,
     opt: Opt,
@@ -32,7 +32,7 @@ pub(super) fn gen(
     write_include_cxxbridge(out, apis, types);
 
     out.next_section();
-    for name in &namespace {
+    for name in namespace {
         writeln!(out, "namespace {} {{", name);
     }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 19cde4f..737c389 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -14,14 +14,14 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         Span::call_site(),
         "#[cxx::bridge] module must have inline contents",
     ))?;
-    let apis = syntax::parse_items(content.1)?;
-    let ref types = Types::collect(&apis)?;
-    check::typecheck(namespace, &apis, types)?;
+    let ref apis = syntax::parse_items(content.1)?;
+    let ref types = Types::collect(apis)?;
+    check::typecheck(namespace, apis, types)?;
 
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
-    for api in &apis {
+    for api in apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
             let ident = &ety.ident;
@@ -32,7 +32,7 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         }
     }
 
-    for api in &apis {
+    for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),

From 15a6c763522593484c5d8847bf884eb53afb4313 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:29:01 +0000
Subject: [PATCH 529/2232] Add test of invocation with multiple parse errors


---

diff --git a/tests/ui/multiple_parse_error.rs b/tests/ui/multiple_parse_error.rs
new file mode 100644
index 0000000..061eab6
--- /dev/null
+++ b/tests/ui/multiple_parse_error.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    struct Monad<T>;
+
+    extern "Haskell" {
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
new file mode 100644
index 0000000..61c4fba
--- /dev/null
+++ b/tests/ui/multiple_parse_error.stderr
@@ -0,0 +1,5 @@
+error: struct with generic parameters is not supported yet
+ --> $DIR/multiple_parse_error.rs:3:5
+  |
+3 |     struct Monad<T>;
+  |     ^^^^^^^^^^^^^^^

From df344a82d91b25ef7fd1461482dc2bc35318294d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:29:16 +0000
Subject: [PATCH 530/2232] Extract error collection to be not specific to check.rs


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 5d442ce..3fb0d06 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::{
     error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
     Types,
@@ -9,17 +10,17 @@ use quote::{quote, ToTokens};
 use std::collections::HashSet;
 use std::fmt::Display;
 use std::u32;
-use syn::{Error, Result};
+use syn::Result;
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
-    errors: &'a mut Vec<Error>,
+    errors: &'a mut Errors,
 }
 
 pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> Result<()> {
-    let mut errors = Vec::new();
+    let mut errors = Errors::new();
     let mut cx = Check {
         namespace,
         apis,
@@ -27,7 +28,7 @@ pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> R
         errors: &mut errors,
     };
     do_typecheck(&mut cx);
-    combine_errors(errors)
+    errors.propagate()
 }
 
 fn do_typecheck(cx: &mut Check) {
@@ -59,7 +60,7 @@ fn do_typecheck(cx: &mut Check) {
 
 impl Check<'_> {
     pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
-        self.errors.push(Error::new_spanned(sp, msg));
+        self.errors.error(sp, msg);
     }
 }
 
@@ -373,18 +374,6 @@ fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
     }
 }
 
-fn combine_errors(errors: Vec<Error>) -> Result<()> {
-    let mut iter = errors.into_iter();
-    let mut all_errors = match iter.next() {
-        Some(err) => err,
-        None => return Ok(()),
-    };
-    for err in iter {
-        all_errors.combine(err);
-    }
-    Err(all_errors)
-}
-
 fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9b1a7e5..e6c5bb8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -10,6 +10,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
+pub mod report;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/report.rs b/syntax/report.rs
new file mode 100644
index 0000000..04f21d8
--- /dev/null
+++ b/syntax/report.rs
@@ -0,0 +1,29 @@
+use quote::ToTokens;
+use std::fmt::Display;
+use syn::{Error, Result};
+
+pub struct Errors {
+    errors: Vec<Error>,
+}
+
+impl Errors {
+    pub fn new() -> Self {
+        Errors { errors: Vec::new() }
+    }
+
+    pub fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
+        self.errors.push(Error::new_spanned(sp, msg));
+    }
+
+    pub fn propagate(&mut self) -> Result<()> {
+        let mut iter = self.errors.drain(..);
+        let mut all_errors = match iter.next() {
+            Some(err) => err,
+            None => return Ok(()),
+        };
+        for err in iter {
+            all_errors.combine(err);
+        }
+        Err(all_errors)
+    }
+}

From 0dd85ff5f734a1f6eaff658640b75a47518fc26b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:29:17 +0000
Subject: [PATCH 531/2232] Move error collection one level out of type checker


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index c7b3c3c..0cfdc59 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -8,6 +8,7 @@ mod write;
 
 use self::error::{format_err, Error, Result};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use quote::quote;
 use std::fs;
@@ -42,12 +43,14 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     };
     match (|| -> Result<_> {
         proc_macro2::fallback::force();
+        let ref mut errors = Errors::new();
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
         let ref namespace = bridge.namespace;
         let ref apis = syntax::parse_items(bridge.module)?;
         let ref types = Types::collect(apis)?;
-        check::typecheck(namespace, apis, types)?;
+        check::typecheck(errors, namespace, apis, types);
+        errors.propagate()?;
         let out = write::gen(namespace, apis, types, opt, header);
         Ok(out)
     })() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 737c389..f5cbbf2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
@@ -9,6 +10,7 @@ use quote::{format_ident, quote, quote_spanned, ToTokens};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
+    let ref mut errors = Errors::new();
     let ident = &ffi.ident;
     let content = ffi.content.ok_or(Error::new(
         Span::call_site(),
@@ -16,7 +18,8 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     ))?;
     let ref apis = syntax::parse_items(content.1)?;
     let ref types = Types::collect(apis)?;
-    check::typecheck(namespace, apis, types)?;
+    check::typecheck(errors, namespace, apis, types);
+    errors.propagate()?;
 
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
diff --git a/syntax/check.rs b/syntax/check.rs
index 3fb0d06..72b4a6c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -10,7 +10,6 @@ use quote::{quote, ToTokens};
 use std::collections::HashSet;
 use std::fmt::Display;
 use std::u32;
-use syn::Result;
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
@@ -19,16 +18,13 @@ pub(crate) struct Check<'a> {
     errors: &'a mut Errors,
 }
 
-pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> Result<()> {
-    let mut errors = Errors::new();
-    let mut cx = Check {
+pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], types: &Types) {
+    do_typecheck(&mut Check {
         namespace,
         apis,
         types,
-        errors: &mut errors,
-    };
-    do_typecheck(&mut cx);
-    errors.propagate()
+        errors: cx,
+    });
 }
 
 fn do_typecheck(cx: &mut Check) {

From cbf3f03ff24ab357ae9beb77cf98809a0b721767 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:29:17 +0000
Subject: [PATCH 532/2232] Demarcate the infallible majority of expand.rs


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f5cbbf2..d1af2cf 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -9,10 +9,9 @@ use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
-pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
+pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
-    let ident = &ffi.ident;
-    let content = ffi.content.ok_or(Error::new(
+    let content = ffi.content.take().ok_or(Error::new(
         Span::call_site(),
         "#[cxx::bridge] module must have inline contents",
     ))?;
@@ -21,6 +20,10 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
 
+    Ok(expand(namespace, ffi, apis, types))
+}
+
+fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
@@ -96,15 +99,16 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         .into_iter()
         .filter(|attr| attr.path.is_ident("doc"));
     let vis = &ffi.vis;
+    let ident = &ffi.ident;
 
-    Ok(quote! {
+    quote! {
         #(#attrs)*
         #[deny(improper_ctypes)]
         #[allow(non_snake_case)]
         #vis mod #ident {
             #expanded
         }
-    })
+    }
 }
 
 fn expand_struct(strct: &Struct) -> TokenStream {

From 5275978d1390846b3b346b0dc0a2d668ffa44e23 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:29:17 +0000
Subject: [PATCH 533/2232] Batch errors from the parser


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 0cfdc59..6663e4b 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -47,8 +47,9 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
         let ref namespace = bridge.namespace;
-        let ref apis = syntax::parse_items(bridge.module)?;
-        let ref types = Types::collect(apis)?;
+        let ref apis = syntax::parse_items(errors, bridge.module);
+        let ref types = Types::collect(errors, apis);
+        errors.propagate()?;
         check::typecheck(errors, namespace, apis, types);
         errors.propagate()?;
         let out = write::gen(namespace, apis, types, opt, header);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d1af2cf..e67902b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -15,8 +15,9 @@ pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
         Span::call_site(),
         "#[cxx::bridge] module must have inline contents",
     ))?;
-    let ref apis = syntax::parse_items(content.1)?;
-    let ref types = Types::collect(apis)?;
+    let ref apis = syntax::parse_items(errors, content.1);
+    let ref types = Types::collect(errors, apis);
+    errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a0dddbd..8bf0a4a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
@@ -16,27 +17,24 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
+pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => {
-                let strct = parse_struct(item)?;
-                apis.push(strct);
-            }
-            Item::Enum(item) => {
-                let enm = parse_enum(item)?;
-                apis.push(enm);
-            }
-            Item::ForeignMod(foreign_mod) => {
-                let functions = parse_foreign_mod(foreign_mod)?;
-                apis.extend(functions);
-            }
-            Item::Use(item) => return Err(Error::new_spanned(item, error::USE_NOT_ALLOWED)),
-            _ => return Err(Error::new_spanned(item, "unsupported item")),
+            Item::Struct(item) => match parse_struct(item) {
+                Ok(strct) => apis.push(strct),
+                Err(err) => cx.push(err),
+            },
+            Item::Enum(item) => match parse_enum(item) {
+                Ok(enm) => apis.push(enm),
+                Err(err) => cx.push(err),
+            },
+            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis),
+            Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
+            _ => cx.error(item, "unsupported item"),
         }
     }
-    Ok(apis)
+    apis
 }
 
 fn parse_struct(item: ItemStruct) -> Result<Api> {
@@ -151,8 +149,11 @@ fn parse_variant(variant: RustVariant) -> Result<Variant> {
     }
 }
 
-fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
-    let lang = parse_lang(foreign_mod.abi)?;
+fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
+    let lang = match parse_lang(foreign_mod.abi) {
+        Ok(lang) => lang,
+        Err(err) => return cx.push(err),
+    };
     let api_type = match lang {
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
@@ -165,19 +166,21 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => {
-                let ety = parse_extern_type(foreign)?;
-                items.push(api_type(ety));
-            }
-            ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang)?;
-                items.push(api_function(efn));
-            }
+            ForeignItem::Type(foreign) => match parse_extern_type(foreign) {
+                Ok(ety) => items.push(api_type(ety)),
+                Err(err) => cx.push(err),
+            },
+            ForeignItem::Fn(foreign) => match parse_extern_fn(foreign, lang) {
+                Ok(efn) => items.push(api_function(efn)),
+                Err(err) => cx.push(err),
+            },
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
-                let include = foreign.mac.parse_body()?;
-                items.push(Api::Include(include));
+                match foreign.mac.parse_body() {
+                    Ok(include) => items.push(Api::Include(include)),
+                    Err(err) => cx.push(err),
+                }
             }
-            _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
+            _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
 
@@ -198,7 +201,7 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         }
     }
 
-    Ok(items)
+    out.extend(items);
 }
 
 fn parse_lang(abi: Abi) -> Result<Lang> {
diff --git a/syntax/report.rs b/syntax/report.rs
index 04f21d8..d1d8bc9 100644
--- a/syntax/report.rs
+++ b/syntax/report.rs
@@ -15,6 +15,10 @@ impl Errors {
         self.errors.push(Error::new_spanned(sp, msg));
     }
 
+    pub fn push(&mut self, error: Error) {
+        self.errors.push(error);
+    }
+
     pub fn propagate(&mut self) -> Result<()> {
         let mut iter = self.errors.drain(..);
         let mut all_errors = match iter.next() {
diff --git a/syntax/types.rs b/syntax/types.rs
index 4842507..02249e2 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,10 +1,10 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{Api, Derive, Enum, Struct, Type};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
-use syn::{Error, Result};
 
 pub struct Types<'a> {
     pub all: Set<'a, Type>,
@@ -15,7 +15,7 @@ pub struct Types<'a> {
 }
 
 impl<'a> Types<'a> {
-    pub fn collect(apis: &'a [Api]) -> Result<Self> {
+    pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
         let mut all = Set::new();
         let mut structs = Map::new();
         let mut enums = Map::new();
@@ -50,39 +50,41 @@ impl<'a> Types<'a> {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
-                    if !type_names.insert(ident) {
-                        return Err(duplicate_name(strct, ident));
+                    if type_names.insert(ident) {
+                        structs.insert(ident.clone(), strct);
+                    } else {
+                        duplicate_name(cx, strct, ident);
                     }
-                    structs.insert(ident.clone(), strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
                 }
                 Api::Enum(enm) => {
                     let ident = &enm.ident;
-                    if !type_names.insert(ident) {
-                        return Err(duplicate_name(enm, ident));
+                    if type_names.insert(ident) {
+                        enums.insert(ident.clone(), enm);
+                    } else {
+                        duplicate_name(cx, enm, ident);
                     }
-                    enums.insert(ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
                     if !type_names.insert(ident) {
-                        return Err(duplicate_name(ety, ident));
+                        duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.ident;
                     if !type_names.insert(ident) {
-                        return Err(duplicate_name(ety, ident));
+                        duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     let ident = &efn.ident;
                     if !function_names.insert((&efn.receiver, ident)) {
-                        return Err(duplicate_name(efn, ident));
+                        duplicate_name(cx, efn, ident);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);
@@ -94,13 +96,13 @@ impl<'a> Types<'a> {
             }
         }
 
-        Ok(Types {
+        Types {
             all,
             structs,
             enums,
             cxx,
             rust,
-        })
+        }
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
@@ -135,7 +137,7 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
-fn duplicate_name(sp: impl ToTokens, ident: &Ident) -> Error {
+fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
-    Error::new_spanned(sp, msg)
+    cx.error(sp, msg);
 }

From 4c14162d34d5c708eaff03ea403bbf3f04ad23e4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:30:09 +0000
Subject: [PATCH 534/2232] Update multi parse errors ui test


---

diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 61c4fba..854aa90 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -3,3 +3,9 @@ error: struct with generic parameters is not supported yet
   |
 3 |     struct Monad<T>;
   |     ^^^^^^^^^^^^^^^
+
+error: unrecognized ABI
+ --> $DIR/multiple_parse_error.rs:5:5
+  |
+5 |     extern "Haskell" {
+  |     ^^^^^^^^^^^^^^^^

From 29bc17710310e97152e1a6ee8562aa6c667adb94 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 08:40:45 +0000
Subject: [PATCH 535/2232] Merge pull request #186 from dtolnay/batch


Batch parse errors
---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index c7b3c3c..6663e4b 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -8,6 +8,7 @@ mod write;
 
 use self::error::{format_err, Error, Result};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use quote::quote;
 use std::fs;
@@ -42,12 +43,15 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     };
     match (|| -> Result<_> {
         proc_macro2::fallback::force();
+        let ref mut errors = Errors::new();
         let syntax = syn::parse_file(&source)?;
         let bridge = find_bridge_mod(syntax)?;
         let ref namespace = bridge.namespace;
-        let ref apis = syntax::parse_items(bridge.module)?;
-        let ref types = Types::collect(apis)?;
-        check::typecheck(namespace, apis, types)?;
+        let ref apis = syntax::parse_items(errors, bridge.module);
+        let ref types = Types::collect(errors, apis);
+        errors.propagate()?;
+        check::typecheck(errors, namespace, apis, types);
+        errors.propagate()?;
         let out = write::gen(namespace, apis, types, opt, header);
         Ok(out)
     })() {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 737c389..e67902b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
@@ -8,16 +9,22 @@ use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
-pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
-    let ident = &ffi.ident;
-    let content = ffi.content.ok_or(Error::new(
+pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
+    let ref mut errors = Errors::new();
+    let content = ffi.content.take().ok_or(Error::new(
         Span::call_site(),
         "#[cxx::bridge] module must have inline contents",
     ))?;
-    let ref apis = syntax::parse_items(content.1)?;
-    let ref types = Types::collect(apis)?;
-    check::typecheck(namespace, apis, types)?;
+    let ref apis = syntax::parse_items(errors, content.1);
+    let ref types = Types::collect(errors, apis);
+    errors.propagate()?;
+    check::typecheck(errors, namespace, apis, types);
+    errors.propagate()?;
+
+    Ok(expand(namespace, ffi, apis, types))
+}
 
+fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
@@ -93,15 +100,16 @@ pub fn bridge(namespace: &Namespace, ffi: ItemMod) -> Result<TokenStream> {
         .into_iter()
         .filter(|attr| attr.path.is_ident("doc"));
     let vis = &ffi.vis;
+    let ident = &ffi.ident;
 
-    Ok(quote! {
+    quote! {
         #(#attrs)*
         #[deny(improper_ctypes)]
         #[allow(non_snake_case)]
         #vis mod #ident {
             #expanded
         }
-    })
+    }
 }
 
 fn expand_struct(strct: &Struct) -> TokenStream {
diff --git a/syntax/check.rs b/syntax/check.rs
index 5d442ce..72b4a6c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
+use crate::syntax::report::Errors;
 use crate::syntax::{
     error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
     Types,
@@ -9,25 +10,21 @@ use quote::{quote, ToTokens};
 use std::collections::HashSet;
 use std::fmt::Display;
 use std::u32;
-use syn::{Error, Result};
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
-    errors: &'a mut Vec<Error>,
+    errors: &'a mut Errors,
 }
 
-pub(crate) fn typecheck(namespace: &Namespace, apis: &[Api], types: &Types) -> Result<()> {
-    let mut errors = Vec::new();
-    let mut cx = Check {
+pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], types: &Types) {
+    do_typecheck(&mut Check {
         namespace,
         apis,
         types,
-        errors: &mut errors,
-    };
-    do_typecheck(&mut cx);
-    combine_errors(errors)
+        errors: cx,
+    });
 }
 
 fn do_typecheck(cx: &mut Check) {
@@ -59,7 +56,7 @@ fn do_typecheck(cx: &mut Check) {
 
 impl Check<'_> {
     pub(crate) fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
-        self.errors.push(Error::new_spanned(sp, msg));
+        self.errors.error(sp, msg);
     }
 }
 
@@ -373,18 +370,6 @@ fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
     }
 }
 
-fn combine_errors(errors: Vec<Error>) -> Result<()> {
-    let mut iter = errors.into_iter();
-    let mut all_errors = match iter.next() {
-        Some(err) => err,
-        None => return Ok(()),
-    };
-    for err in iter {
-        all_errors.combine(err);
-    }
-    Err(all_errors)
-}
-
 fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9b1a7e5..e6c5bb8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -10,6 +10,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
+pub mod report;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a0dddbd..8bf0a4a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
@@ -16,27 +17,24 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(items: Vec<Item>) -> Result<Vec<Api>> {
+pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => {
-                let strct = parse_struct(item)?;
-                apis.push(strct);
-            }
-            Item::Enum(item) => {
-                let enm = parse_enum(item)?;
-                apis.push(enm);
-            }
-            Item::ForeignMod(foreign_mod) => {
-                let functions = parse_foreign_mod(foreign_mod)?;
-                apis.extend(functions);
-            }
-            Item::Use(item) => return Err(Error::new_spanned(item, error::USE_NOT_ALLOWED)),
-            _ => return Err(Error::new_spanned(item, "unsupported item")),
+            Item::Struct(item) => match parse_struct(item) {
+                Ok(strct) => apis.push(strct),
+                Err(err) => cx.push(err),
+            },
+            Item::Enum(item) => match parse_enum(item) {
+                Ok(enm) => apis.push(enm),
+                Err(err) => cx.push(err),
+            },
+            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis),
+            Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
+            _ => cx.error(item, "unsupported item"),
         }
     }
-    Ok(apis)
+    apis
 }
 
 fn parse_struct(item: ItemStruct) -> Result<Api> {
@@ -151,8 +149,11 @@ fn parse_variant(variant: RustVariant) -> Result<Variant> {
     }
 }
 
-fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
-    let lang = parse_lang(foreign_mod.abi)?;
+fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
+    let lang = match parse_lang(foreign_mod.abi) {
+        Ok(lang) => lang,
+        Err(err) => return cx.push(err),
+    };
     let api_type = match lang {
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
@@ -165,19 +166,21 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => {
-                let ety = parse_extern_type(foreign)?;
-                items.push(api_type(ety));
-            }
-            ForeignItem::Fn(foreign) => {
-                let efn = parse_extern_fn(foreign, lang)?;
-                items.push(api_function(efn));
-            }
+            ForeignItem::Type(foreign) => match parse_extern_type(foreign) {
+                Ok(ety) => items.push(api_type(ety)),
+                Err(err) => cx.push(err),
+            },
+            ForeignItem::Fn(foreign) => match parse_extern_fn(foreign, lang) {
+                Ok(efn) => items.push(api_function(efn)),
+                Err(err) => cx.push(err),
+            },
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
-                let include = foreign.mac.parse_body()?;
-                items.push(Api::Include(include));
+                match foreign.mac.parse_body() {
+                    Ok(include) => items.push(Api::Include(include)),
+                    Err(err) => cx.push(err),
+                }
             }
-            _ => return Err(Error::new_spanned(foreign, "unsupported foreign item")),
+            _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
 
@@ -198,7 +201,7 @@ fn parse_foreign_mod(foreign_mod: ItemForeignMod) -> Result<Vec<Api>> {
         }
     }
 
-    Ok(items)
+    out.extend(items);
 }
 
 fn parse_lang(abi: Abi) -> Result<Lang> {
diff --git a/syntax/report.rs b/syntax/report.rs
new file mode 100644
index 0000000..d1d8bc9
--- /dev/null
+++ b/syntax/report.rs
@@ -0,0 +1,33 @@
+use quote::ToTokens;
+use std::fmt::Display;
+use syn::{Error, Result};
+
+pub struct Errors {
+    errors: Vec<Error>,
+}
+
+impl Errors {
+    pub fn new() -> Self {
+        Errors { errors: Vec::new() }
+    }
+
+    pub fn error(&mut self, sp: impl ToTokens, msg: impl Display) {
+        self.errors.push(Error::new_spanned(sp, msg));
+    }
+
+    pub fn push(&mut self, error: Error) {
+        self.errors.push(error);
+    }
+
+    pub fn propagate(&mut self) -> Result<()> {
+        let mut iter = self.errors.drain(..);
+        let mut all_errors = match iter.next() {
+            Some(err) => err,
+            None => return Ok(()),
+        };
+        for err in iter {
+            all_errors.combine(err);
+        }
+        Err(all_errors)
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 4842507..02249e2 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,10 +1,10 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{Api, Derive, Enum, Struct, Type};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
-use syn::{Error, Result};
 
 pub struct Types<'a> {
     pub all: Set<'a, Type>,
@@ -15,7 +15,7 @@ pub struct Types<'a> {
 }
 
 impl<'a> Types<'a> {
-    pub fn collect(apis: &'a [Api]) -> Result<Self> {
+    pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
         let mut all = Set::new();
         let mut structs = Map::new();
         let mut enums = Map::new();
@@ -50,39 +50,41 @@ impl<'a> Types<'a> {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
-                    if !type_names.insert(ident) {
-                        return Err(duplicate_name(strct, ident));
+                    if type_names.insert(ident) {
+                        structs.insert(ident.clone(), strct);
+                    } else {
+                        duplicate_name(cx, strct, ident);
                     }
-                    structs.insert(ident.clone(), strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
                 }
                 Api::Enum(enm) => {
                     let ident = &enm.ident;
-                    if !type_names.insert(ident) {
-                        return Err(duplicate_name(enm, ident));
+                    if type_names.insert(ident) {
+                        enums.insert(ident.clone(), enm);
+                    } else {
+                        duplicate_name(cx, enm, ident);
                     }
-                    enums.insert(ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
                     if !type_names.insert(ident) {
-                        return Err(duplicate_name(ety, ident));
+                        duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.ident;
                     if !type_names.insert(ident) {
-                        return Err(duplicate_name(ety, ident));
+                        duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     let ident = &efn.ident;
                     if !function_names.insert((&efn.receiver, ident)) {
-                        return Err(duplicate_name(efn, ident));
+                        duplicate_name(cx, efn, ident);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);
@@ -94,13 +96,13 @@ impl<'a> Types<'a> {
             }
         }
 
-        Ok(Types {
+        Types {
             all,
             structs,
             enums,
             cxx,
             rust,
-        })
+        }
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
@@ -135,7 +137,7 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
-fn duplicate_name(sp: impl ToTokens, ident: &Ident) -> Error {
+fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
-    Error::new_spanned(sp, msg)
+    cx.error(sp, msg);
 }
diff --git a/tests/ui/multiple_parse_error.rs b/tests/ui/multiple_parse_error.rs
new file mode 100644
index 0000000..061eab6
--- /dev/null
+++ b/tests/ui/multiple_parse_error.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    struct Monad<T>;
+
+    extern "Haskell" {
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
new file mode 100644
index 0000000..854aa90
--- /dev/null
+++ b/tests/ui/multiple_parse_error.stderr
@@ -0,0 +1,11 @@
+error: struct with generic parameters is not supported yet
+ --> $DIR/multiple_parse_error.rs:3:5
+  |
+3 |     struct Monad<T>;
+  |     ^^^^^^^^^^^^^^^
+
+error: unrecognized ABI
+ --> $DIR/multiple_parse_error.rs:5:5
+  |
+5 |     extern "Haskell" {
+  |     ^^^^^^^^^^^^^^^^

From 24d22b471abf8949dfed8810a4ba314a5b7041d6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 04 2020 09:31:53 +0000
Subject: [PATCH 536/2232] Remove Travis configuration


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 06cedb4..1040454 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: test
+name: CI
 
 on:
   push:
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index f65f7f8..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-language: rust
-
-rust:
-  - nightly
-  - beta
-  - stable
-
-script:
-  - cargo run --manifest-path demo-rs/Cargo.toml
-  - cargo test
-
-matrix:
-  include:
-    - name: macOS
-      os: macos
-      rust: nightly
-
-    - name: Windows (gnu)
-      os: windows
-      rust: nightly-x86_64-pc-windows-gnu
-      before_script:
-        # windows is bad at symlinks
-        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
-        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
-
-    - name: Windows (msvc)
-      os: windows
-      rust: nightly-x86_64-pc-windows-msvc
-      before_script:
-        - rm gen/build/src/gen gen/build/src/syntax gen/cmd/src/gen gen/cmd/src/syntax gen/src/include macro/src/syntax
-        - cp -r include gen/src; cp -r gen/src gen/build/src/gen; cp -r gen/src gen/cmd/src/gen; cp -r syntax gen/build/src; cp -r syntax gen/cmd/src; cp -r syntax macro/src
-
-    - name: Buck
-      rust: nightly
-      before_install:
-        - sudo apt-get install -y openjdk-8-jdk
-        - export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
-        - wget -O buck.deb https://github.com/facebook/buck/releases/download/v2019.10.17.01/buck.2019.10.17.01_all.deb
-        - sudo dpkg -i buck.deb
-      before_script:
-        - cp third-party/Cargo.lock .
-        - cargo vendor --versioned-dirs --locked third-party/vendor
-      script:
-        - buck build :cxx#check --verbose=0
-        - buck run demo-rs --verbose=0
-        - buck test ... --verbose=0
-
-    - name: Bazel
-      rust: nightly
-      before_install:
-        - wget -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
-        - chmod +x install.sh
-        - ./install.sh --user
-      before_script:
-        - cp third-party/Cargo.lock .
-        - cargo vendor --versioned-dirs --locked third-party/vendor
-      script:
-        - bazel run demo-rs --verbose_failures --noshow_progress
-        - bazel test ... --verbose_failures --noshow_progress
-
-    - name: Minimum rustc
-      rust: 1.42.0
-      script:
-        - cargo run --manifest-path demo-rs/Cargo.toml

From 905eb2e1f5307f64850503ca1f46101239dabf17 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 04 2020 22:02:17 +0000
Subject: [PATCH 537/2232] Support enums defined in C++ code.


This allows listing an enum in an extern "C" block as well as in the
shared block.  In this case, we do not emit the C++ declaration of the
enum but instead emit static assertions that it has the values that we
expect.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8ce3813..2ea6ca8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 
 pub(super) fn gen(
     namespace: &Namespace,
@@ -46,6 +46,7 @@ pub(super) fn gen(
         }
     }
 
+    let mut cxx_types = HashSet::new();
     let mut methods_for_type = HashMap::new();
     for api in apis {
         if let Api::RustFunction(efn) = api {
@@ -56,6 +57,9 @@ pub(super) fn gen(
                     .push(efn);
             }
         }
+        if let Api::CxxType(enm) = api {
+            cxx_types.insert(&enm.ident);
+        }
     }
 
     for api in apis {
@@ -66,7 +70,11 @@ pub(super) fn gen(
             }
             Api::Enum(enm) => {
                 out.next_section();
-                write_enum(out, enm);
+                if cxx_types.contains(&enm.ident) {
+                    check_enum(out, enm);
+                } else {
+                    write_enum(out, enm);
+                }
             }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
@@ -373,6 +381,34 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     writeln!(out, "}};");
 }
 
+fn check_enum(out: &mut OutFile, enm: &Enum) {
+    let discriminants = enm
+        .variants
+        .iter()
+        .scan(None, |prev_discriminant, variant| {
+            let discriminant = variant
+                .discriminant
+                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+            *prev_discriminant = Some(discriminant);
+            Some(discriminant)
+        });
+    writeln!(
+        out,
+        "static_assert(sizeof({}) == sizeof(uint32_t));",
+        enm.ident
+    );
+    enm.variants
+        .iter()
+        .zip(discriminants)
+        .for_each(|(variant, discriminant)| {
+            writeln!(
+                out,
+                "static_assert({}::{} == {});",
+                enm.ident, variant.ident, discriminant
+            );
+        });
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e67902b..1a23960 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -7,6 +7,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
+use std::collections::HashSet;
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
@@ -39,12 +40,22 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
         }
     }
 
+    let mut enums = HashSet::new();
+    for api in apis {
+        if let Api::Enum(enm) = api {
+            enums.insert(&enm.ident);
+        }
+    }
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
-            Api::CxxType(ety) => expanded.extend(expand_cxx_type(ety)),
+            Api::CxxType(ety) => {
+                if !enums.contains(&ety.ident) {
+                    expanded.extend(expand_cxx_type(ety));
+                }
+            }
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(namespace, efn, types));
             }
diff --git a/syntax/types.rs b/syntax/types.rs
index 02249e2..bfe7bf0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -69,7 +69,9 @@ impl<'a> Types<'a> {
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
-                    if !type_names.insert(ident) {
+                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
+                    // means not to emit the C++ enum definition.
+                    if !type_names.insert(ident) && !enums.contains_key(ident) {
                         duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);

From 0f654ffeb0037fba4aadaa098e163434406a3fd5 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 05 2020 03:04:21 +0000
Subject: [PATCH 538/2232] Fix previous commit.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2ea6ca8..70620ce 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
 
 pub(super) fn gen(
     namespace: &Namespace,
@@ -46,7 +46,6 @@ pub(super) fn gen(
         }
     }
 
-    let mut cxx_types = HashSet::new();
     let mut methods_for_type = HashMap::new();
     for api in apis {
         if let Api::RustFunction(efn) = api {
@@ -57,9 +56,6 @@ pub(super) fn gen(
                     .push(efn);
             }
         }
-        if let Api::CxxType(enm) = api {
-            cxx_types.insert(&enm.ident);
-        }
     }
 
     for api in apis {
@@ -70,7 +66,7 @@ pub(super) fn gen(
             }
             Api::Enum(enm) => {
                 out.next_section();
-                if cxx_types.contains(&enm.ident) {
+                if types.cxx.contains(&enm.ident) {
                     check_enum(out, enm);
                 } else {
                     write_enum(out, enm);
@@ -382,31 +378,24 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {
-    let discriminants = enm
-        .variants
-        .iter()
-        .scan(None, |prev_discriminant, variant| {
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            *prev_discriminant = Some(discriminant);
-            Some(discriminant)
-        });
     writeln!(
         out,
         "static_assert(sizeof({}) == sizeof(uint32_t));",
         enm.ident
     );
-    enm.variants
-        .iter()
-        .zip(discriminants)
-        .for_each(|(variant, discriminant)| {
-            writeln!(
-                out,
-                "static_assert({}::{} == {});",
-                enm.ident, variant.ident, discriminant
-            );
-        });
+    let mut prev_discriminant = None;
+    for variant in &enm.variants {
+        let discriminant = variant
+            .discriminant
+            .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+        writeln!(
+            out,
+            "static_assert(static_cast<uint32_t>({}::{}) == {},
+              \"disagrees with the value in #[cxx::bridge]\");",
+            enm.ident, variant.ident, discriminant,
+        );
+        prev_discriminant = Some(discriminant);
+    }
 }
 
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1a23960..d8810dc 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -7,7 +7,6 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use std::collections::HashSet;
 use syn::{parse_quote, Error, ItemMod, Result, Token};
 
 pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
@@ -40,19 +39,13 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
         }
     }
 
-    let mut enums = HashSet::new();
-    for api in apis {
-        if let Api::Enum(enm) = api {
-            enums.insert(&enm.ident);
-        }
-    }
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
-                if !enums.contains(&ety.ident) {
+                if !types.enums.contains_key(&ety.ident) {
                     expanded.extend(expand_cxx_type(ety));
                 }
             }
diff --git a/syntax/types.rs b/syntax/types.rs
index bfe7bf0..5800513 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -61,11 +61,12 @@ impl<'a> Types<'a> {
                 }
                 Api::Enum(enm) => {
                     let ident = &enm.ident;
-                    if type_names.insert(ident) {
-                        enums.insert(ident.clone(), enm);
-                    } else {
+                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
+                    // means not to emit the C++ enum definition.
+                    if !type_names.insert(ident) && !cxx.contains(ident) {
                         duplicate_name(cx, enm, ident);
                     }
+                    enums.insert(ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0162c9b..16846fb 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -84,6 +84,15 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
     }
 
+    extern "C" {
+        type COwnedEnum;
+    }
+
+    enum COwnedEnum {
+        CVal1,
+        CVal2,
+    }
+
     extern "Rust" {
         type R;
         type R2;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index d3b7d38..795b4a9 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -23,6 +23,11 @@ private:
   std::vector<uint8_t> v;
 };
 
+enum COwnedEnum {
+  CVal1,
+  CVal2,
+};
+
 size_t c_return_primitive();
 Shared c_return_shared();
 rust::Box<R> c_return_box();

From 9fe5ea3ad742ab7d465adb16e4cc52febc939c61 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 05 2020 03:25:15 +0000
Subject: [PATCH 539/2232] Add missing message.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 70620ce..3c059a7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -380,7 +380,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 fn check_enum(out: &mut OutFile, enm: &Enum) {
     writeln!(
         out,
-        "static_assert(sizeof({}) == sizeof(uint32_t));",
+        "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
         enm.ident
     );
     let mut prev_discriminant = None;

From de471c9a2202e40be77ff2b5dda28d5c4882c1fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 03:49:52 +0000
Subject: [PATCH 540/2232] Merge pull request #187 from jgalenson/enums


Support enums defined in C++ code.
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8ce3813..3c059a7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -66,7 +66,11 @@ pub(super) fn gen(
             }
             Api::Enum(enm) => {
                 out.next_section();
-                write_enum(out, enm);
+                if types.cxx.contains(&enm.ident) {
+                    check_enum(out, enm);
+                } else {
+                    write_enum(out, enm);
+                }
             }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
@@ -373,6 +377,27 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     writeln!(out, "}};");
 }
 
+fn check_enum(out: &mut OutFile, enm: &Enum) {
+    writeln!(
+        out,
+        "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
+        enm.ident
+    );
+    let mut prev_discriminant = None;
+    for variant in &enm.variants {
+        let discriminant = variant
+            .discriminant
+            .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+        writeln!(
+            out,
+            "static_assert(static_cast<uint32_t>({}::{}) == {},
+              \"disagrees with the value in #[cxx::bridge]\");",
+            enm.ident, variant.ident, discriminant,
+        );
+        prev_discriminant = Some(discriminant);
+    }
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e67902b..d8810dc 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -44,7 +44,11 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::Include(_) | Api::RustType(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
-            Api::CxxType(ety) => expanded.extend(expand_cxx_type(ety)),
+            Api::CxxType(ety) => {
+                if !types.enums.contains_key(&ety.ident) {
+                    expanded.extend(expand_cxx_type(ety));
+                }
+            }
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(namespace, efn, types));
             }
diff --git a/syntax/types.rs b/syntax/types.rs
index 02249e2..5800513 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -61,15 +61,18 @@ impl<'a> Types<'a> {
                 }
                 Api::Enum(enm) => {
                     let ident = &enm.ident;
-                    if type_names.insert(ident) {
-                        enums.insert(ident.clone(), enm);
-                    } else {
+                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
+                    // means not to emit the C++ enum definition.
+                    if !type_names.insert(ident) && !cxx.contains(ident) {
                         duplicate_name(cx, enm, ident);
                     }
+                    enums.insert(ident.clone(), enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
-                    if !type_names.insert(ident) {
+                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
+                    // means not to emit the C++ enum definition.
+                    if !type_names.insert(ident) && !enums.contains_key(ident) {
                         duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0162c9b..16846fb 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -84,6 +84,15 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
     }
 
+    extern "C" {
+        type COwnedEnum;
+    }
+
+    enum COwnedEnum {
+        CVal1,
+        CVal2,
+    }
+
     extern "Rust" {
         type R;
         type R2;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index d3b7d38..795b4a9 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -23,6 +23,11 @@ private:
   std::vector<uint8_t> v;
 };
 
+enum COwnedEnum {
+  CVal1,
+  CVal2,
+};
+
 size_t c_return_primitive();
 Shared c_return_shared();
 rust::Box<R> c_return_box();

From 8854773c56ebf4f318d7dba3d022626259178ec0 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 05 2020 15:32:32 +0000
Subject: [PATCH 541/2232] Compute enum discriminant during parsing


This allows us to reuse the computation in multiple places later.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3c059a7..4e98674 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -367,12 +367,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     }
     writeln!(out, "enum class {} : uint32_t {{", enm.ident);
     for variant in &enm.variants {
-        write!(out, "  ");
-        write!(out, "{}", variant.ident);
-        if let Some(discriminant) = &variant.discriminant {
-            write!(out, " = {}", discriminant);
-        }
-        writeln!(out, ",");
+        writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
 }
@@ -383,18 +378,13 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
         "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
         enm.ident
     );
-    let mut prev_discriminant = None;
     for variant in &enm.variants {
-        let discriminant = variant
-            .discriminant
-            .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
         writeln!(
             out,
             "static_assert(static_cast<uint32_t>({}::{}) == {},
               \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident, variant.ident, discriminant,
+            enm.ident, variant.ident, variant.discriminant,
         );
-        prev_discriminant = Some(discriminant);
     }
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d8810dc..fcb845c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -139,19 +139,13 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
-    let variants = enm
-        .variants
-        .iter()
-        .scan(None, |prev_discriminant, variant| {
-            let variant_ident = &variant.ident;
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            *prev_discriminant = Some(discriminant);
-            Some(quote! {
-                pub const #variant_ident: Self = #ident { repr: #discriminant };
-            })
-        });
+    let variants = enm.variants.iter().map(|variant| {
+        let variant_ident = &variant.ident;
+        let discriminant = &variant.discriminant;
+        Some(quote! {
+            pub const #variant_ident: Self = #ident { repr: #discriminant };
+        })
+    });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
diff --git a/syntax/check.rs b/syntax/check.rs
index 72b4a6c..c54430c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -7,9 +7,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
-use std::collections::HashSet;
 use std::fmt::Display;
-use std::u32;
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
@@ -191,25 +189,6 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
         let span = span_for_enum_error(enm);
         cx.error(span, "enums without any variants are not supported");
     }
-
-    let mut discriminants = HashSet::new();
-    enm.variants
-        .iter()
-        .fold(None, |prev_discriminant, variant| {
-            if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
-                let msg = format!("overflowed on value after {}", prev_discriminant.unwrap());
-                cx.error(span_for_enum_error(enm), msg);
-                return None;
-            }
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            if !discriminants.insert(discriminant) {
-                let msg = format!("discriminant value `{}` already exists", discriminant);
-                cx.error(span_for_enum_error(enm), msg);
-            }
-            Some(discriminant)
-        });
 }
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e6c5bb8..fd8db73 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -95,7 +95,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub ident: Ident,
-    pub discriminant: Option<u32>,
+    pub discriminant: u32,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8bf0a4a..fc51ee9 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,6 +5,7 @@ use crate::syntax::{
     Struct, Ty1, Type, Var, Variant,
 };
 use quote::{format_ident, quote};
+use std::collections::HashSet;
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -96,16 +97,33 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
 
     let doc = attrs::parse_doc(&item.attrs)?;
 
-    for variant in &item.variants {
-        match &variant.fields {
+    let mut variants = Vec::new();
+    let mut discriminants = HashSet::new();
+    let mut prev_discriminant = None;
+    for variant in item.variants {
+        match variant.fields {
             Fields::Unit => {}
             _ => {
                 return Err(Error::new_spanned(
                     variant,
                     "enums with data are not supported yet",
-                ))
+                ));
             }
         }
+        if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+            return Err(Error::new_spanned(variant, "overflowed on value"));
+        }
+        let discriminant =
+            parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+        if !discriminants.insert(discriminant) {
+            let msg = format!("discriminant value `{}` already exists", discriminant);
+            return Err(Error::new_spanned(variant, msg));
+        }
+        variants.push(Variant {
+            ident: variant.ident,
+            discriminant: discriminant,
+        });
+        prev_discriminant = Some(discriminant);
     }
 
     Ok(Api::Enum(Enum {
@@ -113,30 +131,20 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         enum_token: item.enum_token,
         ident: item.ident,
         brace_token: item.brace_token,
-        variants: item
-            .variants
-            .into_iter()
-            .map(parse_variant)
-            .collect::<Result<_>>()?,
+        variants: variants,
     }))
 }
 
-fn parse_variant(variant: RustVariant) -> Result<Variant> {
+fn parse_discriminant(variant: &RustVariant) -> Result<Option<u32>> {
     match &variant.discriminant {
-        None => Ok(Variant {
-            ident: variant.ident,
-            discriminant: None,
-        }),
+        None => Ok(None),
         Some((
             _,
             Expr::Lit(ExprLit {
                 lit: Lit::Int(n), ..
             }),
         )) => match n.base10_parse() {
-            Ok(val) => Ok(Variant {
-                ident: variant.ident,
-                discriminant: Some(val),
-            }),
+            Ok(val) => Ok(Some(val)),
             Err(_) => Err(Error::new_spanned(
                 variant,
                 "cannot parse enum discriminant as an integer",
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
index f5a879f..14505e3 100644
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ b/tests/ui/duplicate_enum_discriminants.stderr
@@ -1,18 +1,11 @@
 error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:3:5
+ --> $DIR/duplicate_enum_discriminants.rs:5:9
   |
-3 | /     enum A {
-4 | |         V1 = 10,
-5 | |         V2 = 10,
-6 | |     }
-  | |_____^
+5 |         V2 = 10,
+  |         ^^^^^^^
 
 error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:8:5
+  --> $DIR/duplicate_enum_discriminants.rs:11:9
    |
-8  | /     enum B {
-9  | |         V1 = 10,
-10 | |         V2,
-11 | |         V3 = 11,
-12 | |     }
-   | |_____^
+11 |         V3 = 11,
+   |         ^^^^^^^
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index 3d1b370..1a22146 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,9 +1,5 @@
-error: overflowed on value after 4294967295
-  --> $DIR/enum_overflows.rs:10:5
+error: overflowed on value
+  --> $DIR/enum_overflows.rs:13:9
    |
-10 | /     enum Bad {
-11 | |         D = 0xfffffffe,
-12 | |         E,
-13 | |         F,
-14 | |     }
-   | |_____^
+13 |         F,
+   |         ^

From 8ef1bc809c6c0cb9df7750248f04dbbdd9f96765 Mon Sep 17 00:00:00 2001
From: Joel Galenson <jgalenson@google.com>
Date: May 05 2020 15:45:49 +0000
Subject: [PATCH 542/2232] Fix rustc 1.42.0.


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index fc51ee9..880e2c7 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,6 +6,7 @@ use crate::syntax::{
 };
 use quote::{format_ident, quote};
 use std::collections::HashSet;
+use std::u32;
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,

From acc64cb20179b7c1b72394931e2c2db51c614293 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:09:16 +0000
Subject: [PATCH 543/2232] Merge pull request #189 from jgalenson/enums


Compute enum discriminant during parsing
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3c059a7..4e98674 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -367,12 +367,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     }
     writeln!(out, "enum class {} : uint32_t {{", enm.ident);
     for variant in &enm.variants {
-        write!(out, "  ");
-        write!(out, "{}", variant.ident);
-        if let Some(discriminant) = &variant.discriminant {
-            write!(out, " = {}", discriminant);
-        }
-        writeln!(out, ",");
+        writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
 }
@@ -383,18 +378,13 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
         "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
         enm.ident
     );
-    let mut prev_discriminant = None;
     for variant in &enm.variants {
-        let discriminant = variant
-            .discriminant
-            .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
         writeln!(
             out,
             "static_assert(static_cast<uint32_t>({}::{}) == {},
               \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident, variant.ident, discriminant,
+            enm.ident, variant.ident, variant.discriminant,
         );
-        prev_discriminant = Some(discriminant);
     }
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d8810dc..fcb845c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -139,19 +139,13 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
-    let variants = enm
-        .variants
-        .iter()
-        .scan(None, |prev_discriminant, variant| {
-            let variant_ident = &variant.ident;
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            *prev_discriminant = Some(discriminant);
-            Some(quote! {
-                pub const #variant_ident: Self = #ident { repr: #discriminant };
-            })
-        });
+    let variants = enm.variants.iter().map(|variant| {
+        let variant_ident = &variant.ident;
+        let discriminant = &variant.discriminant;
+        Some(quote! {
+            pub const #variant_ident: Self = #ident { repr: #discriminant };
+        })
+    });
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
diff --git a/syntax/check.rs b/syntax/check.rs
index 72b4a6c..c54430c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -7,9 +7,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
-use std::collections::HashSet;
 use std::fmt::Display;
-use std::u32;
 
 pub(crate) struct Check<'a> {
     namespace: &'a Namespace,
@@ -191,25 +189,6 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
         let span = span_for_enum_error(enm);
         cx.error(span, "enums without any variants are not supported");
     }
-
-    let mut discriminants = HashSet::new();
-    enm.variants
-        .iter()
-        .fold(None, |prev_discriminant, variant| {
-            if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
-                let msg = format!("overflowed on value after {}", prev_discriminant.unwrap());
-                cx.error(span_for_enum_error(enm), msg);
-                return None;
-            }
-            let discriminant = variant
-                .discriminant
-                .unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-            if !discriminants.insert(discriminant) {
-                let msg = format!("discriminant value `{}` already exists", discriminant);
-                cx.error(span_for_enum_error(enm), msg);
-            }
-            Some(discriminant)
-        });
 }
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e6c5bb8..fd8db73 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -95,7 +95,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub ident: Ident,
-    pub discriminant: Option<u32>,
+    pub discriminant: u32,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8bf0a4a..880e2c7 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,6 +5,8 @@ use crate::syntax::{
     Struct, Ty1, Type, Var, Variant,
 };
 use quote::{format_ident, quote};
+use std::collections::HashSet;
+use std::u32;
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -96,16 +98,33 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
 
     let doc = attrs::parse_doc(&item.attrs)?;
 
-    for variant in &item.variants {
-        match &variant.fields {
+    let mut variants = Vec::new();
+    let mut discriminants = HashSet::new();
+    let mut prev_discriminant = None;
+    for variant in item.variants {
+        match variant.fields {
             Fields::Unit => {}
             _ => {
                 return Err(Error::new_spanned(
                     variant,
                     "enums with data are not supported yet",
-                ))
+                ));
             }
         }
+        if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+            return Err(Error::new_spanned(variant, "overflowed on value"));
+        }
+        let discriminant =
+            parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
+        if !discriminants.insert(discriminant) {
+            let msg = format!("discriminant value `{}` already exists", discriminant);
+            return Err(Error::new_spanned(variant, msg));
+        }
+        variants.push(Variant {
+            ident: variant.ident,
+            discriminant: discriminant,
+        });
+        prev_discriminant = Some(discriminant);
     }
 
     Ok(Api::Enum(Enum {
@@ -113,30 +132,20 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         enum_token: item.enum_token,
         ident: item.ident,
         brace_token: item.brace_token,
-        variants: item
-            .variants
-            .into_iter()
-            .map(parse_variant)
-            .collect::<Result<_>>()?,
+        variants: variants,
     }))
 }
 
-fn parse_variant(variant: RustVariant) -> Result<Variant> {
+fn parse_discriminant(variant: &RustVariant) -> Result<Option<u32>> {
     match &variant.discriminant {
-        None => Ok(Variant {
-            ident: variant.ident,
-            discriminant: None,
-        }),
+        None => Ok(None),
         Some((
             _,
             Expr::Lit(ExprLit {
                 lit: Lit::Int(n), ..
             }),
         )) => match n.base10_parse() {
-            Ok(val) => Ok(Variant {
-                ident: variant.ident,
-                discriminant: Some(val),
-            }),
+            Ok(val) => Ok(Some(val)),
             Err(_) => Err(Error::new_spanned(
                 variant,
                 "cannot parse enum discriminant as an integer",
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
index f5a879f..14505e3 100644
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ b/tests/ui/duplicate_enum_discriminants.stderr
@@ -1,18 +1,11 @@
 error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:3:5
+ --> $DIR/duplicate_enum_discriminants.rs:5:9
   |
-3 | /     enum A {
-4 | |         V1 = 10,
-5 | |         V2 = 10,
-6 | |     }
-  | |_____^
+5 |         V2 = 10,
+  |         ^^^^^^^
 
 error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:8:5
+  --> $DIR/duplicate_enum_discriminants.rs:11:9
    |
-8  | /     enum B {
-9  | |         V1 = 10,
-10 | |         V2,
-11 | |         V3 = 11,
-12 | |     }
-   | |_____^
+11 |         V3 = 11,
+   |         ^^^^^^^
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index 3d1b370..1a22146 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,9 +1,5 @@
-error: overflowed on value after 4294967295
-  --> $DIR/enum_overflows.rs:10:5
+error: overflowed on value
+  --> $DIR/enum_overflows.rs:13:9
    |
-10 | /     enum Bad {
-11 | |         D = 0xfffffffe,
-12 | |         E,
-13 | |         F,
-14 | |     }
-   | |_____^
+13 |         F,
+   |         ^

From 7ae018fb5a37cd8c8622892bc2900f729976e63e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:11:30 +0000
Subject: [PATCH 544/2232] Resolve redundant_field_names lint


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 880e2c7..1f6cbac 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -122,7 +122,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         }
         variants.push(Variant {
             ident: variant.ident,
-            discriminant: discriminant,
+            discriminant,
         });
         prev_discriminant = Some(discriminant);
     }
@@ -132,7 +132,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         enum_token: item.enum_token,
         ident: item.ident,
         brace_token: item.brace_token,
-        variants: variants,
+        variants,
     }))
 }
 

From 39ee0ed36bb7646642967a09806ce3cbeb53f013 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:12:29 +0000
Subject: [PATCH 545/2232] Resolve assign_op_pattern lint


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 0d952f9..bfb4a4e 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -88,8 +88,9 @@ where
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.index = self.index + 1;
-        self.v.get(self.index - 1)
+        let next = self.v.get(self.index);
+        self.index += 1;
+        next
     }
 }
 

From c79ba750b0796010ef852c63a034dff19b41e6b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:13:00 +0000
Subject: [PATCH 546/2232] Suppress len_without_is_empty lint


---

diff --git a/src/lib.rs b/src/lib.rs
index 86318c8..cc0dcf2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -350,6 +350,7 @@
     clippy::declare_interior_mutable_const,
     clippy::inherent_to_string,
     clippy::large_enum_variant,
+    clippy::len_without_is_empty,
     clippy::missing_safety_doc,
     clippy::module_inception,
     clippy::needless_doctest_main,

From db450b0a9de864e147d9c881e30d629efadd4cf6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:16:57 +0000
Subject: [PATCH 547/2232] Suppress some lints in cxx-build


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 5bee67f..cabe2b1 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -45,6 +45,13 @@
 //! $ cxxbridge src/main.rs > path/to/mybridge.cc
 //! ```
 
+#![allow(
+    clippy::inherent_to_string,
+    clippy::needless_doctest_main,
+    clippy::new_without_default,
+    clippy::toplevel_ref_arg
+)]
+
 mod error;
 mod gen;
 mod paths;

From 884d91f0bc86242a6a984cbe6335cf99cf57f3cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:17:23 +0000
Subject: [PATCH 548/2232] Resolve absurd_extreme_comparisons lint


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 16846fb..e298e88 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -218,7 +218,7 @@ fn r_return_sum(n1: usize, n2: usize) -> usize {
 }
 
 fn r_return_enum(n: u32) -> ffi::Enum {
-    if n <= 0 {
+    if n == 0 {
         ffi::Enum::AVal
     } else if n <= 2020 {
         ffi::Enum::BVal

From a3f6407efac747dc09c73b4edc34799ffdf79abf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:28:00 +0000
Subject: [PATCH 549/2232] Expand discriminant overflow error message


Renders as:

    error[cxxbridge]: discriminant overflow on value after 4294967295
       ┌─ src/main.rs:11:9
       │
    11 │         B,
       │         ^ discriminant overflow
       │
       = note: explicitly set `= 0` if that is desired outcome

This more closely matches rustc's error message, which is:

    error[E0370]: enum discriminant overflowed
     --> src/lib.rs:4:5
      |
    4 |     B,
      |     ^ overflowed on value after 255
      |
      = note: explicitly set `B = 0` if that is desired outcome

---

diff --git a/syntax/error.rs b/syntax/error.rs
index f2cb8d1..a60b7da 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -18,6 +18,7 @@ pub static ERRORS: &[Error] = &[
     CXXBRIDGE_RESERVED,
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
+    DISCRIMINANT_OVERFLOW,
     DOUBLE_UNDERSCORE,
     RUST_TYPE_BY_VALUE,
     USE_NOT_ALLOWED,
@@ -47,6 +48,12 @@ pub static CXX_TYPE_BY_VALUE: Error = Error {
     note: Some("hint: wrap it in a UniquePtr<>"),
 };
 
+pub static DISCRIMINANT_OVERFLOW: Error = Error {
+    msg: "discriminant overflow on value after ",
+    label: Some("discriminant overflow"),
+    note: Some("note: explicitly set `= 0` if that is desired outcome"),
+};
+
 pub static DOUBLE_UNDERSCORE: Error = Error {
     msg: "identifiers containing double underscore are reserved in C++",
     label: Some("reserved identifier"),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1f6cbac..7e4422d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -112,7 +112,8 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
             }
         }
         if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
-            return Err(Error::new_spanned(variant, "overflowed on value"));
+            let msg = format!("discriminant overflow on value after {}", u32::MAX);
+            return Err(Error::new_spanned(variant, msg));
         }
         let discriminant =
             parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index 1a22146..db92f7f 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,4 +1,4 @@
-error: overflowed on value
+error: discriminant overflow on value after 4294967295
   --> $DIR/enum_overflows.rs:13:9
    |
 13 |         F,

From 4301f3ca51cada2595248758daf64d40be5bbfb1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:29:52 +0000
Subject: [PATCH 550/2232] Simplify discriminant overflow check


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7e4422d..602a269 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -111,7 +111,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
                 ));
             }
         }
-        if variant.discriminant.is_none() && prev_discriminant.unwrap_or(0) == u32::MAX {
+        if variant.discriminant.is_none() && prev_discriminant == Some(u32::MAX) {
             let msg = format!("discriminant overflow on value after {}", u32::MAX);
             return Err(Error::new_spanned(variant, msg));
         }

From dfbce4bbc566d356de7c27ad86117b2c14d1605c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 17:52:12 +0000
Subject: [PATCH 551/2232] Remove unreachable return case from cxx function shim


This is unreachable because returning a CxxVector by value is not
allowed.

    error[cxxbridge]: returning C++ vector by value is not supported
       ┌─ lib.rs:30:29
       │
    30 │     fn not_allowed() -> CxxVector<u8>;
       │                         ^^^^^^^^^^^^^ returning C++ vector by value is not supported
       │

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4e98674..f28a58e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -522,10 +522,6 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::CxxVector(_)) => write!(
-            out,
-            " /* Use RVO to convert to r-value and move construct */"
-        ),
         Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }

From 9531334f5a73c50d6ced9c6ff53681a3c89a5253 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 19:54:15 +0000
Subject: [PATCH 552/2232] Move github funding.yml out of repo root


---

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..7507077
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: dtolnay
diff --git a/FUNDING.yml b/FUNDING.yml
deleted file mode 100644
index 7507077..0000000
--- a/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-github: dtolnay

From 29061ea1d89704500f3a18f2038df9c5721f534f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 05 2020 20:56:54 +0000
Subject: [PATCH 553/2232] Update build status badge to GitHub Actions


---

diff --git a/README.md b/README.md
index f1cf00f..1b1611d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 CXX &mdash; safe FFI between Rust and C++
 =========================================
 
-[![Build Status](https://api.travis-ci.com/dtolnay/cxx.svg?branch=master)](https://travis-ci.com/dtolnay/cxx)
+[![Build Status](https://img.shields.io/github/workflow/status/dtolnay/cxx/CI/master)](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster)
 [![Latest Version](https://img.shields.io/crates/v/cxx.svg)](https://crates.io/crates/cxx)
 [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/cxx)
 

From 295ef6b38a1cf7b8f0b0029c5fa618bf515bb101 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 07 2020 23:10:30 +0000
Subject: [PATCH 554/2232] Adjust foreign item parsing to prepare for type aliases


This will be required for parse_extern_type to return a different kind
of Api for the case of type aliases.

---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 602a269..b794ba9 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -164,24 +164,16 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
         Ok(lang) => lang,
         Err(err) => return cx.push(err),
     };
-    let api_type = match lang {
-        Lang::Cxx => Api::CxxType,
-        Lang::Rust => Api::RustType,
-    };
-    let api_function = match lang {
-        Lang::Cxx => Api::CxxFunction,
-        Lang::Rust => Api::RustFunction,
-    };
 
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(foreign) {
-                Ok(ety) => items.push(api_type(ety)),
+            ForeignItem::Type(foreign) => match parse_extern_type(foreign, lang) {
+                Ok(ety) => items.push(ety),
                 Err(err) => cx.push(err),
             },
             ForeignItem::Fn(foreign) => match parse_extern_fn(foreign, lang) {
-                Ok(efn) => items.push(api_function(efn)),
+                Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
@@ -231,18 +223,22 @@ fn parse_lang(abi: Abi) -> Result<Lang> {
     }
 }
 
-fn parse_extern_type(foreign_type: &ForeignItemType) -> Result<ExternType> {
+fn parse_extern_type(foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
     let doc = attrs::parse_doc(&foreign_type.attrs)?;
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
-    Ok(ExternType {
+    let api_type = match lang {
+        Lang::Cxx => Api::CxxType,
+        Lang::Rust => Api::RustType,
+    };
+    Ok(api_type(ExternType {
         doc,
         type_token,
         ident,
-    })
+    }))
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
+fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -318,8 +314,12 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
     let ident = foreign_fn.sig.ident.clone();
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
+    let api_function = match lang {
+        Lang::Cxx => Api::CxxFunction,
+        Lang::Rust => Api::RustFunction,
+    };
 
-    Ok(ExternFn {
+    Ok(api_function(ExternFn {
         lang,
         doc,
         ident,
@@ -333,7 +333,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<ExternFn> {
             throws_tokens,
         },
         semi_token,
-    })
+    }))
 }
 
 fn parse_type(ty: &RustType) -> Result<Type> {

From 6e80833572b3bf6e7b47cb54ebbd5d79cc97d4f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:44:11 +0000
Subject: [PATCH 555/2232] Support code generation for multiple cxx::bridge files in one Build


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index cabe2b1..9e8475a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -62,6 +62,7 @@ use crate::gen::Opt;
 use anyhow::anyhow;
 use std::fs;
 use std::io::{self, Write};
+use std::iter;
 use std::path::Path;
 use std::process;
 
@@ -72,16 +73,31 @@ use std::process;
 /// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
 #[must_use]
 pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
-    match try_generate_bridge(rust_source_file.as_ref()) {
-        Ok(build) => build,
-        Err(err) => {
+    bridges(iter::once(rust_source_file))
+}
+
+/// `cxx_build::bridge` but for when more than one file contains a
+/// #\[cxx::bridge\] module.
+///
+/// ```no_run
+/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
+/// cxx_build::bridges(source_files)
+///     .file("../demo-cxx/demo.cc")
+///     .flag("-std=c++11")
+///     .compile("cxxbridge-demo");
+/// ```
+pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
+    let mut build = paths::cc_build();
+    for path in rust_source_files {
+        if let Err(err) = try_generate_bridge(&mut build, path.as_ref()) {
             let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
             process::exit(1);
         }
     }
+    build
 }
 
-fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
+fn try_generate_bridge(build: &mut cc::Build, rust_source_file: &Path) -> Result<()> {
     let header = gen::do_generate_header(rust_source_file, Opt::default());
     let header_path = paths::out_with_extension(rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
@@ -91,7 +107,6 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
     let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
     fs::write(&bridge_path, bridge)?;
-    let mut build = paths::cc_build();
     build.file(&bridge_path);
 
     let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
@@ -99,5 +114,5 @@ fn try_generate_bridge(rust_source_file: &Path) -> Result<cc::Build> {
     let _ = fs::remove_file(cxx_h);
     let _ = fs::write(cxx_h, gen::include::HEADER);
 
-    Ok(build)
+    Ok(())
 }

From db08d4affec5fa375736e7652ebe54c253bc29e1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:01 +0000
Subject: [PATCH 556/2232] Pull in quote 1.0.4


Includes https://github.com/dtolnay/quote/pull/151 which will be used in
the implementation of type_id.

---

diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 4c2d423..18b46e5 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -13,7 +13,7 @@ proc-macro = true
 
 [dependencies]
 proc-macro2 = "1.0"
-quote = "1.0"
+quote = "1.0.4"
 syn = { version = "1.0", features = ["full"] }
 
 [dev-dependencies]

From d09e012608fbe9c0e6929e33ae5f8dc214fbb1d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:01 +0000
Subject: [PATCH 557/2232] Add a type-level encoding of qualified paths


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b56f58e..bc8d19b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -11,10 +11,11 @@ extern crate proc_macro;
 
 mod expand;
 mod syntax;
+mod type_id;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod};
+use syn::{parse_macro_input, ItemMod, LitStr};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,3 +45,9 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
+
+#[proc_macro]
+pub fn type_id(input: TokenStream) -> TokenStream {
+    let arg = parse_macro_input!(input as LitStr);
+    type_id::expand(arg).into()
+}
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
new file mode 100644
index 0000000..15a5833
--- /dev/null
+++ b/macro/src/type_id.rs
@@ -0,0 +1,29 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::LitStr;
+
+// "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
+pub fn expand(arg: LitStr) -> TokenStream {
+    let mut ids = Vec::new();
+
+    for word in arg.value().split("::") {
+        if !ids.is_empty() {
+            ids.push(quote!(()));
+        }
+        for ch in word.chars() {
+            ids.push(match ch {
+                'A'..='Z' | 'a'..='z' => {
+                    let t = format_ident!("{}", ch);
+                    quote!(::cxx::private::#t)
+                }
+                '0'..='9' | '_' => {
+                    let t = format_ident!("_{}", ch);
+                    quote!(::cxx::private::#t)
+                }
+                _ => quote!([(); #ch as _]),
+            });
+        }
+    }
+
+    quote! { (#(#ids,)*) }
+}
diff --git a/src/lib.rs b/src/lib.rs
index cc0dcf2..39b1ecc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -376,6 +376,7 @@ mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
+mod type_id;
 mod unique_ptr;
 mod unwind;
 
@@ -386,7 +387,7 @@ pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::unique_ptr::UniquePtr;
-pub use cxxbridge_macro::bridge;
+pub use cxxbridge_macro::{bridge, type_id};
 
 // Not public API.
 #[doc(hidden)]
@@ -399,6 +400,7 @@ pub mod private {
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::rust_vec::RustVec;
+    pub use crate::type_id::*;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
diff --git a/src/type_id.rs b/src/type_id.rs
new file mode 100644
index 0000000..68020ea
--- /dev/null
+++ b/src/type_id.rs
@@ -0,0 +1,16 @@
+#![allow(non_camel_case_types)]
+
+macro_rules! chars {
+    ($($ch:ident)*) => {
+        $(
+            pub enum $ch {}
+        )*
+    };
+}
+
+chars! {
+    _0 _1 _2 _3 _4 _5 _6 _7 _8 _9
+    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+    a b c d e f g h i j k l m n o p q r s t u v w x y z
+    __ // underscore
+}

From 9938381aa777ac49e973d322e48b1aa3aacd2ac9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 558/2232] Introduce type aliases in syntax tree


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fcb845c..6eac0d9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -55,6 +55,7 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::RustFunction(efn) => {
                 hidden.extend(expand_rust_function_shim(namespace, efn, types))
             }
+            Api::TypeAlias(_alias) => unimplemented!(),
         }
     }
 
diff --git a/syntax/ident.rs b/syntax/ident.rs
index cec424c..41eef3b 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -42,6 +42,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                     check(cx, &arg.ident);
                 }
             }
+            Api::TypeAlias(_alias) => unimplemented!(),
         }
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index fd8db73..3eb6c6e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,7 +20,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Lifetime, LitStr, Token};
+use syn::{Lifetime, LitStr, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -35,6 +35,7 @@ pub enum Api {
     CxxFunction(ExternFn),
     RustType(ExternType),
     RustFunction(ExternFn),
+    TypeAlias(TypeAlias),
 }
 
 pub struct ExternType {
@@ -68,6 +69,14 @@ pub struct ExternFn {
     pub semi_token: Token![;],
 }
 
+pub struct TypeAlias {
+    pub type_token: Token![type],
+    pub ident: Ident,
+    pub eq_token: Token![=],
+    pub ty: RustType,
+    pub semi_token: Token![;],
+}
+
 pub struct Signature {
     pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 934c85b..6dd6073 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type, Var,
+    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
+    TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -86,6 +87,14 @@ impl ToTokens for ExternType {
     }
 }
 
+impl ToTokens for TypeAlias {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        // Notional token range for error reporting purposes.
+        self.type_token.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Struct {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
diff --git a/syntax/types.rs b/syntax/types.rs
index 5800513..2ab8cbd 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -96,6 +96,7 @@ impl<'a> Types<'a> {
                         visit(&mut all, ret);
                     }
                 }
+                Api::TypeAlias(_alias) => unimplemented!(),
             }
         }
 

From e47119ca2fa337fa585b6079e022f7d221e320b9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 559/2232] Pull in syn 1.0.19


Includes https://github.com/dtolnay/syn/pull/790 which we need for
extern type aliases.

---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 1cbcced..16aeba3 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,7 +13,7 @@ cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.19", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 57f2e39..92adb89 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.19", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 18b46e5..8ade852 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -14,7 +14,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0.4"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.19", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "0.3", path = ".." }
diff --git a/third-party/BUCK b/third-party/BUCK
index 2de784b..e16bad2 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.18/src/**"]),
+    srcs = glob(["vendor/syn-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 4d8fd9f..45b1163 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.18/src/**"]),
+    srcs = glob(["vendor/syn-1.0.19/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3397192..231863d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.18"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
+checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
 dependencies = [
  "proc-macro2",
  "quote",

From e2f9ec4c891ef06683cdb63ff4076c4c918e75e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 560/2232] Type alias parsing


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index b794ba9..b41f3df 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -2,17 +2,19 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Var, Variant,
+    Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
+use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
 use std::collections::HashSet;
 use std::u32;
+use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat, PathArguments,
-    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
-    Variant as RustVariant,
+    Abi, Attribute, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn,
+    ForeignItemType, GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat,
+    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
+    TypeReference, TypeSlice, Variant as RustVariant,
 };
 
 pub mod kw {
@@ -182,6 +184,10 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
                     Err(err) => cx.push(err),
                 }
             }
+            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(tokens, lang) {
+                Ok(api) => items.push(api),
+                Err(err) => cx.push(err),
+            },
             _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
@@ -336,6 +342,44 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     }))
 }
 
+fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
+    // type Alias = crate::path::to::Type;
+    fn parse(input: ParseStream) -> Result<TypeAlias> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let type_token: Token![type] = match input.parse()? {
+            Some(type_token) => type_token,
+            None => {
+                let span = input.cursor().token_stream();
+                return Err(Error::new_spanned(span, "unsupported foreign item"));
+            }
+        };
+        let ident: Ident = input.parse()?;
+        let eq_token: Token![=] = input.parse()?;
+        let ty: RustType = input.parse()?;
+        let semi_token: Token![;] = input.parse()?;
+        attrs::parse_doc(&attrs)?;
+
+        Ok(TypeAlias {
+            type_token,
+            ident,
+            eq_token,
+            ty,
+            semi_token,
+        })
+    }
+
+    let type_alias = parse.parse2(tokens.clone())?;
+    match lang {
+        Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
+        Lang::Rust => {
+            let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
+            let span = quote!(#type_token #semi_token);
+            let msg = "type alias in extern \"Rust\" block is not supported";
+            Err(Error::new_spanned(span, msg))
+        }
+    }
+}
+
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
diff --git a/tests/ui/type_alias_rust.rs b/tests/ui/type_alias_rust.rs
new file mode 100644
index 0000000..67df489
--- /dev/null
+++ b/tests/ui/type_alias_rust.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        /// Incorrect.
+        type Alias = crate::Type;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type_alias_rust.stderr b/tests/ui/type_alias_rust.stderr
new file mode 100644
index 0000000..1b08f67
--- /dev/null
+++ b/tests/ui/type_alias_rust.stderr
@@ -0,0 +1,5 @@
+error: type alias in extern "Rust" block is not supported
+ --> $DIR/type_alias_rust.rs:5:9
+  |
+5 |         type Alias = crate::Type;
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^

From 3118fa6606b8705af46febb078dbcd96e7b41a2b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 561/2232] Type alias ident checking


---

diff --git a/syntax/ident.rs b/syntax/ident.rs
index 41eef3b..7545e92 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -42,7 +42,9 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                     check(cx, &arg.ident);
                 }
             }
-            Api::TypeAlias(_alias) => unimplemented!(),
+            Api::TypeAlias(alias) => {
+                check(cx, &alias.ident);
+            }
         }
     }
 }

From 379d342779696f38ee67ae8a3d6367c7a2caf8e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 562/2232] Type alias type info


---

diff --git a/syntax/types.rs b/syntax/types.rs
index 2ab8cbd..987d618 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -96,7 +96,13 @@ impl<'a> Types<'a> {
                         visit(&mut all, ret);
                     }
                 }
-                Api::TypeAlias(_alias) => unimplemented!(),
+                Api::TypeAlias(alias) => {
+                    let ident = &alias.ident;
+                    if !type_names.insert(ident) {
+                        duplicate_name(cx, alias, ident);
+                    }
+                    cxx.insert(ident);
+                }
             }
         }
 

From 5f9e8ca1a00b31cfd328da216f6ec6ee45165e13 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 563/2232] Type alias code generation


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6eac0d9..e3026ba 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,7 +3,7 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -46,7 +46,7 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 if !types.enums.contains_key(&ety.ident) {
-                    expanded.extend(expand_cxx_type(ety));
+                    expanded.extend(expand_cxx_type(namespace, ety));
                 }
             }
             Api::CxxFunction(efn) => {
@@ -55,7 +55,10 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::RustFunction(efn) => {
                 hidden.extend(expand_rust_function_shim(namespace, efn, types))
             }
-            Api::TypeAlias(_alias) => unimplemented!(),
+            Api::TypeAlias(alias) => {
+                expanded.extend(expand_type_alias(alias));
+                hidden.extend(expand_type_alias_verify(namespace, alias));
+            }
         }
     }
 
@@ -162,15 +165,21 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     }
 }
 
-fn expand_cxx_type(ety: &ExternType) -> TokenStream {
+fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     let doc = &ety.doc;
+    let type_id = type_id(namespace, ident);
+
     quote! {
         #doc
         #[repr(C)]
         pub struct #ident {
             _private: ::cxx::private::Opaque,
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+        }
     }
 }
 
@@ -555,6 +564,35 @@ fn expand_rust_function_shim_impl(
     }
 }
 
+fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let ty = &alias.ty;
+    quote! {
+        pub type #ident = #ty;
+    }
+}
+
+fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let type_id = type_id(namespace, ident);
+    quote! {
+        const _: fn() = ::cxx::private::verify_extern_type::<#ident, #type_id>;
+    }
+}
+
+fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
+    let mut path = String::new();
+    for name in namespace {
+        path += &name.to_string();
+        path += "::";
+    }
+    path += &ident.to_string();
+
+    quote! {
+        ::cxx::type_id!(#path)
+    }
+}
+
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_prefix = format!("cxxbridge03$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
diff --git a/src/extern_type.rs b/src/extern_type.rs
new file mode 100644
index 0000000..f7c376b
--- /dev/null
+++ b/src/extern_type.rs
@@ -0,0 +1,6 @@
+pub unsafe trait ExternType {
+    type Id;
+}
+
+#[doc(hidden)]
+pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
diff --git a/src/lib.rs b/src/lib.rs
index 39b1ecc..d15d441 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -369,6 +369,7 @@ mod macros;
 mod cxx_string;
 mod cxx_vector;
 mod exception;
+mod extern_type;
 mod function;
 mod opaque;
 mod result;
@@ -386,6 +387,7 @@ mod symbols;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
+pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::{bridge, type_id};
 
@@ -393,6 +395,7 @@ pub use cxxbridge_macro::{bridge, type_id};
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
+    pub use crate::extern_type::verify_extern_type;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};

From 9f07303af10661133a212f302ffb04804ffcfca4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 564/2232] Add ui test of type_id mismatch


---

diff --git a/tests/ui/wrong_type_id.rs b/tests/ui/wrong_type_id.rs
new file mode 100644
index 0000000..81a9b3f
--- /dev/null
+++ b/tests/ui/wrong_type_id.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge(namespace = folly)]
+mod here {
+    extern "C" {
+        type StringPiece;
+    }
+}
+
+#[cxx::bridge(namespace = folly)]
+mod there {
+    extern "C" {
+        type ByteRange = crate::here::StringPiece;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
new file mode 100644
index 0000000..e6b9fc7
--- /dev/null
+++ b/tests/ui/wrong_type_id.stderr
@@ -0,0 +1,14 @@
+error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::B, cxx::type_id::y, cxx::type_id::t, cxx::type_id::e, cxx::type_id::R, cxx::type_id::a, cxx::type_id::n, cxx::type_id::g, cxx::type_id::e)`
+ --> $DIR/wrong_type_id.rs:8:1
+  |
+8 | #[cxx::bridge(namespace = folly)]
+  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
+  | 
+ ::: $WORKSPACE/src/extern_type.rs:6:41
+  |
+6 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+  |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+  |
+  = note: expected tuple `(cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::B, cxx::type_id::y, cxx::type_id::t, cxx::type_id::e, cxx::type_id::R, cxx::type_id::a, cxx::type_id::n, cxx::type_id::g, cxx::type_id::e)`
+             found tuple `(cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::S, cxx::type_id::t, cxx::type_id::r, cxx::type_id::i, cxx::type_id::n, cxx::type_id::g, cxx::type_id::P, cxx::type_id::i, cxx::type_id::e, cxx::type_id::c, cxx::type_id::e)`
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From c6ba2d27f486895999feeb4c6753120897be8872 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 02:46:02 +0000
Subject: [PATCH 565/2232] Condense type ids rendered by rustc


---

diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 15a5833..445da2b 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -14,11 +14,11 @@ pub fn expand(arg: LitStr) -> TokenStream {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
-                    quote!(::cxx::private::#t)
+                    quote!(::cxx::#t)
                 }
                 '0'..='9' | '_' => {
                     let t = format_ident!("_{}", ch);
-                    quote!(::cxx::private::#t)
+                    quote!(::cxx::#t)
                 }
                 _ => quote!([(); #ch as _]),
             });
diff --git a/src/lib.rs b/src/lib.rs
index d15d441..32d42a0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -345,6 +345,7 @@
 
 #![doc(html_root_url = "https://docs.rs/cxx/0.3.0")]
 #![deny(improper_ctypes)]
+#![allow(non_camel_case_types)]
 #![allow(
     clippy::cognitive_complexity,
     clippy::declare_interior_mutable_const,
@@ -377,7 +378,6 @@ mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
-mod type_id;
 mod unique_ptr;
 mod unwind;
 
@@ -403,7 +403,22 @@ pub mod private {
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::rust_vec::RustVec;
-    pub use crate::type_id::*;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
+
+macro_rules! chars {
+    ($($ch:ident)*) => {
+        $(
+            #[doc(hidden)]
+            pub enum $ch {}
+        )*
+    };
+}
+
+chars! {
+    _0 _1 _2 _3 _4 _5 _6 _7 _8 _9
+    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+    a b c d e f g h i j k l m n o p q r s t u v w x y z
+    __ // underscore
+}
diff --git a/src/type_id.rs b/src/type_id.rs
deleted file mode 100644
index 68020ea..0000000
--- a/src/type_id.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-#![allow(non_camel_case_types)]
-
-macro_rules! chars {
-    ($($ch:ident)*) => {
-        $(
-            pub enum $ch {}
-        )*
-    };
-}
-
-chars! {
-    _0 _1 _2 _3 _4 _5 _6 _7 _8 _9
-    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
-    a b c d e f g h i j k l m n o p q r s t u v w x y z
-    __ // underscore
-}
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index e6b9fc7..165cdc0 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::B, cxx::type_id::y, cxx::type_id::t, cxx::type_id::e, cxx::type_id::R, cxx::type_id::a, cxx::type_id::n, cxx::type_id::g, cxx::type_id::e)`
+error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
  --> $DIR/wrong_type_id.rs:8:1
   |
 8 | #[cxx::bridge(namespace = folly)]
@@ -9,6 +9,6 @@ error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::E
 6 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
   |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
   |
-  = note: expected tuple `(cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::B, cxx::type_id::y, cxx::type_id::t, cxx::type_id::e, cxx::type_id::R, cxx::type_id::a, cxx::type_id::n, cxx::type_id::g, cxx::type_id::e)`
-             found tuple `(cxx::type_id::f, cxx::type_id::o, cxx::type_id::l, cxx::type_id::l, cxx::type_id::y, (), cxx::type_id::S, cxx::type_id::t, cxx::type_id::r, cxx::type_id::i, cxx::type_id::n, cxx::type_id::g, cxx::type_id::P, cxx::type_id::i, cxx::type_id::e, cxx::type_id::c, cxx::type_id::e)`
+  = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+             found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 83fe0f06d5933b324a288b8e1717b61dbf92ab9f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 03:14:49 +0000
Subject: [PATCH 566/2232] Preserve a better span for type id mismatch errors


---

diff --git a/Cargo.toml b/Cargo.toml
index 1455e55..dd7c18f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ cc = "1.0.49"
 cxx-build = { version = "=0.3.0", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = { version = "1.0.21", features = ["diff"] }
+trybuild = { version = "1.0.27", features = ["diff"] }
 
 [workspace]
 members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e3026ba..efd20e8 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -575,8 +575,13 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
 fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
     let ident = &alias.ident;
     let type_id = type_id(namespace, 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::<);
+    let end = quote_spanned!(end_span=> >);
+
     quote! {
-        const _: fn() = ::cxx::private::verify_extern_type::<#ident, #type_id>;
+        const _: fn() = #begin #ident, #type_id #end;
     }
 }
 
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index 165cdc0..969c826 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,14 +1,13 @@
 error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
- --> $DIR/wrong_type_id.rs:8:1
-  |
-8 | #[cxx::bridge(namespace = folly)]
-  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
-  | 
- ::: $WORKSPACE/src/extern_type.rs:6:41
-  |
-6 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
-  |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
-  |
-  = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
-             found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/wrong_type_id.rs:11:9
+   |
+11 |         type ByteRange = crate::here::StringPiece;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
+   |
+  ::: $WORKSPACE/src/extern_type.rs:6:41
+   |
+6  | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+   |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+   |
+   = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+              found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`

From e5a015a2b4c299aa77fd3d533290b916837ae8d9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 04:54:31 +0000
Subject: [PATCH 567/2232] Allow type alias as a method receiver


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index b41f3df..0640e7f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -193,11 +193,12 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
     }
 
     let mut types = items.iter().filter_map(|item| match item {
-        Api::CxxType(ty) | Api::RustType(ty) => Some(ty),
+        Api::CxxType(ty) | Api::RustType(ty) => Some(&ty.ident),
+        Api::TypeAlias(alias) => Some(&alias.ident),
         _ => None,
     });
     if let (Some(single_type), None) = (types.next(), types.next()) {
-        let single_type = single_type.ident.clone();
+        let single_type = single_type.clone();
         for item in &mut items {
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {

From 2b821e60e00c139dd8a2db829c0bf5a052ebd875 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 06:18:09 +0000
Subject: [PATCH 568/2232] Don't do trait impls for non-local types


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index f28a58e..8f54bd7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -971,10 +971,6 @@ fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
 }
 
 fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
-    fn allow_unique_ptr(ident: &Ident) -> bool {
-        Atom::from(ident).is_none()
-    }
-
     out.begin_block("extern \"C\"");
     for ty in types {
         if let Type::RustBox(ty) = ty {
@@ -991,14 +987,14 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if allow_unique_ptr(inner) {
+                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() {
+                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index efd20e8..fc129c6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -77,13 +77,13 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() {
+                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
                     expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() {
+                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
diff --git a/syntax/types.rs b/syntax/types.rs
index 987d618..ba9bc78 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -12,6 +12,7 @@ pub struct Types<'a> {
     pub enums: Map<Ident, &'a Enum>,
     pub cxx: Set<'a, Ident>,
     pub rust: Set<'a, Ident>,
+    pub aliases: Map<Ident, &'a TypeAlias>,
 }
 
 impl<'a> Types<'a> {
@@ -21,6 +22,7 @@ impl<'a> Types<'a> {
         let mut enums = Map::new();
         let mut cxx = Set::new();
         let mut rust = Set::new();
+        let mut aliases = Map::new();
 
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
@@ -102,6 +104,7 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, alias, ident);
                     }
                     cxx.insert(ident);
+                    aliases.insert(ident.clone(), alias);
                 }
             }
         }
@@ -112,6 +115,7 @@ impl<'a> Types<'a> {
             enums,
             cxx,
             rust,
+            aliases,
         }
     }
 

From a62cca2268582a42c9895428f71df5310ad6ad2a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 06:20:06 +0000
Subject: [PATCH 569/2232] Add a use of type alias to test suite


---

diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index b970362..2c96d73 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -3,7 +3,8 @@ fn main() {
         return;
     }
 
-    cxx_build::bridge("lib.rs")
+    let sources = vec!["lib.rs", "module.rs"];
+    cxx_build::bridges(sources)
         .file("tests.cc")
         .flag("-std=c++11")
         .compile("cxx-test-suite");
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e298e88..9457229 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,6 +4,8 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
+pub mod module;
+
 use cxx::{CxxString, UniquePtr};
 use std::fmt::{self, Display};
 
@@ -47,7 +49,6 @@ pub mod ffi {
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
         fn c_take_box(r: Box<R>);
-        fn c_take_unique_ptr(c: UniquePtr<C>);
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
new file mode 100644
index 0000000..77bae06
--- /dev/null
+++ b/tests/ffi/module.rs
@@ -0,0 +1,13 @@
+// Rustfmt mangles the extern type alias.
+// https://github.com/rust-lang/rustfmt/issues/4159
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi {
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        type C = crate::ffi::C;
+
+        fn c_take_unique_ptr(c: UniquePtr<C>);
+    }
+}
diff --git a/tests/test.rs b/tests/test.rs
index b8593c5..ddf8f70 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -89,7 +89,7 @@ fn test_c_take() {
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
-    check!(ffi::c_take_unique_ptr(unique_ptr));
+    check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
     check!(ffi::c_take_rust_string("2020".to_owned()));

From 094db3ecea92f93463f7bea681a8fcb3c90bb5d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 09:06:30 +0000
Subject: [PATCH 570/2232] Document ExternType trait


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index f7c376b..6701ef5 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,4 +1,108 @@
+/// A type for which the layout is determined by its C++ definition.
+///
+/// This trait serves the following two related purposes.
+///
+/// <br>
+///
+/// ## Safely unifying occurrences of the same extern type
+///
+/// `ExternType` makes it possible for CXX to safely share a consistent Rust
+/// type across multiple #\[cxx::bridge\] invocations that refer to a common
+/// extern C++ type.
+///
+/// In the following snippet, two #\[cxx::bridge\] invocations in different
+/// files (possibly different crates) both contain function signatures involving
+/// the same C++ type `example::Demo`. If both were written just containing
+/// `type Demo;`, then both macro expansions would produce their own separate
+/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
+/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
+/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
+/// `Demo`s has been defined as an extern type alias of the other, making them
+/// the same type in Rust. The CXX code generator will use an automatically
+/// generated `ExternType` impl emitted in file1 to statically verify that in
+/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
+/// `example::Demo` as expected in file2.
+///
+/// ```no_run
+/// // file1.rs
+/// # mod file1 {
+/// #[cxx::bridge(namespace = example)]
+/// pub mod ffi {
+///     extern "C" {
+///         type Demo;
+///
+///         fn create_demo() -> UniquePtr<Demo>;
+///     }
+/// }
+/// # }
+///
+/// // file2.rs
+/// #[cxx::bridge(namespace = example)]
+/// pub mod ffi {
+///     extern "C" {
+///         type Demo = crate::file1::ffi::Demo;
+///
+///         fn take_ref_demo(demo: &Demo);
+///     }
+/// }
+/// #
+/// # fn main() {}
+/// ```
+///
+/// <br><br>
+///
+/// ## Integrating with bindgen-generated types
+///
+/// Handwritten `ExternType` impls make it possible to plug in a data structure
+/// emitted by bindgen as the definition of an opaque C++ type emitted by CXX.
+///
+/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
+/// namespace and type name given in the type id refers to a C++ type that is
+/// equivalent to Rust type that is the `Self` type of the impl.
+///
+/// ```no_run
+/// # const _: &str = stringify! {
+/// mod folly_sys;  // the bindgen-generated bindings
+/// # };
+/// # mod folly_sys {
+/// #     #[repr(transparent)]
+/// #     pub struct StringPiece([usize; 2]);
+/// # }
+///
+/// use cxx::{type_id, ExternType};
+///
+/// unsafe impl ExternType for folly_sys::StringPiece {
+///     type Id = type_id!("folly::StringPiece");
+/// }
+///
+/// #[cxx::bridge(namespace = folly)]
+/// pub mod ffi {
+///     extern "C" {
+///         include!("rust_cxx_bindings.h");
+///
+///         type StringPiece = crate::folly_sys::StringPiece;
+///
+///         fn print_string_piece(s: &StringPiece);
+///     }
+/// }
+///
+/// // Now if we construct a StringPiece or obtain one through one
+/// // of the bindgen-generated signatures, we are able to pass it
+/// // along to ffi::print_string_piece.
+/// #
+/// # fn main() {}
+/// ```
 pub unsafe trait ExternType {
+    /// A type-level representation of the type's C++ namespace and type name.
+    ///
+    /// This will always be defined using `type_id!` in the following form:
+    ///
+    /// ```
+    /// # struct TypeName;
+    /// # unsafe impl cxx::ExternType for TypeName {
+    /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// # }
+    /// ```
     type Id;
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 32d42a0..fc0e682 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -389,7 +389,10 @@ pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
-pub use cxxbridge_macro::{bridge, type_id};
+pub use cxxbridge_macro::{bridge};
+
+/// For use in impls of the `ExternType` trait. See [`ExternType`].
+pub use cxxbridge_macro::type_id;
 
 // Not public API.
 #[doc(hidden)]
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index 969c826..5b4f6c6 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,13 +1,13 @@
 error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
-  --> $DIR/wrong_type_id.rs:11:9
-   |
-11 |         type ByteRange = crate::here::StringPiece;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
-   |
-  ::: $WORKSPACE/src/extern_type.rs:6:41
-   |
-6  | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
-   |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
-   |
-   = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
-              found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`
+   --> $DIR/wrong_type_id.rs:11:9
+    |
+11  |         type ByteRange = crate::here::StringPiece;
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
+    |
+   ::: $WORKSPACE/src/extern_type.rs:110:41
+    |
+110 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+    |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+    |
+    = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+               found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`

From ae4dedab556191d644f6c96c739962770d94eedf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 09:23:10 +0000
Subject: [PATCH 571/2232] Update build files of test suite


---

diff --git a/tests/BUCK b/tests/BUCK
index 659223c..41781c8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -6,7 +6,10 @@ rust_test(
 
 rust_library(
     name = "ffi",
-    srcs = ["ffi/lib.rs"],
+    srcs = [
+        "ffi/lib.rs",
+        "ffi/module.rs",
+    ],
     crate = "cxx_test_suite",
     deps = [
         ":impl",
@@ -18,25 +21,33 @@ cxx_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-source",
+        ":gen-lib-source",
+        ":gen-module-source",
     ],
     headers = {
-        "ffi/lib.rs.h": ":gen-header",
+        "ffi/lib.rs.h": ":gen-lib-header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
 
 genrule(
-    name = "gen-header",
+    name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    out = "generated.h",
+    out = "lib.rs.h",
 )
 
 genrule(
-    name = "gen-source",
+    name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    out = "generated.cc",
+    out = "lib.rs.cc",
+)
+
+genrule(
+    name = "gen-module-source",
+    srcs = ["ffi/module.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    out = "module.rs.cc",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 65c5b41..e1f1637 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -8,7 +8,10 @@ rust_test(
 
 rust_library(
     name = "cxx_test_suite",
-    srcs = ["ffi/lib.rs"],
+    srcs = [
+        "ffi/lib.rs",
+        "ffi/module.rs",
+    ],
     deps = [
         ":impl",
         "//:cxx",
@@ -19,17 +22,18 @@ cc_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-source",
+        ":gen-lib-source",
+        ":gen-module-source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
-        ":include",
+        ":lib-include",
         "//:core",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
     outs = ["lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -37,15 +41,23 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    outs = ["generated.cc"],
+    outs = ["lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
 
 cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
+    name = "lib-include",
+    hdrs = [":gen-lib-header"],
     include_prefix = "tests/ffi",
 )
+
+genrule(
+    name = "gen-module-source",
+    srcs = ["ffi/module.rs"],
+    outs = ["module.rs.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 231863d..b1227f9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -356,9 +356,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e5696e4fd793743fbcc29943fe965ea3993b6c3d2a6a3a35c6680d926fd3a49"
+checksum = "744665442556a91933cee5e75b0371376eb03498c4d0bfbcebd2a9882b4fb5ef"
 dependencies = [
  "dissimilar",
  "glob",

From 2429c6b0f6e8a203a05619e7990487a55b620cd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 09:36:06 +0000
Subject: [PATCH 572/2232] Merge pull request #190 from dtolnay/id


Enable sharing a consistent Rust type across multiple FFI blocks
---

diff --git a/Cargo.toml b/Cargo.toml
index 1455e55..dd7c18f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ cc = "1.0.49"
 cxx-build = { version = "=0.3.0", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = { version = "1.0.21", features = ["diff"] }
+trybuild = { version = "1.0.27", features = ["diff"] }
 
 [workspace]
 members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 1cbcced..16aeba3 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,7 +13,7 @@ cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.19", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 57f2e39..92adb89 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
-syn = { version = "1.0", features = ["full"] }
+syn = { version = "1.0.19", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f28a58e..8f54bd7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -971,10 +971,6 @@ fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
 }
 
 fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
-    fn allow_unique_ptr(ident: &Ident) -> bool {
-        Atom::from(ident).is_none()
-    }
-
     out.begin_block("extern \"C\"");
     for ty in types {
         if let Type::RustBox(ty) = ty {
@@ -991,14 +987,14 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if allow_unique_ptr(inner) {
+                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() {
+                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
                 }
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 4c2d423..8ade852 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -13,8 +13,8 @@ proc-macro = true
 
 [dependencies]
 proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
+quote = "1.0.4"
+syn = { version = "1.0.19", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "0.3", path = ".." }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fcb845c..fc129c6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,7 +3,7 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -46,7 +46,7 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 if !types.enums.contains_key(&ety.ident) {
-                    expanded.extend(expand_cxx_type(ety));
+                    expanded.extend(expand_cxx_type(namespace, ety));
                 }
             }
             Api::CxxFunction(efn) => {
@@ -55,6 +55,10 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             Api::RustFunction(efn) => {
                 hidden.extend(expand_rust_function_shim(namespace, efn, types))
             }
+            Api::TypeAlias(alias) => {
+                expanded.extend(expand_type_alias(alias));
+                hidden.extend(expand_type_alias_verify(namespace, alias));
+            }
         }
     }
 
@@ -73,13 +77,13 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() {
+                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
                     expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() {
+                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
@@ -161,15 +165,21 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     }
 }
 
-fn expand_cxx_type(ety: &ExternType) -> TokenStream {
+fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     let doc = &ety.doc;
+    let type_id = type_id(namespace, ident);
+
     quote! {
         #doc
         #[repr(C)]
         pub struct #ident {
             _private: ::cxx::private::Opaque,
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+        }
     }
 }
 
@@ -554,6 +564,40 @@ fn expand_rust_function_shim_impl(
     }
 }
 
+fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let ty = &alias.ty;
+    quote! {
+        pub type #ident = #ty;
+    }
+}
+
+fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let type_id = type_id(namespace, 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::<);
+    let end = quote_spanned!(end_span=> >);
+
+    quote! {
+        const _: fn() = #begin #ident, #type_id #end;
+    }
+}
+
+fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
+    let mut path = String::new();
+    for name in namespace {
+        path += &name.to_string();
+        path += "::";
+    }
+    path += &ident.to_string();
+
+    quote! {
+        ::cxx::type_id!(#path)
+    }
+}
+
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_prefix = format!("cxxbridge03$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b56f58e..bc8d19b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -11,10 +11,11 @@ extern crate proc_macro;
 
 mod expand;
 mod syntax;
+mod type_id;
 
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod};
+use syn::{parse_macro_input, ItemMod, LitStr};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -44,3 +45,9 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
+
+#[proc_macro]
+pub fn type_id(input: TokenStream) -> TokenStream {
+    let arg = parse_macro_input!(input as LitStr);
+    type_id::expand(arg).into()
+}
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
new file mode 100644
index 0000000..445da2b
--- /dev/null
+++ b/macro/src/type_id.rs
@@ -0,0 +1,29 @@
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::LitStr;
+
+// "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
+pub fn expand(arg: LitStr) -> TokenStream {
+    let mut ids = Vec::new();
+
+    for word in arg.value().split("::") {
+        if !ids.is_empty() {
+            ids.push(quote!(()));
+        }
+        for ch in word.chars() {
+            ids.push(match ch {
+                'A'..='Z' | 'a'..='z' => {
+                    let t = format_ident!("{}", ch);
+                    quote!(::cxx::#t)
+                }
+                '0'..='9' | '_' => {
+                    let t = format_ident!("_{}", ch);
+                    quote!(::cxx::#t)
+                }
+                _ => quote!([(); #ch as _]),
+            });
+        }
+    }
+
+    quote! { (#(#ids,)*) }
+}
diff --git a/src/extern_type.rs b/src/extern_type.rs
new file mode 100644
index 0000000..6701ef5
--- /dev/null
+++ b/src/extern_type.rs
@@ -0,0 +1,110 @@
+/// A type for which the layout is determined by its C++ definition.
+///
+/// This trait serves the following two related purposes.
+///
+/// <br>
+///
+/// ## Safely unifying occurrences of the same extern type
+///
+/// `ExternType` makes it possible for CXX to safely share a consistent Rust
+/// type across multiple #\[cxx::bridge\] invocations that refer to a common
+/// extern C++ type.
+///
+/// In the following snippet, two #\[cxx::bridge\] invocations in different
+/// files (possibly different crates) both contain function signatures involving
+/// the same C++ type `example::Demo`. If both were written just containing
+/// `type Demo;`, then both macro expansions would produce their own separate
+/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the
+/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo`
+/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two
+/// `Demo`s has been defined as an extern type alias of the other, making them
+/// the same type in Rust. The CXX code generator will use an automatically
+/// generated `ExternType` impl emitted in file1 to statically verify that in
+/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type
+/// `example::Demo` as expected in file2.
+///
+/// ```no_run
+/// // file1.rs
+/// # mod file1 {
+/// #[cxx::bridge(namespace = example)]
+/// pub mod ffi {
+///     extern "C" {
+///         type Demo;
+///
+///         fn create_demo() -> UniquePtr<Demo>;
+///     }
+/// }
+/// # }
+///
+/// // file2.rs
+/// #[cxx::bridge(namespace = example)]
+/// pub mod ffi {
+///     extern "C" {
+///         type Demo = crate::file1::ffi::Demo;
+///
+///         fn take_ref_demo(demo: &Demo);
+///     }
+/// }
+/// #
+/// # fn main() {}
+/// ```
+///
+/// <br><br>
+///
+/// ## Integrating with bindgen-generated types
+///
+/// Handwritten `ExternType` impls make it possible to plug in a data structure
+/// emitted by bindgen as the definition of an opaque C++ type emitted by CXX.
+///
+/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
+/// namespace and type name given in the type id refers to a C++ type that is
+/// equivalent to Rust type that is the `Self` type of the impl.
+///
+/// ```no_run
+/// # const _: &str = stringify! {
+/// mod folly_sys;  // the bindgen-generated bindings
+/// # };
+/// # mod folly_sys {
+/// #     #[repr(transparent)]
+/// #     pub struct StringPiece([usize; 2]);
+/// # }
+///
+/// use cxx::{type_id, ExternType};
+///
+/// unsafe impl ExternType for folly_sys::StringPiece {
+///     type Id = type_id!("folly::StringPiece");
+/// }
+///
+/// #[cxx::bridge(namespace = folly)]
+/// pub mod ffi {
+///     extern "C" {
+///         include!("rust_cxx_bindings.h");
+///
+///         type StringPiece = crate::folly_sys::StringPiece;
+///
+///         fn print_string_piece(s: &StringPiece);
+///     }
+/// }
+///
+/// // Now if we construct a StringPiece or obtain one through one
+/// // of the bindgen-generated signatures, we are able to pass it
+/// // along to ffi::print_string_piece.
+/// #
+/// # fn main() {}
+/// ```
+pub unsafe trait ExternType {
+    /// A type-level representation of the type's C++ namespace and type name.
+    ///
+    /// This will always be defined using `type_id!` in the following form:
+    ///
+    /// ```
+    /// # struct TypeName;
+    /// # unsafe impl cxx::ExternType for TypeName {
+    /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// # }
+    /// ```
+    type Id;
+}
+
+#[doc(hidden)]
+pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
diff --git a/src/lib.rs b/src/lib.rs
index cc0dcf2..fc0e682 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -345,6 +345,7 @@
 
 #![doc(html_root_url = "https://docs.rs/cxx/0.3.0")]
 #![deny(improper_ctypes)]
+#![allow(non_camel_case_types)]
 #![allow(
     clippy::cognitive_complexity,
     clippy::declare_interior_mutable_const,
@@ -369,6 +370,7 @@ mod macros;
 mod cxx_string;
 mod cxx_vector;
 mod exception;
+mod extern_type;
 mod function;
 mod opaque;
 mod result;
@@ -385,13 +387,18 @@ mod symbols;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
+pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
-pub use cxxbridge_macro::bridge;
+pub use cxxbridge_macro::{bridge};
+
+/// For use in impls of the `ExternType` trait. See [`ExternType`].
+pub use cxxbridge_macro::type_id;
 
 // Not public API.
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
+    pub use crate::extern_type::verify_extern_type;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
@@ -402,3 +409,19 @@ pub mod private {
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
+
+macro_rules! chars {
+    ($($ch:ident)*) => {
+        $(
+            #[doc(hidden)]
+            pub enum $ch {}
+        )*
+    };
+}
+
+chars! {
+    _0 _1 _2 _3 _4 _5 _6 _7 _8 _9
+    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
+    a b c d e f g h i j k l m n o p q r s t u v w x y z
+    __ // underscore
+}
diff --git a/syntax/ident.rs b/syntax/ident.rs
index cec424c..7545e92 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -42,6 +42,9 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                     check(cx, &arg.ident);
                 }
             }
+            Api::TypeAlias(alias) => {
+                check(cx, &alias.ident);
+            }
         }
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index fd8db73..3eb6c6e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,7 +20,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Lifetime, LitStr, Token};
+use syn::{Lifetime, LitStr, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::doc::Doc;
@@ -35,6 +35,7 @@ pub enum Api {
     CxxFunction(ExternFn),
     RustType(ExternType),
     RustFunction(ExternFn),
+    TypeAlias(TypeAlias),
 }
 
 pub struct ExternType {
@@ -68,6 +69,14 @@ pub struct ExternFn {
     pub semi_token: Token![;],
 }
 
+pub struct TypeAlias {
+    pub type_token: Token![type],
+    pub ident: Ident,
+    pub eq_token: Token![=],
+    pub ty: RustType,
+    pub semi_token: Token![;],
+}
+
 pub struct Signature {
     pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b794ba9..0640e7f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -2,17 +2,19 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Var, Variant,
+    Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
+use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
 use std::collections::HashSet;
 use std::u32;
+use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat, PathArguments,
-    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
-    Variant as RustVariant,
+    Abi, Attribute, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn,
+    ForeignItemType, GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat,
+    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
+    TypeReference, TypeSlice, Variant as RustVariant,
 };
 
 pub mod kw {
@@ -182,16 +184,21 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
                     Err(err) => cx.push(err),
                 }
             }
+            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(tokens, lang) {
+                Ok(api) => items.push(api),
+                Err(err) => cx.push(err),
+            },
             _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
 
     let mut types = items.iter().filter_map(|item| match item {
-        Api::CxxType(ty) | Api::RustType(ty) => Some(ty),
+        Api::CxxType(ty) | Api::RustType(ty) => Some(&ty.ident),
+        Api::TypeAlias(alias) => Some(&alias.ident),
         _ => None,
     });
     if let (Some(single_type), None) = (types.next(), types.next()) {
-        let single_type = single_type.ident.clone();
+        let single_type = single_type.clone();
         for item in &mut items {
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
@@ -336,6 +343,44 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     }))
 }
 
+fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
+    // type Alias = crate::path::to::Type;
+    fn parse(input: ParseStream) -> Result<TypeAlias> {
+        let attrs = input.call(Attribute::parse_outer)?;
+        let type_token: Token![type] = match input.parse()? {
+            Some(type_token) => type_token,
+            None => {
+                let span = input.cursor().token_stream();
+                return Err(Error::new_spanned(span, "unsupported foreign item"));
+            }
+        };
+        let ident: Ident = input.parse()?;
+        let eq_token: Token![=] = input.parse()?;
+        let ty: RustType = input.parse()?;
+        let semi_token: Token![;] = input.parse()?;
+        attrs::parse_doc(&attrs)?;
+
+        Ok(TypeAlias {
+            type_token,
+            ident,
+            eq_token,
+            ty,
+            semi_token,
+        })
+    }
+
+    let type_alias = parse.parse2(tokens.clone())?;
+    match lang {
+        Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
+        Lang::Rust => {
+            let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
+            let span = quote!(#type_token #semi_token);
+            let msg = "type alias in extern \"Rust\" block is not supported";
+            Err(Error::new_spanned(span, msg))
+        }
+    }
+}
+
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 934c85b..6dd6073 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type, Var,
+    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
+    TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -86,6 +87,14 @@ impl ToTokens for ExternType {
     }
 }
 
+impl ToTokens for TypeAlias {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        // Notional token range for error reporting purposes.
+        self.type_token.to_tokens(tokens);
+        self.ident.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Struct {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
diff --git a/syntax/types.rs b/syntax/types.rs
index 5800513..ba9bc78 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, Struct, Type};
+use crate::syntax::{Api, Derive, Enum, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -12,6 +12,7 @@ pub struct Types<'a> {
     pub enums: Map<Ident, &'a Enum>,
     pub cxx: Set<'a, Ident>,
     pub rust: Set<'a, Ident>,
+    pub aliases: Map<Ident, &'a TypeAlias>,
 }
 
 impl<'a> Types<'a> {
@@ -21,6 +22,7 @@ impl<'a> Types<'a> {
         let mut enums = Map::new();
         let mut cxx = Set::new();
         let mut rust = Set::new();
+        let mut aliases = Map::new();
 
         fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
             all.insert(ty);
@@ -96,6 +98,14 @@ impl<'a> Types<'a> {
                         visit(&mut all, ret);
                     }
                 }
+                Api::TypeAlias(alias) => {
+                    let ident = &alias.ident;
+                    if !type_names.insert(ident) {
+                        duplicate_name(cx, alias, ident);
+                    }
+                    cxx.insert(ident);
+                    aliases.insert(ident.clone(), alias);
+                }
             }
         }
 
@@ -105,6 +115,7 @@ impl<'a> Types<'a> {
             enums,
             cxx,
             rust,
+            aliases,
         }
     }
 
diff --git a/tests/BUCK b/tests/BUCK
index 659223c..41781c8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -6,7 +6,10 @@ rust_test(
 
 rust_library(
     name = "ffi",
-    srcs = ["ffi/lib.rs"],
+    srcs = [
+        "ffi/lib.rs",
+        "ffi/module.rs",
+    ],
     crate = "cxx_test_suite",
     deps = [
         ":impl",
@@ -18,25 +21,33 @@ cxx_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-source",
+        ":gen-lib-source",
+        ":gen-module-source",
     ],
     headers = {
-        "ffi/lib.rs.h": ":gen-header",
+        "ffi/lib.rs.h": ":gen-lib-header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
 
 genrule(
-    name = "gen-header",
+    name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    out = "generated.h",
+    out = "lib.rs.h",
 )
 
 genrule(
-    name = "gen-source",
+    name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    out = "generated.cc",
+    out = "lib.rs.cc",
+)
+
+genrule(
+    name = "gen-module-source",
+    srcs = ["ffi/module.rs"],
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    out = "module.rs.cc",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 65c5b41..e1f1637 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -8,7 +8,10 @@ rust_test(
 
 rust_library(
     name = "cxx_test_suite",
-    srcs = ["ffi/lib.rs"],
+    srcs = [
+        "ffi/lib.rs",
+        "ffi/module.rs",
+    ],
     deps = [
         ":impl",
         "//:cxx",
@@ -19,17 +22,18 @@ cc_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-source",
+        ":gen-lib-source",
+        ":gen-module-source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
-        ":include",
+        ":lib-include",
         "//:core",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
     outs = ["lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -37,15 +41,23 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    outs = ["generated.cc"],
+    outs = ["lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
 
 cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
+    name = "lib-include",
+    hdrs = [":gen-lib-header"],
     include_prefix = "tests/ffi",
 )
+
+genrule(
+    name = "gen-module-source",
+    srcs = ["ffi/module.rs"],
+    outs = ["module.rs.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index b970362..2c96d73 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -3,7 +3,8 @@ fn main() {
         return;
     }
 
-    cxx_build::bridge("lib.rs")
+    let sources = vec!["lib.rs", "module.rs"];
+    cxx_build::bridges(sources)
         .file("tests.cc")
         .flag("-std=c++11")
         .compile("cxx-test-suite");
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e298e88..9457229 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,6 +4,8 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
+pub mod module;
+
 use cxx::{CxxString, UniquePtr};
 use std::fmt::{self, Display};
 
@@ -47,7 +49,6 @@ pub mod ffi {
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
         fn c_take_box(r: Box<R>);
-        fn c_take_unique_ptr(c: UniquePtr<C>);
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
new file mode 100644
index 0000000..77bae06
--- /dev/null
+++ b/tests/ffi/module.rs
@@ -0,0 +1,13 @@
+// Rustfmt mangles the extern type alias.
+// https://github.com/rust-lang/rustfmt/issues/4159
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi {
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        type C = crate::ffi::C;
+
+        fn c_take_unique_ptr(c: UniquePtr<C>);
+    }
+}
diff --git a/tests/test.rs b/tests/test.rs
index b8593c5..ddf8f70 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -89,7 +89,7 @@ fn test_c_take() {
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
-    check!(ffi::c_take_unique_ptr(unique_ptr));
+    check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
     check!(ffi::c_take_rust_string("2020".to_owned()));
diff --git a/tests/ui/type_alias_rust.rs b/tests/ui/type_alias_rust.rs
new file mode 100644
index 0000000..67df489
--- /dev/null
+++ b/tests/ui/type_alias_rust.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        /// Incorrect.
+        type Alias = crate::Type;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/type_alias_rust.stderr b/tests/ui/type_alias_rust.stderr
new file mode 100644
index 0000000..1b08f67
--- /dev/null
+++ b/tests/ui/type_alias_rust.stderr
@@ -0,0 +1,5 @@
+error: type alias in extern "Rust" block is not supported
+ --> $DIR/type_alias_rust.rs:5:9
+  |
+5 |         type Alias = crate::Type;
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/wrong_type_id.rs b/tests/ui/wrong_type_id.rs
new file mode 100644
index 0000000..81a9b3f
--- /dev/null
+++ b/tests/ui/wrong_type_id.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge(namespace = folly)]
+mod here {
+    extern "C" {
+        type StringPiece;
+    }
+}
+
+#[cxx::bridge(namespace = folly)]
+mod there {
+    extern "C" {
+        type ByteRange = crate::here::StringPiece;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
new file mode 100644
index 0000000..5b4f6c6
--- /dev/null
+++ b/tests/ui/wrong_type_id.stderr
@@ -0,0 +1,13 @@
+error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+   --> $DIR/wrong_type_id.rs:11:9
+    |
+11  |         type ByteRange = crate::here::StringPiece;
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
+    |
+   ::: $WORKSPACE/src/extern_type.rs:110:41
+    |
+110 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+    |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+    |
+    = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+               found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`
diff --git a/third-party/BUCK b/third-party/BUCK
index 2de784b..e16bad2 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.18/src/**"]),
+    srcs = glob(["vendor/syn-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 4d8fd9f..45b1163 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.18/src/**"]),
+    srcs = glob(["vendor/syn-1.0.19/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3397192..b1227f9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.18"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
+checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -356,9 +356,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e5696e4fd793743fbcc29943fe965ea3993b6c3d2a6a3a35c6680d926fd3a49"
+checksum = "744665442556a91933cee5e75b0371376eb03498c4d0bfbcebd2a9882b4fb5ef"
 dependencies = [
  "dissimilar",
  "glob",

From 878ab12a155a613e9a2a41304d260fe4fdba7f2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 17:05:03 +0000
Subject: [PATCH 573/2232] Release 0.3.1


---

diff --git a/Cargo.toml b/Cargo.toml
index dd7c18f..09280f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.0" # remember to update html_root_url
+version = "0.3.1" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -12,14 +12,14 @@ readme = "README.md"
 exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.0", path = "macro" }
+cxxbridge-macro = { version = "=0.3.1", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.0", path = "gen/build" }
+cxx-build = { version = "=0.3.1", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.27", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 16aeba3..4f4db9d 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.0"
+version = "0.3.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 92adb89..bb2c72d 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.0"
+version = "0.3.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 8ade852..3b9662b 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.0"
+version = "0.3.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index fc0e682..43540be 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -343,7 +343,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.0")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.1")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b1227f9..e95d00c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.0"
+version = "0.3.1"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.0"
+version = "0.3.1"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.0"
+version = "0.3.1"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.0"
+version = "0.3.1"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -389,9 +389,9 @@ checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 
 [[package]]
 name = "vec_map"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
 [[package]]
 name = "version_check"

From d24563dd24db07bb08b92c22cd8f4c820d5ffc9f Mon Sep 17 00:00:00 2001
From: Christopher Chalmers <c.chalmers@me.com>
Date: May 08 2020 19:39:10 +0000
Subject: [PATCH 574/2232] Add cpp flag to cc


This means that clang++ will be called instead of clang.

---

diff --git a/build.rs b/build.rs
index 1f3b6eb..05d7880 100644
--- a/build.rs
+++ b/build.rs
@@ -1,6 +1,7 @@
 fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
+        .cpp(true)
         .flag("-std=c++11")
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index edbb281..e435019 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,6 +1,7 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
+        .cpp(true)
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
 

From 96c351b5a845bb01f3df528f0ff893ed0377eef7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 20:06:18 +0000
Subject: [PATCH 575/2232] Format with rustfmt 2020-04-14


---

diff --git a/src/lib.rs b/src/lib.rs
index 43540be..2da7a59 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -389,7 +389,7 @@ pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
-pub use cxxbridge_macro::{bridge};
+pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
 pub use cxxbridge_macro::type_id;

From 110df7dc214a1a92c930434be90150cba250b38f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 20:09:56 +0000
Subject: [PATCH 576/2232] Defer to link-cplusplus crate for linking a standard library


---

diff --git a/build.rs b/build.rs
index 05d7880..16837f3 100644
--- a/build.rs
+++ b/build.rs
@@ -2,6 +2,7 @@ fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
         .cpp(true)
+        .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag("-std=c++11")
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index e435019..edbb281 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,7 +1,6 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
-        .cpp(true)
         .flag("-std=c++11")
         .compile("cxxbridge-demo");
 
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 9e8475a..b33e192 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -88,12 +88,16 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
 /// ```
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
     let mut build = paths::cc_build();
+    build.cpp(true);
+    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+
     for path in rust_source_files {
         if let Err(err) = try_generate_bridge(&mut build, path.as_ref()) {
             let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
             process::exit(1);
         }
     }
+
     build
 }
 

From 887c8a2eb1de93737173b9f26fc79788319265fa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 22:55:10 +0000
Subject: [PATCH 577/2232] Merge pull request #192 from cchalmers/cpp-true


Add cpp flag to cc
---

diff --git a/build.rs b/build.rs
index 1f3b6eb..16837f3 100644
--- a/build.rs
+++ b/build.rs
@@ -1,6 +1,8 @@
 fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
+        .cpp(true)
+        .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag("-std=c++11")
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 9e8475a..b33e192 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -88,12 +88,16 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
 /// ```
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
     let mut build = paths::cc_build();
+    build.cpp(true);
+    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+
     for path in rust_source_files {
         if let Err(err) = try_generate_bridge(&mut build, path.as_ref()) {
             let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
             process::exit(1);
         }
     }
+
     build
 }
 

From e2f70fea3e769d4c135ad8808983b9939928b172 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 08 2020 22:57:14 +0000
Subject: [PATCH 578/2232] Release 0.3.2


---

diff --git a/Cargo.toml b/Cargo.toml
index 09280f4..32e5803 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.1" # remember to update html_root_url
+version = "0.3.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -12,14 +12,14 @@ readme = "README.md"
 exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.1", path = "macro" }
+cxxbridge-macro = { version = "=0.3.2", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.1", path = "gen/build" }
+cxx-build = { version = "=0.3.2", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.27", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 4f4db9d..71c6aef 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.1"
+version = "0.3.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index bb2c72d..2ce8ce5 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.1"
+version = "0.3.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 3b9662b..bc3f001 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.1"
+version = "0.3.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 2da7a59..78aba3d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -343,7 +343,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.1")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.2")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index e95d00c..e54c293 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.1"
+version = "0.3.2"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.1"
+version = "0.3.2"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.1"
+version = "0.3.2"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.1"
+version = "0.3.2"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -246,18 +246,18 @@ checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
 
 [[package]]
 name = "serde"
-version = "1.0.106"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399"
+checksum = "eba7550f2cdf88ffc23ab0f1607133486c390a8c0f89b57e589b9654ee15e04d"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.106"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c"
+checksum = "10be45e22e5597d4b88afcc71f9d7bfadcd604bf0c78a3ab4582b8d2b37f39f3"
 dependencies = [
  "proc-macro2",
  "quote",

From 064668a00f5c3965ef52fc405b07745a321b92c8 Mon Sep 17 00:00:00 2001
From: Philip Craig <689193+philipcraig@users.noreply.github.com>
Date: May 09 2020 07:24:12 +0000
Subject: [PATCH 579/2232] fix path to c++ generator example


---

diff --git a/README.md b/README.md
index 1b1611d..04cabd0 100644
--- a/README.md
+++ b/README.md
@@ -120,7 +120,7 @@ generators:
 $ cargo expand --manifest-path demo-rs/Cargo.toml
 
    # run C++ code generator and print to stdout
-$ cargo run --manifest-path cmd/Cargo.toml -- demo-rs/src/main.rs
+$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
 ```
 
 <br>

From 55f4949549cf46046091a40248cc97e37010fbd2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 09 2020 16:56:08 +0000
Subject: [PATCH 580/2232] Merge pull request #193 from philipcraig/fix_readme


fix path to c++ generator example
---

diff --git a/README.md b/README.md
index 1b1611d..04cabd0 100644
--- a/README.md
+++ b/README.md
@@ -120,7 +120,7 @@ generators:
 $ cargo expand --manifest-path demo-rs/Cargo.toml
 
    # run C++ code generator and print to stdout
-$ cargo run --manifest-path cmd/Cargo.toml -- demo-rs/src/main.rs
+$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
 ```
 
 <br>

From 32439dae389e4439c7e8e1d4bd650765c23854e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 09 2020 16:59:40 +0000
Subject: [PATCH 581/2232] Apply PR 193 to rustdoc as well


---

diff --git a/src/lib.rs b/src/lib.rs
index 78aba3d..bbe66f9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -122,7 +122,7 @@
 //! $ cargo expand --manifest-path demo-rs/Cargo.toml
 //!
 //!    # run C++ code generator and print to stdout
-//! $ cargo run --manifest-path cmd/Cargo.toml -- demo-rs/src/main.rs
+//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
 //! ```
 //!
 //! <br>

From 7e14e2e6cbab8d1c556b556983e2a5e2dcbba6cc Mon Sep 17 00:00:00 2001
From: Philip Craig <689193+philipcraig@users.noreply.github.com>
Date: May 09 2020 19:00:49 +0000
Subject: [PATCH 582/2232] avoid MSVC warning via flag_if_supported


---

diff --git a/README.md b/README.md
index 1b1611d..f819636 100644
--- a/README.md
+++ b/README.md
@@ -228,7 +228,7 @@ cxx-build = "0.3"
 fn main() {
     cxx_build::bridge("src/main.rs")  // returns a cc::Build
         .file("../demo-cxx/demo.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/build.rs b/build.rs
index 16837f3..9a071fe 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,7 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index edbb281..e4792c2 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,7 +1,7 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b33e192..14683b6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -16,7 +16,7 @@
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")
 //!         .file("../demo-cxx/demo.cc")
-//!         .flag("-std=c++11")
+//!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
@@ -83,7 +83,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
 /// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
 /// cxx_build::bridges(source_files)
 ///     .file("../demo-cxx/demo.cc")
-///     .flag("-std=c++11")
+///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
diff --git a/src/lib.rs b/src/lib.rs
index 78aba3d..7e6ece4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -233,7 +233,7 @@
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
 //!         .file("../demo-cxx/demo.cc")
-//!         .flag("-std=c++11")
+//!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 2c96d73..f6fa59e 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,6 +6,6 @@ fn main() {
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxx-test-suite");
 }

From 6cadf70b5833f511e3cc902e6ddbe10ab620f447 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 09 2020 19:06:54 +0000
Subject: [PATCH 583/2232] Merge pull request #194 from philipcraig/std_c++11_not_required_on_msvc


avoid MSVC warning via flag_if_supported
---

diff --git a/README.md b/README.md
index 04cabd0..9e397f2 100644
--- a/README.md
+++ b/README.md
@@ -228,7 +228,7 @@ cxx-build = "0.3"
 fn main() {
     cxx_build::bridge("src/main.rs")  // returns a cc::Build
         .file("../demo-cxx/demo.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/build.rs b/build.rs
index 16837f3..9a071fe 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,7 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index edbb281..e4792c2 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,7 +1,7 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b33e192..14683b6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -16,7 +16,7 @@
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")
 //!         .file("../demo-cxx/demo.cc")
-//!         .flag("-std=c++11")
+//!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
@@ -83,7 +83,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
 /// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
 /// cxx_build::bridges(source_files)
 ///     .file("../demo-cxx/demo.cc")
-///     .flag("-std=c++11")
+///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
diff --git a/src/lib.rs b/src/lib.rs
index bbe66f9..3b37c5a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -233,7 +233,7 @@
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
 //!         .file("../demo-cxx/demo.cc")
-//!         .flag("-std=c++11")
+//!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 2c96d73..f6fa59e 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,6 +6,6 @@ fn main() {
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
-        .flag("-std=c++11")
+        .flag_if_supported("-std=c++11")
         .compile("cxx-test-suite");
 }

From e86b9cf2259dab6fe9f61d4efc85ce379c9bea63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 10 2020 21:26:04 +0000
Subject: [PATCH 584/2232] Update derive parsing to produce structured representation


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 6d661ba..798cbee 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -13,7 +13,7 @@ pub(super) fn parse_doc(attrs: &[Attribute]) -> Result<Doc> {
 pub(super) fn parse(
     attrs: &[Attribute],
     doc: &mut Doc,
-    mut derives: Option<&mut Vec<Ident>>,
+    mut derives: Option<&mut Vec<Derive>>,
 ) -> Result<()> {
     for attr in attrs {
         if attr.path.is_ident("doc") {
@@ -37,13 +37,17 @@ fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
     Ok(lit)
 }
 
-fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Ident>> {
+fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
     input
         .parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?
         .into_iter()
-        .map(|path| match path.get_ident() {
-            Some(ident) if Derive::from(ident).is_some() => Ok(ident.clone()),
-            _ => Err(Error::new_spanned(path, "unsupported derive")),
+        .map(|path| {
+            if let Some(ident) = path.get_ident() {
+                if let Some(derive) = Derive::from(ident) {
+                    return Ok(derive);
+                }
+            }
+            Err(Error::new_spanned(path, "unsupported derive"))
         })
         .collect()
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3eb6c6e..9e4cbbc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -46,7 +46,7 @@ pub struct ExternType {
 
 pub struct Struct {
     pub doc: Doc,
-    pub derives: Vec<Ident>,
+    pub derives: Vec<Derive>,
     pub struct_token: Token![struct],
     pub ident: Ident,
     pub brace_token: Brace,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 6dd6073..9a1fee0 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -71,11 +71,7 @@ impl ToTokens for Slice {
 
 impl ToTokens for Derive {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let name = match self {
-            Derive::Clone => "Clone",
-            Derive::Copy => "Copy",
-        };
-        Ident::new(name, Span::call_site()).to_tokens(tokens);
+        Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
     }
 }
 

From b129ea71633fea7f6a969ba428cae755e676ee07 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 10 2020 21:48:30 +0000
Subject: [PATCH 585/2232] Organize how the caller determines which attrs to parse


In preparation for parsing even more attributes, such as `repr`.

---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 798cbee..edb403d 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,27 +1,36 @@
 use crate::syntax::{Derive, Doc};
 use proc_macro2::Ident;
-use syn::parse::{ParseStream, Parser};
+use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
+#[derive(Default)]
+pub struct Parser<'a> {
+    pub doc: Option<&'a mut Doc>,
+    pub derives: Option<&'a mut Vec<Derive>>,
+}
+
 pub(super) fn parse_doc(attrs: &[Attribute]) -> Result<Doc> {
     let mut doc = Doc::new();
-    let derives = None;
-    parse(attrs, &mut doc, derives)?;
+    parse(
+        attrs,
+        Parser {
+            doc: Some(&mut doc),
+            ..Parser::default()
+        },
+    )?;
     Ok(doc)
 }
 
-pub(super) fn parse(
-    attrs: &[Attribute],
-    doc: &mut Doc,
-    mut derives: Option<&mut Vec<Derive>>,
-) -> Result<()> {
+pub(super) fn parse(attrs: &[Attribute], mut parser: Parser) -> Result<()> {
     for attr in attrs {
         if attr.path.is_ident("doc") {
-            let lit = parse_doc_attribute.parse2(attr.tokens.clone())?;
-            doc.push(lit);
-            continue;
+            if let Some(doc) = &mut parser.doc {
+                let lit = parse_doc_attribute.parse2(attr.tokens.clone())?;
+                doc.push(lit);
+                continue;
+            }
         } else if attr.path.is_ident("derive") {
-            if let Some(derives) = &mut derives {
+            if let Some(derives) = &mut parser.derives {
                 derives.extend(attr.parse_args_with(parse_derive_attribute)?);
                 continue;
             }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0640e7f..b5070c7 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -56,7 +56,13 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
 
     let mut doc = Doc::new();
     let mut derives = Vec::new();
-    attrs::parse(&item.attrs, &mut doc, Some(&mut derives))?;
+    attrs::parse(
+        &item.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            derives: Some(&mut derives),
+        },
+    )?;
 
     let fields = match item.fields {
         Fields::Named(fields) => fields,

From 3e6288896061b170d2dfa72d7b009915d1269641 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 10 2020 22:36:01 +0000
Subject: [PATCH 586/2232] Keep items that have attr parse errors


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index edb403d..1cb0657 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::{Derive, Doc};
 use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
@@ -9,35 +10,44 @@ pub struct Parser<'a> {
     pub derives: Option<&'a mut Vec<Derive>>,
 }
 
-pub(super) fn parse_doc(attrs: &[Attribute]) -> Result<Doc> {
+pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
     let mut doc = Doc::new();
     parse(
+        cx,
         attrs,
         Parser {
             doc: Some(&mut doc),
             ..Parser::default()
         },
-    )?;
-    Ok(doc)
+    );
+    doc
 }
 
-pub(super) fn parse(attrs: &[Attribute], mut parser: Parser) -> Result<()> {
+pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
     for attr in attrs {
         if attr.path.is_ident("doc") {
-            if let Some(doc) = &mut parser.doc {
-                let lit = parse_doc_attribute.parse2(attr.tokens.clone())?;
-                doc.push(lit);
-                continue;
+            match parse_doc_attribute.parse2(attr.tokens.clone()) {
+                Ok(lit) => {
+                    if let Some(doc) = &mut parser.doc {
+                        doc.push(lit);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
             }
         } else if attr.path.is_ident("derive") {
-            if let Some(derives) = &mut parser.derives {
-                derives.extend(attr.parse_args_with(parse_derive_attribute)?);
-                continue;
+            match attr.parse_args_with(parse_derive_attribute) {
+                Ok(attr) => {
+                    if let Some(derives) = &mut parser.derives {
+                        derives.extend(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
             }
         }
-        return Err(Error::new_spanned(attr, "unsupported attribute"));
+        return cx.error(attr, "unsupported attribute");
     }
-    Ok(())
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b5070c7..f84ff32 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -25,11 +25,11 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(item) {
+            Item::Struct(item) => match parse_struct(cx, item) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(item) {
+            Item::Enum(item) => match parse_enum(cx, item) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
@@ -41,7 +41,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
     apis
 }
 
-fn parse_struct(item: ItemStruct) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -57,12 +57,13 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     attrs::parse(
+        cx,
         &item.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
         },
-    )?;
+    );
 
     let fields = match item.fields {
         Fields::Named(fields) => fields,
@@ -91,7 +92,7 @@ fn parse_struct(item: ItemStruct) -> Result<Api> {
     }))
 }
 
-fn parse_enum(item: ItemEnum) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -104,7 +105,7 @@ fn parse_enum(item: ItemEnum) -> Result<Api> {
         ));
     }
 
-    let doc = attrs::parse_doc(&item.attrs)?;
+    let doc = attrs::parse_doc(cx, &item.attrs);
 
     let mut variants = Vec::new();
     let mut discriminants = HashSet::new();
@@ -176,11 +177,11 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(foreign, lang) {
+            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang) {
                 Ok(ety) => items.push(ety),
                 Err(err) => cx.push(err),
             },
-            ForeignItem::Fn(foreign) => match parse_extern_fn(foreign, lang) {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -190,7 +191,7 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(tokens, lang) {
+            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(cx, tokens, lang) {
                 Ok(api) => items.push(api),
                 Err(err) => cx.push(err),
             },
@@ -236,8 +237,8 @@ fn parse_lang(abi: Abi) -> Result<Lang> {
     }
 }
 
-fn parse_extern_type(foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
-    let doc = attrs::parse_doc(&foreign_type.attrs)?;
+fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
+    let doc = attrs::parse_doc(cx, &foreign_type.attrs);
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
     let api_type = match lang {
@@ -251,7 +252,7 @@ fn parse_extern_type(foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> 
     }))
 }
 
-fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
+fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -322,7 +323,7 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let doc = attrs::parse_doc(&foreign_fn.attrs)?;
+    let doc = attrs::parse_doc(cx, &foreign_fn.attrs);
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -349,9 +350,9 @@ fn parse_extern_fn(foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
     }))
 }
 
-fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
+fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> Result<Api> {
     // type Alias = crate::path::to::Type;
-    fn parse(input: ParseStream) -> Result<TypeAlias> {
+    let parse = |input: ParseStream| -> Result<TypeAlias> {
         let attrs = input.call(Attribute::parse_outer)?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
@@ -364,7 +365,7 @@ fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        attrs::parse_doc(&attrs)?;
+        attrs::parse_doc(cx, &attrs);
 
         Ok(TypeAlias {
             type_token,
@@ -373,7 +374,7 @@ fn parse_extern_verbatim(tokens: &TokenStream, lang: Lang) -> Result<Api> {
             ty,
             semi_token,
         })
-    }
+    };
 
     let type_alias = parse.parse2(tokens.clone())?;
     match lang {

From c0fad20670d85aad0cd560dce126fd7a52cbece7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 03:16:28 +0000
Subject: [PATCH 587/2232] Add crates.io categories and keywords


---

diff --git a/Cargo.toml b/Cargo.toml
index 32e5803..829eac3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,6 +10,8 @@ repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
 readme = "README.md"
 exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
+keywords = ["ffi"]
+categories = ["development-tools::ffi", "api-bindings"]
 
 [dependencies]
 cxxbridge-macro = { version = "=0.3.2", path = "macro" }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 71c6aef..84ab6fe 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi"]
 
 [dependencies]
 anyhow = "1.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 2ce8ce5..d14dc84 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi"]
 
 [[bin]]
 name = "cxxbridge"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index bc3f001..0dc3038 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -7,6 +7,8 @@ license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
 exclude = ["README.md"]
+keywords = ["ffi"]
+categories = ["development-tools::ffi"]
 
 [lib]
 proc-macro = true

From 64703b42071b90875501abef44e31ee83be48721 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:12:33 +0000
Subject: [PATCH 588/2232] Give Derive enum and impls their own module


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 1cb0657..f48a210 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,6 +1,5 @@
 use crate::syntax::report::Errors;
 use crate::syntax::{Derive, Doc};
-use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
@@ -70,22 +69,3 @@ fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
         })
         .collect()
 }
-
-impl Derive {
-    pub fn from(ident: &Ident) -> Option<Self> {
-        match ident.to_string().as_str() {
-            "Clone" => Some(Derive::Clone),
-            "Copy" => Some(Derive::Copy),
-            _ => None,
-        }
-    }
-}
-
-impl AsRef<str> for Derive {
-    fn as_ref(&self) -> &str {
-        match self {
-            Derive::Clone => "Clone",
-            Derive::Copy => "Copy",
-        }
-    }
-}
diff --git a/syntax/derive.rs b/syntax/derive.rs
new file mode 100644
index 0000000..435aa20
--- /dev/null
+++ b/syntax/derive.rs
@@ -0,0 +1,26 @@
+use proc_macro2::Ident;
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum Derive {
+    Clone,
+    Copy,
+}
+
+impl Derive {
+    pub fn from(ident: &Ident) -> Option<Self> {
+        match ident.to_string().as_str() {
+            "Clone" => Some(Derive::Clone),
+            "Copy" => Some(Derive::Copy),
+            _ => None,
+        }
+    }
+}
+
+impl AsRef<str> for Derive {
+    fn as_ref(&self) -> &str {
+        match self {
+            Derive::Clone => "Clone",
+            Derive::Copy => "Copy",
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9e4cbbc..d21c083 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -3,6 +3,7 @@
 pub mod atom;
 mod attrs;
 pub mod check;
+mod derive;
 mod doc;
 pub mod error;
 pub mod ident;
@@ -23,6 +24,7 @@ use syn::token::{Brace, Bracket, Paren};
 use syn::{Lifetime, LitStr, Token, Type as RustType};
 
 pub use self::atom::Atom;
+pub use self::derive::Derive;
 pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
@@ -145,9 +147,3 @@ pub enum Lang {
     Cxx,
     Rust,
 }
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum Derive {
-    Clone,
-    Copy,
-}

From a4596c4455ab7ddc2386182e25d7b65358c2bd64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:55:45 +0000
Subject: [PATCH 589/2232] Expose Atom str for use in error messages


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index eeea831..5b20c4c 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -44,9 +44,26 @@ impl Atom {
     }
 }
 
-impl PartialEq<Atom> for Ident {
-    fn eq(&self, atom: &Atom) -> bool {
-        Atom::from(self) == Some(*atom)
+impl AsRef<str> for Atom {
+    fn as_ref(&self) -> &str {
+        use self::Atom::*;
+        match self {
+            Bool => "bool",
+            U8 => "u8",
+            U16 => "u16",
+            U32 => "u32",
+            U64 => "u64",
+            Usize => "usize",
+            I8 => "i8",
+            I16 => "i16",
+            I32 => "i32",
+            I64 => "i64",
+            Isize => "isize",
+            F32 => "f32",
+            F64 => "f64",
+            CxxString => "CxxString",
+            RustString => "String",
+        }
     }
 }
 

From 699351bc78c30bfcf1b57da62e6d25fc35b0cdeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:08 +0000
Subject: [PATCH 590/2232] Display for Atom


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index 5b20c4c..a2ff7b7 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -1,5 +1,6 @@
 use crate::syntax::Type;
 use proc_macro2::Ident;
+use std::fmt::{self, Display};
 
 #[derive(Copy, Clone, PartialEq)]
 pub enum Atom {
@@ -44,6 +45,12 @@ impl Atom {
     }
 }
 
+impl Display for Atom {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(self.as_ref())
+    }
+}
+
 impl AsRef<str> for Atom {
     fn as_ref(&self) -> &str {
         use self::Atom::*;

From 17e137fbb3f02a1c41c0124ae53da89ae83d499e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 591/2232] Factor out a discriminant processing library


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
new file mode 100644
index 0000000..2a55468
--- /dev/null
+++ b/syntax/discriminant.rs
@@ -0,0 +1,99 @@
+use proc_macro2::{Literal, Span, TokenStream};
+use quote::ToTokens;
+use std::collections::HashSet;
+use std::fmt::{self, Display};
+use std::str::FromStr;
+use syn::{Error, Expr, Lit, Result};
+
+pub struct DiscriminantSet {
+    values: HashSet<Discriminant>,
+    previous: Option<Discriminant>,
+}
+
+#[derive(Copy, Clone, Hash, Eq, PartialEq)]
+pub struct Discriminant {
+    magnitude: u32,
+}
+
+impl DiscriminantSet {
+    pub fn new() -> Self {
+        DiscriminantSet {
+            values: HashSet::new(),
+            previous: None,
+        }
+    }
+
+    pub fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
+        let discriminant = expr_to_discriminant(expr)?;
+        insert(self, discriminant)
+    }
+
+    pub fn insert_next(&mut self) -> Result<Discriminant> {
+        let discriminant = match self.previous {
+            None => Discriminant::zero(),
+            Some(mut discriminant) => {
+                if discriminant.magnitude == u32::MAX {
+                    let msg = format!("discriminant overflow on value after {}", u32::MAX);
+                    return Err(Error::new(Span::call_site(), msg));
+                }
+                discriminant.magnitude += 1;
+                discriminant
+            }
+        };
+        insert(self, discriminant)
+    }
+}
+
+fn expr_to_discriminant(expr: &Expr) -> Result<Discriminant> {
+    if let Expr::Lit(expr) = expr {
+        if let Lit::Int(lit) = &expr.lit {
+            return lit.base10_parse::<Discriminant>();
+        }
+    }
+    Err(Error::new_spanned(
+        expr,
+        "enums with non-integer literal discriminants are not supported yet",
+    ))
+}
+
+fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discriminant> {
+    if set.values.insert(discriminant) {
+        set.previous = Some(discriminant);
+        Ok(discriminant)
+    } else {
+        let msg = format!("discriminant value `{}` already exists", discriminant);
+        Err(Error::new(Span::call_site(), msg))
+    }
+}
+
+impl Discriminant {
+    fn zero() -> Self {
+        Discriminant { magnitude: 0 }
+    }
+}
+
+impl Display for Discriminant {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.magnitude, f)
+    }
+}
+
+impl ToTokens for Discriminant {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u32_unsuffixed(self.magnitude).to_tokens(tokens);
+    }
+}
+
+impl FromStr for Discriminant {
+    type Err = Error;
+
+    fn from_str(s: &str) -> Result<Self> {
+        match s.parse::<u32>() {
+            Ok(magnitude) => Ok(Discriminant { magnitude }),
+            Err(_) => Err(Error::new(
+                Span::call_site(),
+                "discriminant value outside of supported range",
+            )),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index d21c083..c109229 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -4,6 +4,7 @@ pub mod atom;
 mod attrs;
 pub mod check;
 mod derive;
+mod discriminant;
 mod doc;
 pub mod error;
 pub mod ident;
@@ -17,6 +18,7 @@ pub mod symbol;
 mod tokens;
 pub mod types;
 
+use self::discriminant::Discriminant;
 use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
@@ -106,7 +108,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub ident: Ident,
-    pub discriminant: u32,
+    pub discriminant: Discriminant,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f84ff32..eff14c0 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::discriminant::DiscriminantSet;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
@@ -6,15 +7,12 @@ use crate::syntax::{
 };
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use std::collections::HashSet;
-use std::u32;
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Attribute, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn,
-    ForeignItemType, GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat,
-    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
-    TypeReference, TypeSlice, Variant as RustVariant,
+    Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Pat, PathArguments, Result,
+    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -108,8 +106,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     let doc = attrs::parse_doc(cx, &item.attrs);
 
     let mut variants = Vec::new();
-    let mut discriminants = HashSet::new();
-    let mut prev_discriminant = None;
+    let mut discriminants = DiscriminantSet::new();
     for variant in item.variants {
         match variant.fields {
             Fields::Unit => {}
@@ -120,21 +117,19 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
                 ));
             }
         }
-        if variant.discriminant.is_none() && prev_discriminant == Some(u32::MAX) {
-            let msg = format!("discriminant overflow on value after {}", u32::MAX);
-            return Err(Error::new_spanned(variant, msg));
-        }
-        let discriminant =
-            parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-        if !discriminants.insert(discriminant) {
-            let msg = format!("discriminant value `{}` already exists", discriminant);
-            return Err(Error::new_spanned(variant, msg));
-        }
+        let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
+        let try_discriminant = match &expr {
+            Some(lit) => discriminants.insert(lit),
+            None => discriminants.insert_next(),
+        };
+        let discriminant = match try_discriminant {
+            Ok(discriminant) => discriminant,
+            Err(err) => return Err(Error::new_spanned(variant, err)),
+        };
         variants.push(Variant {
             ident: variant.ident,
             discriminant,
         });
-        prev_discriminant = Some(discriminant);
     }
 
     Ok(Api::Enum(Enum {
@@ -146,28 +141,6 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     }))
 }
 
-fn parse_discriminant(variant: &RustVariant) -> Result<Option<u32>> {
-    match &variant.discriminant {
-        None => Ok(None),
-        Some((
-            _,
-            Expr::Lit(ExprLit {
-                lit: Lit::Int(n), ..
-            }),
-        )) => match n.base10_parse() {
-            Ok(val) => Ok(Some(val)),
-            Err(_) => Err(Error::new_spanned(
-                variant,
-                "cannot parse enum discriminant as an integer",
-            )),
-        },
-        _ => Err(Error::new_spanned(
-            variant,
-            "enums with non-integer literal discriminants are not supported yet",
-        )),
-    }
-}
-
 fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
     let lang = match parse_lang(foreign_mod.abi) {
         Ok(lang) => lang,

From 69c7960cb2d5e9a3daa3dfa535c8017da53b801a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 592/2232] Parse negative discriminants


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 2a55468..06a6d1b 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -3,7 +3,7 @@ use quote::ToTokens;
 use std::collections::HashSet;
 use std::fmt::{self, Display};
 use std::str::FromStr;
-use syn::{Error, Expr, Lit, Result};
+use syn::{Error, Expr, Lit, Result, Token, UnOp};
 
 pub struct DiscriminantSet {
     values: HashSet<Discriminant>,
@@ -12,6 +12,7 @@ pub struct DiscriminantSet {
 
 #[derive(Copy, Clone, Hash, Eq, PartialEq)]
 pub struct Discriminant {
+    negative: bool,
     magnitude: u32,
 }
 
@@ -31,6 +32,13 @@ impl DiscriminantSet {
     pub fn insert_next(&mut self) -> Result<Discriminant> {
         let discriminant = match self.previous {
             None => Discriminant::zero(),
+            Some(mut discriminant) if discriminant.negative => {
+                discriminant.magnitude -= 1;
+                if discriminant.magnitude == 0 {
+                    discriminant.negative = false;
+                }
+                discriminant
+            }
             Some(mut discriminant) => {
                 if discriminant.magnitude == u32::MAX {
                     let msg = format!("discriminant overflow on value after {}", u32::MAX);
@@ -45,10 +53,20 @@ impl DiscriminantSet {
 }
 
 fn expr_to_discriminant(expr: &Expr) -> Result<Discriminant> {
-    if let Expr::Lit(expr) = expr {
-        if let Lit::Int(lit) = &expr.lit {
-            return lit.base10_parse::<Discriminant>();
+    match expr {
+        Expr::Lit(expr) => {
+            if let Lit::Int(lit) = &expr.lit {
+                return lit.base10_parse::<Discriminant>();
+            }
+        }
+        Expr::Unary(unary) => {
+            if let UnOp::Neg(_) = unary.op {
+                let mut discriminant = expr_to_discriminant(&unary.expr)?;
+                discriminant.negative ^= true;
+                return Ok(discriminant);
+            }
         }
+        _ => {}
     }
     Err(Error::new_spanned(
         expr,
@@ -68,18 +86,27 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
 
 impl Discriminant {
     fn zero() -> Self {
-        Discriminant { magnitude: 0 }
+        Discriminant {
+            negative: false,
+            magnitude: 0,
+        }
     }
 }
 
 impl Display for Discriminant {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.negative {
+            f.write_str("-")?;
+        }
         Display::fmt(&self.magnitude, f)
     }
 }
 
 impl ToTokens for Discriminant {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        if self.negative {
+            Token![-](Span::call_site()).to_tokens(tokens);
+        }
         Literal::u32_unsuffixed(self.magnitude).to_tokens(tokens);
     }
 }
@@ -87,9 +114,16 @@ impl ToTokens for Discriminant {
 impl FromStr for Discriminant {
     type Err = Error;
 
-    fn from_str(s: &str) -> Result<Self> {
+    fn from_str(mut s: &str) -> Result<Self> {
+        let negative = s.starts_with('-');
+        if negative {
+            s = &s[1..];
+        }
         match s.parse::<u32>() {
-            Ok(magnitude) => Ok(Discriminant { magnitude }),
+            Ok(magnitude) => Ok(Discriminant {
+                negative,
+                magnitude,
+            }),
             Err(_) => Err(Error::new(
                 Span::call_site(),
                 "discriminant value outside of supported range",

From 2b8bf6d262ef6baacd0ededee1b28e7af8266d44 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 593/2232] Preserve the original discriminant Expr


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index c109229..e1402a0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -23,7 +23,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Lifetime, LitStr, Token, Type as RustType};
+use syn::{Expr, Lifetime, LitStr, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -109,6 +109,7 @@ pub struct Receiver {
 pub struct Variant {
     pub ident: Ident,
     pub discriminant: Discriminant,
+    pub expr: Option<Expr>,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index eff14c0..3ca63ab 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -126,9 +126,11 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
             Ok(discriminant) => discriminant,
             Err(err) => return Err(Error::new_spanned(variant, err)),
         };
+        let expr = variant.discriminant.map(|(_, expr)| expr);
         variants.push(Variant {
             ident: variant.ident,
             discriminant,
+            expr,
         });
     }
 

From 9bcb4c6d0b48553dbe56b891b49b25cc8f53d0ec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 594/2232] Extract integer suffix of discriminants as the repr


---

diff --git a/syntax/atom.rs b/syntax/atom.rs
index a2ff7b7..6e5fa88 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -23,8 +23,12 @@ pub enum Atom {
 
 impl Atom {
     pub fn from(ident: &Ident) -> Option<Self> {
+        Self::from_str(ident.to_string().as_str())
+    }
+
+    pub fn from_str(s: &str) -> Option<Self> {
         use self::Atom::*;
-        match ident.to_string().as_str() {
+        match s {
             "bool" => Some(Bool),
             "u8" => Some(U8),
             "u16" => Some(U16),
diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 06a6d1b..7293824 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -1,3 +1,4 @@
+use crate::syntax::Atom::{self, *};
 use proc_macro2::{Literal, Span, TokenStream};
 use quote::ToTokens;
 use std::collections::HashSet;
@@ -6,6 +7,7 @@ use std::str::FromStr;
 use syn::{Error, Expr, Lit, Result, Token, UnOp};
 
 pub struct DiscriminantSet {
+    repr: Option<Atom>,
     values: HashSet<Discriminant>,
     previous: Option<Discriminant>,
 }
@@ -19,13 +21,15 @@ pub struct Discriminant {
 impl DiscriminantSet {
     pub fn new() -> Self {
         DiscriminantSet {
+            repr: None,
             values: HashSet::new(),
             previous: None,
         }
     }
 
     pub fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
-        let discriminant = expr_to_discriminant(expr)?;
+        let (discriminant, repr) = expr_to_discriminant(expr)?;
+        self.repr = self.repr.or(repr);
         insert(self, discriminant)
     }
 
@@ -52,18 +56,20 @@ impl DiscriminantSet {
     }
 }
 
-fn expr_to_discriminant(expr: &Expr) -> Result<Discriminant> {
+fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
     match expr {
         Expr::Lit(expr) => {
             if let Lit::Int(lit) = &expr.lit {
-                return lit.base10_parse::<Discriminant>();
+                let discriminant = lit.base10_parse::<Discriminant>()?;
+                let repr = parse_int_suffix(lit.suffix())?;
+                return Ok((discriminant, repr));
             }
         }
         Expr::Unary(unary) => {
             if let UnOp::Neg(_) = unary.op {
-                let mut discriminant = expr_to_discriminant(&unary.expr)?;
+                let (mut discriminant, repr) = expr_to_discriminant(&unary.expr)?;
                 discriminant.negative ^= true;
-                return Ok(discriminant);
+                return Ok((discriminant, repr));
             }
         }
         _ => {}
@@ -131,3 +137,17 @@ impl FromStr for Discriminant {
         }
     }
 }
+
+fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
+    if suffix.is_empty() {
+        return Ok(None);
+    }
+    if let Some(atom) = Atom::from_str(suffix) {
+        match atom {
+            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(Some(atom)),
+            _ => {}
+        }
+    }
+    let msg = format!("unrecognized integer suffix: `{}`", suffix);
+    Err(Error::new(Span::call_site(), msg))
+}

From f1715fa9943c0909780fc3eb240767e2c437168d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 595/2232] Add const bound data for various discriminant reprs


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 7293824..e14c6a0 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -91,12 +91,31 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
 }
 
 impl Discriminant {
-    fn zero() -> Self {
+    const fn zero() -> Self {
         Discriminant {
             negative: false,
             magnitude: 0,
         }
     }
+
+    const fn pos(u: u32) -> Self {
+        Discriminant {
+            negative: false,
+            magnitude: u,
+        }
+    }
+
+    const fn neg(i: i32) -> Self {
+        Discriminant {
+            negative: i < 0,
+            // This is `i.abs() as u32` but without overflow on MIN. Uses the
+            // fact that MIN.wrapping_abs() wraps back to MIN whose binary
+            // representation is 1<<31, and thus the `as u32` conversion
+            // produces 1<<31 too which happens to be the correct unsigned
+            // magnitude.
+            magnitude: i.wrapping_abs() as u32,
+        }
+    }
 }
 
 impl Display for Discriminant {
@@ -151,3 +170,42 @@ fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
     let msg = format!("unrecognized integer suffix: `{}`", suffix);
     Err(Error::new(Span::call_site(), msg))
 }
+
+struct Bounds {
+    repr: Atom,
+    min: Discriminant,
+    max: Discriminant,
+}
+
+const BOUNDS: [Bounds; 6] = [
+    Bounds {
+        repr: U8,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(u8::MAX as u32),
+    },
+    Bounds {
+        repr: I8,
+        min: Discriminant::neg(i8::MIN as i32),
+        max: Discriminant::pos(i8::MAX as u32),
+    },
+    Bounds {
+        repr: U16,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(u16::MAX as u32),
+    },
+    Bounds {
+        repr: I16,
+        min: Discriminant::neg(i16::MIN as i32),
+        max: Discriminant::pos(i16::MAX as u32),
+    },
+    Bounds {
+        repr: U32,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(u32::MAX),
+    },
+    Bounds {
+        repr: I32,
+        min: Discriminant::neg(i32::MIN),
+        max: Discriminant::pos(i32::MAX as u32),
+    },
+];

From e2e303f7f2bbef6366c4b55431ea5ae1f7641d4e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:32 +0000
Subject: [PATCH 596/2232] Infer enum repr based on discriminant range


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index e14c6a0..388a117 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -1,18 +1,19 @@
 use crate::syntax::Atom::{self, *};
 use proc_macro2::{Literal, Span, TokenStream};
 use quote::ToTokens;
-use std::collections::HashSet;
+use std::cmp::Ordering;
+use std::collections::BTreeSet;
 use std::fmt::{self, Display};
 use std::str::FromStr;
 use syn::{Error, Expr, Lit, Result, Token, UnOp};
 
 pub struct DiscriminantSet {
     repr: Option<Atom>,
-    values: HashSet<Discriminant>,
+    values: BTreeSet<Discriminant>,
     previous: Option<Discriminant>,
 }
 
-#[derive(Copy, Clone, Hash, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Discriminant {
     negative: bool,
     magnitude: u32,
@@ -22,7 +23,7 @@ impl DiscriminantSet {
     pub fn new() -> Self {
         DiscriminantSet {
             repr: None,
-            values: HashSet::new(),
+            values: BTreeSet::new(),
             previous: None,
         }
     }
@@ -54,6 +55,24 @@ impl DiscriminantSet {
         };
         insert(self, discriminant)
     }
+
+    pub fn inferred_repr(&self) -> Result<Atom> {
+        if let Some(repr) = self.repr {
+            return Ok(repr);
+        }
+        if self.values.is_empty() {
+            return Ok(U8);
+        }
+        let min = *self.values.iter().next().unwrap();
+        let max = *self.values.iter().next_back().unwrap();
+        for bounds in &BOUNDS {
+            if bounds.min <= min && max <= bounds.max {
+                return Ok(bounds.repr);
+            }
+        }
+        let msg = "these discriminant values do not fit in any supported enum repr type";
+        Err(Error::new(Span::call_site(), msg))
+    }
 }
 
 fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
@@ -157,6 +176,23 @@ impl FromStr for Discriminant {
     }
 }
 
+impl Ord for Discriminant {
+    fn cmp(&self, other: &Self) -> Ordering {
+        match (self.negative, other.negative) {
+            (true, true) => self.magnitude.cmp(&other.magnitude).reverse(),
+            (true, false) => Ordering::Less, // negative < positive
+            (false, true) => Ordering::Greater, // positive > negative
+            (false, false) => self.magnitude.cmp(&other.magnitude),
+        }
+    }
+}
+
+impl PartialOrd for Discriminant {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
 fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
     if suffix.is_empty() {
         return Ok(None);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e1402a0..4702a69 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -63,6 +63,7 @@ pub struct Enum {
     pub ident: Ident,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
+    pub repr: Atom,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3ca63ab..1525fbc 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,7 +6,7 @@ use crate::syntax::{
     Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
+use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
@@ -134,12 +134,24 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         });
     }
 
+    let enum_token = item.enum_token;
+    let brace_token = item.brace_token;
+
+    let repr = match discriminants.inferred_repr() {
+        Ok(repr) => repr,
+        Err(err) => {
+            let span = quote_spanned!(brace_token.span=> #enum_token {});
+            return Err(Error::new_spanned(span, err));
+        }
+    };
+
     Ok(Api::Enum(Enum {
         doc,
-        enum_token: item.enum_token,
+        enum_token,
         ident: item.ident,
-        brace_token: item.brace_token,
+        brace_token,
         variants,
+        repr,
     }))
 }
 

From 0435a818428856aa8987cbd8702fbc60a365b9a2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:33 +0000
Subject: [PATCH 597/2232] Recover from some enum parsing errors


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1525fbc..ab5dcc1 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -111,10 +111,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         match variant.fields {
             Fields::Unit => {}
             _ => {
-                return Err(Error::new_spanned(
-                    variant,
-                    "enums with data are not supported yet",
-                ));
+                cx.error(variant, "enums with data are not supported yet");
+                break;
             }
         }
         let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
@@ -124,7 +122,10 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         };
         let discriminant = match try_discriminant {
             Ok(discriminant) => discriminant,
-            Err(err) => return Err(Error::new_spanned(variant, err)),
+            Err(err) => {
+                cx.error(variant, err);
+                break;
+            }
         };
         let expr = variant.discriminant.map(|(_, expr)| expr);
         variants.push(Variant {
@@ -137,13 +138,15 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
-    let repr = match discriminants.inferred_repr() {
-        Ok(repr) => repr,
+    let mut repr = U8;
+    match discriminants.inferred_repr() {
+        Ok(inferred) => repr = inferred,
         Err(err) => {
             let span = quote_spanned!(brace_token.span=> #enum_token {});
-            return Err(Error::new_spanned(span, err));
+            cx.error(span, err);
+            variants.clear();
         }
-    };
+    }
 
     Ok(Api::Enum(Enum {
         doc,

From ddf69e291bc821ebd252d106e223abd9fe069415 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:57:33 +0000
Subject: [PATCH 598/2232] Parse repr attribute on enums


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index f48a210..16541a3 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,5 +1,7 @@
 use crate::syntax::report::Errors;
+use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
+use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
@@ -7,6 +9,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token};
 pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,
     pub derives: Option<&'a mut Vec<Derive>>,
+    pub repr: Option<&'a mut Option<Atom>>,
 }
 
 pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
@@ -44,6 +47,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("repr") {
+            match attr.parse_args_with(parse_repr_attribute) {
+                Ok(attr) => {
+                    if let Some(repr) = &mut parser.repr {
+                        **repr = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -69,3 +82,18 @@ fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
         })
         .collect()
 }
+
+fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
+    let begin = input.cursor();
+    let ident: Ident = input.parse()?;
+    if let Some(atom) = Atom::from(&ident) {
+        match atom {
+            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(atom),
+            _ => {}
+        }
+    }
+    Err(Error::new_spanned(
+        begin.token_stream(),
+        "unrecognized repr",
+    ))
+}
diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 388a117..c65b3f4 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -20,9 +20,9 @@ pub struct Discriminant {
 }
 
 impl DiscriminantSet {
-    pub fn new() -> Self {
+    pub fn new(repr: Option<Atom>) -> Self {
         DiscriminantSet {
-            repr: None,
+            repr,
             values: BTreeSet::new(),
             previous: None,
         }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index ab5dcc1..a11a5c8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -60,6 +60,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
+            ..Default::default()
         },
     );
 
@@ -103,10 +104,20 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         ));
     }
 
-    let doc = attrs::parse_doc(cx, &item.attrs);
+    let mut doc = Doc::new();
+    let mut repr = None;
+    attrs::parse(
+        cx,
+        &item.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            repr: Some(&mut repr),
+            ..Default::default()
+        },
+    );
 
     let mut variants = Vec::new();
-    let mut discriminants = DiscriminantSet::new();
+    let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
         match variant.fields {
             Fields::Unit => {}

From 5966f7b3f6a43a19f62b0b26759ec3bf75bb60dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 05:59:56 +0000
Subject: [PATCH 599/2232] Detect out of bounds when inserting discriminant


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index c65b3f4..4caa42b 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -100,6 +100,21 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
 }
 
 fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discriminant> {
+    if let Some(expected_repr) = set.repr {
+        for bounds in &BOUNDS {
+            if bounds.repr != expected_repr {
+                continue;
+            }
+            if bounds.min <= discriminant && discriminant <= bounds.max {
+                break;
+            }
+            let msg = format!(
+                "discriminant value `{}` is outside the limits of {}",
+                discriminant, expected_repr,
+            );
+            return Err(Error::new(Span::call_site(), msg));
+        }
+    }
     if set.values.insert(discriminant) {
         set.previous = Some(discriminant);
         Ok(discriminant)

From 94cce00fddbc7dd5617872730ae8eb1d2fbdfaf6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:19:39 +0000
Subject: [PATCH 600/2232] Detect mismatched suffix on discriminant values


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 4caa42b..d683eef 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -30,7 +30,14 @@ impl DiscriminantSet {
 
     pub fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
         let (discriminant, repr) = expr_to_discriminant(expr)?;
-        self.repr = self.repr.or(repr);
+        match (self.repr, repr) {
+            (None, _) => self.repr = repr,
+            (Some(prev), Some(repr)) if prev != repr => {
+                let msg = format!("expected {}, found {}", prev, repr);
+                return Err(Error::new(Span::call_site(), msg));
+            }
+            _ => {}
+        }
         insert(self, discriminant)
     }
 

From f2d584101dd02845e4fa349b6c21e512e782478e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:23:37 +0000
Subject: [PATCH 601/2232] Expand maximum recognized discriminant to 64 bits


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index d683eef..7ce18ff 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -16,7 +16,7 @@ pub struct DiscriminantSet {
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Discriminant {
     negative: bool,
-    magnitude: u32,
+    magnitude: u64,
 }
 
 impl DiscriminantSet {
@@ -52,8 +52,8 @@ impl DiscriminantSet {
                 discriminant
             }
             Some(mut discriminant) => {
-                if discriminant.magnitude == u32::MAX {
-                    let msg = format!("discriminant overflow on value after {}", u32::MAX);
+                if discriminant.magnitude == u64::MAX {
+                    let msg = format!("discriminant overflow on value after {}", u64::MAX);
                     return Err(Error::new(Span::call_site(), msg));
                 }
                 discriminant.magnitude += 1;
@@ -139,22 +139,22 @@ impl Discriminant {
         }
     }
 
-    const fn pos(u: u32) -> Self {
+    const fn pos(u: u64) -> Self {
         Discriminant {
             negative: false,
             magnitude: u,
         }
     }
 
-    const fn neg(i: i32) -> Self {
+    const fn neg(i: i64) -> Self {
         Discriminant {
             negative: i < 0,
-            // This is `i.abs() as u32` but without overflow on MIN. Uses the
+            // This is `i.abs() as u64` but without overflow on MIN. Uses the
             // fact that MIN.wrapping_abs() wraps back to MIN whose binary
-            // representation is 1<<31, and thus the `as u32` conversion
-            // produces 1<<31 too which happens to be the correct unsigned
+            // representation is 1<<63, and thus the `as u64` conversion
+            // produces 1<<63 too which happens to be the correct unsigned
             // magnitude.
-            magnitude: i.wrapping_abs() as u32,
+            magnitude: i.wrapping_abs() as u64,
         }
     }
 }
@@ -173,7 +173,7 @@ impl ToTokens for Discriminant {
         if self.negative {
             Token![-](Span::call_site()).to_tokens(tokens);
         }
-        Literal::u32_unsuffixed(self.magnitude).to_tokens(tokens);
+        Literal::u64_unsuffixed(self.magnitude).to_tokens(tokens);
     }
 }
 
@@ -185,7 +185,7 @@ impl FromStr for Discriminant {
         if negative {
             s = &s[1..];
         }
-        match s.parse::<u32>() {
+        match s.parse::<u64>() {
             Ok(magnitude) => Ok(Discriminant {
                 negative,
                 magnitude,
@@ -235,35 +235,45 @@ struct Bounds {
     max: Discriminant,
 }
 
-const BOUNDS: [Bounds; 6] = [
+const BOUNDS: [Bounds; 8] = [
     Bounds {
         repr: U8,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u8::MAX as u32),
+        max: Discriminant::pos(u8::MAX as u64),
     },
     Bounds {
         repr: I8,
-        min: Discriminant::neg(i8::MIN as i32),
-        max: Discriminant::pos(i8::MAX as u32),
+        min: Discriminant::neg(i8::MIN as i64),
+        max: Discriminant::pos(i8::MAX as u64),
     },
     Bounds {
         repr: U16,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u16::MAX as u32),
+        max: Discriminant::pos(u16::MAX as u64),
     },
     Bounds {
         repr: I16,
-        min: Discriminant::neg(i16::MIN as i32),
-        max: Discriminant::pos(i16::MAX as u32),
+        min: Discriminant::neg(i16::MIN as i64),
+        max: Discriminant::pos(i16::MAX as u64),
     },
     Bounds {
         repr: U32,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u32::MAX),
+        max: Discriminant::pos(u32::MAX as u64),
     },
     Bounds {
         repr: I32,
-        min: Discriminant::neg(i32::MIN),
-        max: Discriminant::pos(i32::MAX as u32),
+        min: Discriminant::neg(i32::MIN as i64),
+        max: Discriminant::pos(i32::MAX as u64),
+    },
+    Bounds {
+        repr: U64,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(u64::MAX),
+    },
+    Bounds {
+        repr: I64,
+        min: Discriminant::neg(i64::MIN),
+        max: Discriminant::pos(i64::MAX as u64),
     },
 ];
diff --git a/tests/ui/enum_overflows.rs b/tests/ui/enum_overflows.rs
index 3f351f0..29de1a0 100644
--- a/tests/ui/enum_overflows.rs
+++ b/tests/ui/enum_overflows.rs
@@ -1,14 +1,14 @@
 #[cxx::bridge]
 mod ffi {
     enum Good1 {
-        A = 0xffffffff,
+        A = 0xFFFF_FFFF_FFFF_FFFF,
     }
     enum Good2 {
-        B = 0xffffffff,
+        B = 0xFFFF_FFFF_FFFF_FFFF,
         C = 2020,
     }
     enum Bad {
-        D = 0xfffffffe,
+        D = 0xFFFF_FFFF_FFFF_FFFE,
         E,
         F,
     }
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index db92f7f..ed58b61 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,4 +1,4 @@
-error: discriminant overflow on value after 4294967295
+error: discriminant overflow on value after 18446744073709551615
   --> $DIR/enum_overflows.rs:13:9
    |
 13 |         F,

From f85431239d8b81ab34f4d1da0056324df22dbfea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:28:04 +0000
Subject: [PATCH 602/2232] Test discriminant outside of the repr's bounds


---

diff --git a/tests/ui/enum_out_of_bounds.rs b/tests/ui/enum_out_of_bounds.rs
new file mode 100644
index 0000000..1aec5f0
--- /dev/null
+++ b/tests/ui/enum_out_of_bounds.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    #[repr(u32)]
+    enum Bad {
+        A = 0xFFFF_FFFF_FFFF_FFFF,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_out_of_bounds.stderr b/tests/ui/enum_out_of_bounds.stderr
new file mode 100644
index 0000000..f437ea1
--- /dev/null
+++ b/tests/ui/enum_out_of_bounds.stderr
@@ -0,0 +1,5 @@
+error: discriminant value `18446744073709551615` is outside the limits of u32
+ --> $DIR/enum_out_of_bounds.rs:5:9
+  |
+5 |         A = 0xFFFF_FFFF_FFFF_FFFF,
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^

From b24f52e2892997dd07aff505625ed146c6e746cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:29:12 +0000
Subject: [PATCH 603/2232] Test inconsistent suffix on enum discriminants


---

diff --git a/tests/ui/enum_inconsistent.rs b/tests/ui/enum_inconsistent.rs
new file mode 100644
index 0000000..cd5ffa5
--- /dev/null
+++ b/tests/ui/enum_inconsistent.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    enum Bad {
+        A = 1u16,
+        B = 2i64,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_inconsistent.stderr b/tests/ui/enum_inconsistent.stderr
new file mode 100644
index 0000000..c5b427a
--- /dev/null
+++ b/tests/ui/enum_inconsistent.stderr
@@ -0,0 +1,5 @@
+error: expected u16, found i64
+ --> $DIR/enum_inconsistent.rs:5:9
+  |
+5 |         B = 2i64,
+  |         ^^^^^^^^

From 560661abe557f21c087223325ab0488d806c0717 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:32:31 +0000
Subject: [PATCH 604/2232] Test unsatisfiable discriminant range


---

diff --git a/tests/ui/enum_unsatisfiable.rs b/tests/ui/enum_unsatisfiable.rs
new file mode 100644
index 0000000..6191287
--- /dev/null
+++ b/tests/ui/enum_unsatisfiable.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    enum Bad {
+        A = -0xFFFF_FFFF_FFFF_FFFF,
+        B = 0xFFFF_FFFF_FFFF_FFFF,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_unsatisfiable.stderr b/tests/ui/enum_unsatisfiable.stderr
new file mode 100644
index 0000000..99852ca
--- /dev/null
+++ b/tests/ui/enum_unsatisfiable.stderr
@@ -0,0 +1,8 @@
+error: these discriminant values do not fit in any supported enum repr type
+ --> $DIR/enum_unsatisfiable.rs:3:5
+  |
+3 | /     enum Bad {
+4 | |         A = -0xFFFF_FFFF_FFFF_FFFF,
+5 | |         B = 0xFFFF_FFFF_FFFF_FFFF,
+6 | |     }
+  | |_____^

From c605e6fa610c3ed08799aef11d08a3d4361433c4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:37:12 +0000
Subject: [PATCH 605/2232] Respect inferred enum repr in Rust code generator


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fc129c6..f28d955 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -143,6 +143,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
+    let repr = enm.repr;
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -155,7 +156,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         #[derive(Copy, Clone, PartialEq, Eq)]
         #[repr(transparent)]
         pub struct #ident {
-            pub repr: u32,
+            pub repr: #repr,
         }
 
         #[allow(non_upper_case_globals)]
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 9a1fee0..4ed264a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
+    Atom, Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
     TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -75,6 +75,12 @@ impl ToTokens for Derive {
     }
 }
 
+impl ToTokens for Atom {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
+    }
+}
+
 impl ToTokens for ExternType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 93a8957..a5a0215 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A { repr: 2u32..=std::u32::MAX }` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=std::u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A { repr: 2u32..=std::u32::MAX }` not covered
+   |           ^ pattern `A { repr: 2u8..=std::u8::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`

From f6a89f2813dda6b21db9726dce07338b2ccddfbf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:45:51 +0000
Subject: [PATCH 606/2232] Respect inferred enum repr in C++ code generator


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8f54bd7..0849d90 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -365,7 +365,9 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "enum class {} : uint32_t {{", enm.ident);
+    write!(out, "enum class {} : ", enm.ident);
+    write_atom(out, enm.repr);
+    writeln!(out, " {{");
     for variant in &enm.variants {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
@@ -373,16 +375,15 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {
-    writeln!(
-        out,
-        "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
-        enm.ident
-    );
+    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident);
+    write_atom(out, enm.repr);
+    writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
+        write!(out, "static_assert(static_cast<");
+        write_atom(out, enm.repr);
         writeln!(
             out,
-            "static_assert(static_cast<uint32_t>({}::{}) == {},
-              \"disagrees with the value in #[cxx::bridge]\");",
+            ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
             enm.ident, variant.ident, variant.discriminant,
         );
     }
@@ -849,21 +850,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
+            Some(atom) => write_atom(out, atom),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
@@ -922,6 +909,26 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+fn write_atom(out: &mut OutFile, atom: Atom) {
+    match atom {
+        Bool => write!(out, "bool"),
+        U8 => write!(out, "uint8_t"),
+        U16 => write!(out, "uint16_t"),
+        U32 => write!(out, "uint32_t"),
+        U64 => write!(out, "uint64_t"),
+        Usize => write!(out, "size_t"),
+        I8 => write!(out, "int8_t"),
+        I16 => write!(out, "int16_t"),
+        I32 => write!(out, "int32_t"),
+        I64 => write!(out, "int64_t"),
+        Isize => write!(out, "::rust::isize"),
+        F32 => write!(out, "float"),
+        F64 => write!(out, "double"),
+        CxxString => write!(out, "::std::string"),
+        RustString => write!(out, "::rust::String"),
+    }
+}
+
 fn write_type_space(out: &mut OutFile, ty: &Type) {
     write_type(out, ty);
     write_space_after_type(out, ty);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9457229..d4e96fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -44,7 +44,7 @@ pub mod ffi {
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
-        fn c_return_enum(n: u32) -> Enum;
+        fn c_return_enum(n: u16) -> Enum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -89,6 +89,7 @@ pub mod ffi {
         type COwnedEnum;
     }
 
+    #[repr(u32)]
     enum COwnedEnum {
         CVal1,
         CVal2,
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 21637d8..af7a4a0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -107,10 +107,10 @@ size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
 
-Enum c_return_enum(uint32_t n) {
-  if (n <= static_cast<uint32_t>(Enum::AVal)) {
+Enum c_return_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(Enum::AVal)) {
     return Enum::AVal;
-  } else if (n <= static_cast<uint32_t>(Enum::BVal)) {
+  } else if (n <= static_cast<uint16_t>(Enum::BVal)) {
     return Enum::BVal;
   } else {
     return Enum::CVal;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 795b4a9..1173a0a 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -7,7 +7,7 @@ namespace tests {
 
 struct R;
 struct Shared;
-enum class Enum : uint32_t;
+enum class Enum : uint16_t;
 
 class C {
 public:
@@ -46,7 +46,7 @@ rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
-Enum c_return_enum(uint32_t n);
+Enum c_return_enum(uint16_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);

From 17451dea3423eccb6462a71f500d40a7d15d34c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 06:49:12 +0000
Subject: [PATCH 607/2232] Restore rust 1.42 compatibility


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 7ce18ff..67fa14d 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -5,6 +5,7 @@ use std::cmp::Ordering;
 use std::collections::BTreeSet;
 use std::fmt::{self, Display};
 use std::str::FromStr;
+use std::u64;
 use syn::{Error, Expr, Lit, Result, Token, UnOp};
 
 pub struct DiscriminantSet {
@@ -239,41 +240,41 @@ const BOUNDS: [Bounds; 8] = [
     Bounds {
         repr: U8,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u8::MAX as u64),
+        max: Discriminant::pos(std::u8::MAX as u64),
     },
     Bounds {
         repr: I8,
-        min: Discriminant::neg(i8::MIN as i64),
-        max: Discriminant::pos(i8::MAX as u64),
+        min: Discriminant::neg(std::i8::MIN as i64),
+        max: Discriminant::pos(std::i8::MAX as u64),
     },
     Bounds {
         repr: U16,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u16::MAX as u64),
+        max: Discriminant::pos(std::u16::MAX as u64),
     },
     Bounds {
         repr: I16,
-        min: Discriminant::neg(i16::MIN as i64),
-        max: Discriminant::pos(i16::MAX as u64),
+        min: Discriminant::neg(std::i16::MIN as i64),
+        max: Discriminant::pos(std::i16::MAX as u64),
     },
     Bounds {
         repr: U32,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u32::MAX as u64),
+        max: Discriminant::pos(std::u32::MAX as u64),
     },
     Bounds {
         repr: I32,
-        min: Discriminant::neg(i32::MIN as i64),
-        max: Discriminant::pos(i32::MAX as u64),
+        min: Discriminant::neg(std::i32::MIN as i64),
+        max: Discriminant::pos(std::i32::MAX as u64),
     },
     Bounds {
         repr: U64,
         min: Discriminant::zero(),
-        max: Discriminant::pos(u64::MAX),
+        max: Discriminant::pos(std::u64::MAX),
     },
     Bounds {
         repr: I64,
-        min: Discriminant::neg(i64::MIN),
-        max: Discriminant::pos(i64::MAX as u64),
+        min: Discriminant::neg(std::i64::MIN),
+        max: Discriminant::pos(std::i64::MAX as u64),
     },
 ];

From a954fcaddeb7a308af33b1fa9b39939453eea4d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:14:44 +0000
Subject: [PATCH 608/2232] Merge pull request #196 from dtolnay/enum


Choose enum discriminant type based on repr attributes, suffixes, values
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8f54bd7..0849d90 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -365,7 +365,9 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "enum class {} : uint32_t {{", enm.ident);
+    write!(out, "enum class {} : ", enm.ident);
+    write_atom(out, enm.repr);
+    writeln!(out, " {{");
     for variant in &enm.variants {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
@@ -373,16 +375,15 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {
-    writeln!(
-        out,
-        "static_assert(sizeof({}) == sizeof(uint32_t), \"incorrect size\");",
-        enm.ident
-    );
+    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident);
+    write_atom(out, enm.repr);
+    writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
+        write!(out, "static_assert(static_cast<");
+        write_atom(out, enm.repr);
         writeln!(
             out,
-            "static_assert(static_cast<uint32_t>({}::{}) == {},
-              \"disagrees with the value in #[cxx::bridge]\");",
+            ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
             enm.ident, variant.ident, variant.discriminant,
         );
     }
@@ -849,21 +850,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
 fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(ident) {
-            Some(Bool) => write!(out, "bool"),
-            Some(U8) => write!(out, "uint8_t"),
-            Some(U16) => write!(out, "uint16_t"),
-            Some(U32) => write!(out, "uint32_t"),
-            Some(U64) => write!(out, "uint64_t"),
-            Some(Usize) => write!(out, "size_t"),
-            Some(I8) => write!(out, "int8_t"),
-            Some(I16) => write!(out, "int16_t"),
-            Some(I32) => write!(out, "int32_t"),
-            Some(I64) => write!(out, "int64_t"),
-            Some(Isize) => write!(out, "::rust::isize"),
-            Some(F32) => write!(out, "float"),
-            Some(F64) => write!(out, "double"),
-            Some(CxxString) => write!(out, "::std::string"),
-            Some(RustString) => write!(out, "::rust::String"),
+            Some(atom) => write_atom(out, atom),
             None => write!(out, "{}", ident),
         },
         Type::RustBox(ty) => {
@@ -922,6 +909,26 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+fn write_atom(out: &mut OutFile, atom: Atom) {
+    match atom {
+        Bool => write!(out, "bool"),
+        U8 => write!(out, "uint8_t"),
+        U16 => write!(out, "uint16_t"),
+        U32 => write!(out, "uint32_t"),
+        U64 => write!(out, "uint64_t"),
+        Usize => write!(out, "size_t"),
+        I8 => write!(out, "int8_t"),
+        I16 => write!(out, "int16_t"),
+        I32 => write!(out, "int32_t"),
+        I64 => write!(out, "int64_t"),
+        Isize => write!(out, "::rust::isize"),
+        F32 => write!(out, "float"),
+        F64 => write!(out, "double"),
+        CxxString => write!(out, "::std::string"),
+        RustString => write!(out, "::rust::String"),
+    }
+}
+
 fn write_type_space(out: &mut OutFile, ty: &Type) {
     write_type(out, ty);
     write_space_after_type(out, ty);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fc129c6..f28d955 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -143,6 +143,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
+    let repr = enm.repr;
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -155,7 +156,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         #[derive(Copy, Clone, PartialEq, Eq)]
         #[repr(transparent)]
         pub struct #ident {
-            pub repr: u32,
+            pub repr: #repr,
         }
 
         #[allow(non_upper_case_globals)]
diff --git a/syntax/atom.rs b/syntax/atom.rs
index a2ff7b7..6e5fa88 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -23,8 +23,12 @@ pub enum Atom {
 
 impl Atom {
     pub fn from(ident: &Ident) -> Option<Self> {
+        Self::from_str(ident.to_string().as_str())
+    }
+
+    pub fn from_str(s: &str) -> Option<Self> {
         use self::Atom::*;
-        match ident.to_string().as_str() {
+        match s {
             "bool" => Some(Bool),
             "u8" => Some(U8),
             "u16" => Some(U16),
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index f48a210..16541a3 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,5 +1,7 @@
 use crate::syntax::report::Errors;
+use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
+use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
@@ -7,6 +9,7 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token};
 pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,
     pub derives: Option<&'a mut Vec<Derive>>,
+    pub repr: Option<&'a mut Option<Atom>>,
 }
 
 pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
@@ -44,6 +47,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("repr") {
+            match attr.parse_args_with(parse_repr_attribute) {
+                Ok(attr) => {
+                    if let Some(repr) = &mut parser.repr {
+                        **repr = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -69,3 +82,18 @@ fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
         })
         .collect()
 }
+
+fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
+    let begin = input.cursor();
+    let ident: Ident = input.parse()?;
+    if let Some(atom) = Atom::from(&ident) {
+        match atom {
+            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(atom),
+            _ => {}
+        }
+    }
+    Err(Error::new_spanned(
+        begin.token_stream(),
+        "unrecognized repr",
+    ))
+}
diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
new file mode 100644
index 0000000..67fa14d
--- /dev/null
+++ b/syntax/discriminant.rs
@@ -0,0 +1,280 @@
+use crate::syntax::Atom::{self, *};
+use proc_macro2::{Literal, Span, TokenStream};
+use quote::ToTokens;
+use std::cmp::Ordering;
+use std::collections::BTreeSet;
+use std::fmt::{self, Display};
+use std::str::FromStr;
+use std::u64;
+use syn::{Error, Expr, Lit, Result, Token, UnOp};
+
+pub struct DiscriminantSet {
+    repr: Option<Atom>,
+    values: BTreeSet<Discriminant>,
+    previous: Option<Discriminant>,
+}
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub struct Discriminant {
+    negative: bool,
+    magnitude: u64,
+}
+
+impl DiscriminantSet {
+    pub fn new(repr: Option<Atom>) -> Self {
+        DiscriminantSet {
+            repr,
+            values: BTreeSet::new(),
+            previous: None,
+        }
+    }
+
+    pub fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
+        let (discriminant, repr) = expr_to_discriminant(expr)?;
+        match (self.repr, repr) {
+            (None, _) => self.repr = repr,
+            (Some(prev), Some(repr)) if prev != repr => {
+                let msg = format!("expected {}, found {}", prev, repr);
+                return Err(Error::new(Span::call_site(), msg));
+            }
+            _ => {}
+        }
+        insert(self, discriminant)
+    }
+
+    pub fn insert_next(&mut self) -> Result<Discriminant> {
+        let discriminant = match self.previous {
+            None => Discriminant::zero(),
+            Some(mut discriminant) if discriminant.negative => {
+                discriminant.magnitude -= 1;
+                if discriminant.magnitude == 0 {
+                    discriminant.negative = false;
+                }
+                discriminant
+            }
+            Some(mut discriminant) => {
+                if discriminant.magnitude == u64::MAX {
+                    let msg = format!("discriminant overflow on value after {}", u64::MAX);
+                    return Err(Error::new(Span::call_site(), msg));
+                }
+                discriminant.magnitude += 1;
+                discriminant
+            }
+        };
+        insert(self, discriminant)
+    }
+
+    pub fn inferred_repr(&self) -> Result<Atom> {
+        if let Some(repr) = self.repr {
+            return Ok(repr);
+        }
+        if self.values.is_empty() {
+            return Ok(U8);
+        }
+        let min = *self.values.iter().next().unwrap();
+        let max = *self.values.iter().next_back().unwrap();
+        for bounds in &BOUNDS {
+            if bounds.min <= min && max <= bounds.max {
+                return Ok(bounds.repr);
+            }
+        }
+        let msg = "these discriminant values do not fit in any supported enum repr type";
+        Err(Error::new(Span::call_site(), msg))
+    }
+}
+
+fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
+    match expr {
+        Expr::Lit(expr) => {
+            if let Lit::Int(lit) = &expr.lit {
+                let discriminant = lit.base10_parse::<Discriminant>()?;
+                let repr = parse_int_suffix(lit.suffix())?;
+                return Ok((discriminant, repr));
+            }
+        }
+        Expr::Unary(unary) => {
+            if let UnOp::Neg(_) = unary.op {
+                let (mut discriminant, repr) = expr_to_discriminant(&unary.expr)?;
+                discriminant.negative ^= true;
+                return Ok((discriminant, repr));
+            }
+        }
+        _ => {}
+    }
+    Err(Error::new_spanned(
+        expr,
+        "enums with non-integer literal discriminants are not supported yet",
+    ))
+}
+
+fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discriminant> {
+    if let Some(expected_repr) = set.repr {
+        for bounds in &BOUNDS {
+            if bounds.repr != expected_repr {
+                continue;
+            }
+            if bounds.min <= discriminant && discriminant <= bounds.max {
+                break;
+            }
+            let msg = format!(
+                "discriminant value `{}` is outside the limits of {}",
+                discriminant, expected_repr,
+            );
+            return Err(Error::new(Span::call_site(), msg));
+        }
+    }
+    if set.values.insert(discriminant) {
+        set.previous = Some(discriminant);
+        Ok(discriminant)
+    } else {
+        let msg = format!("discriminant value `{}` already exists", discriminant);
+        Err(Error::new(Span::call_site(), msg))
+    }
+}
+
+impl Discriminant {
+    const fn zero() -> Self {
+        Discriminant {
+            negative: false,
+            magnitude: 0,
+        }
+    }
+
+    const fn pos(u: u64) -> Self {
+        Discriminant {
+            negative: false,
+            magnitude: u,
+        }
+    }
+
+    const fn neg(i: i64) -> Self {
+        Discriminant {
+            negative: i < 0,
+            // This is `i.abs() as u64` but without overflow on MIN. Uses the
+            // fact that MIN.wrapping_abs() wraps back to MIN whose binary
+            // representation is 1<<63, and thus the `as u64` conversion
+            // produces 1<<63 too which happens to be the correct unsigned
+            // magnitude.
+            magnitude: i.wrapping_abs() as u64,
+        }
+    }
+}
+
+impl Display for Discriminant {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.negative {
+            f.write_str("-")?;
+        }
+        Display::fmt(&self.magnitude, f)
+    }
+}
+
+impl ToTokens for Discriminant {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if self.negative {
+            Token![-](Span::call_site()).to_tokens(tokens);
+        }
+        Literal::u64_unsuffixed(self.magnitude).to_tokens(tokens);
+    }
+}
+
+impl FromStr for Discriminant {
+    type Err = Error;
+
+    fn from_str(mut s: &str) -> Result<Self> {
+        let negative = s.starts_with('-');
+        if negative {
+            s = &s[1..];
+        }
+        match s.parse::<u64>() {
+            Ok(magnitude) => Ok(Discriminant {
+                negative,
+                magnitude,
+            }),
+            Err(_) => Err(Error::new(
+                Span::call_site(),
+                "discriminant value outside of supported range",
+            )),
+        }
+    }
+}
+
+impl Ord for Discriminant {
+    fn cmp(&self, other: &Self) -> Ordering {
+        match (self.negative, other.negative) {
+            (true, true) => self.magnitude.cmp(&other.magnitude).reverse(),
+            (true, false) => Ordering::Less, // negative < positive
+            (false, true) => Ordering::Greater, // positive > negative
+            (false, false) => self.magnitude.cmp(&other.magnitude),
+        }
+    }
+}
+
+impl PartialOrd for Discriminant {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
+    if suffix.is_empty() {
+        return Ok(None);
+    }
+    if let Some(atom) = Atom::from_str(suffix) {
+        match atom {
+            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(Some(atom)),
+            _ => {}
+        }
+    }
+    let msg = format!("unrecognized integer suffix: `{}`", suffix);
+    Err(Error::new(Span::call_site(), msg))
+}
+
+struct Bounds {
+    repr: Atom,
+    min: Discriminant,
+    max: Discriminant,
+}
+
+const BOUNDS: [Bounds; 8] = [
+    Bounds {
+        repr: U8,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(std::u8::MAX as u64),
+    },
+    Bounds {
+        repr: I8,
+        min: Discriminant::neg(std::i8::MIN as i64),
+        max: Discriminant::pos(std::i8::MAX as u64),
+    },
+    Bounds {
+        repr: U16,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(std::u16::MAX as u64),
+    },
+    Bounds {
+        repr: I16,
+        min: Discriminant::neg(std::i16::MIN as i64),
+        max: Discriminant::pos(std::i16::MAX as u64),
+    },
+    Bounds {
+        repr: U32,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(std::u32::MAX as u64),
+    },
+    Bounds {
+        repr: I32,
+        min: Discriminant::neg(std::i32::MIN as i64),
+        max: Discriminant::pos(std::i32::MAX as u64),
+    },
+    Bounds {
+        repr: U64,
+        min: Discriminant::zero(),
+        max: Discriminant::pos(std::u64::MAX),
+    },
+    Bounds {
+        repr: I64,
+        min: Discriminant::neg(std::i64::MIN),
+        max: Discriminant::pos(std::i64::MAX as u64),
+    },
+];
diff --git a/syntax/mod.rs b/syntax/mod.rs
index d21c083..4702a69 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -4,6 +4,7 @@ pub mod atom;
 mod attrs;
 pub mod check;
 mod derive;
+mod discriminant;
 mod doc;
 pub mod error;
 pub mod ident;
@@ -17,11 +18,12 @@ pub mod symbol;
 mod tokens;
 pub mod types;
 
+use self::discriminant::Discriminant;
 use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Lifetime, LitStr, Token, Type as RustType};
+use syn::{Expr, Lifetime, LitStr, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -61,6 +63,7 @@ pub struct Enum {
     pub ident: Ident,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
+    pub repr: Atom,
 }
 
 pub struct ExternFn {
@@ -106,7 +109,8 @@ pub struct Receiver {
 
 pub struct Variant {
     pub ident: Ident,
-    pub discriminant: u32,
+    pub discriminant: Discriminant,
+    pub expr: Option<Expr>,
 }
 
 pub enum Type {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f84ff32..a11a5c8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::discriminant::DiscriminantSet;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
@@ -5,16 +6,13 @@ use crate::syntax::{
     Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
-use std::collections::HashSet;
-use std::u32;
+use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Attribute, Error, Expr, ExprLit, Fields, FnArg, ForeignItem, ForeignItemFn,
-    ForeignItemType, GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Lit, Pat,
-    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
-    TypeReference, TypeSlice, Variant as RustVariant,
+    Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Pat, PathArguments, Result,
+    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -62,6 +60,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
+            ..Default::default()
         },
     );
 
@@ -105,69 +104,71 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         ));
     }
 
-    let doc = attrs::parse_doc(cx, &item.attrs);
+    let mut doc = Doc::new();
+    let mut repr = None;
+    attrs::parse(
+        cx,
+        &item.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            repr: Some(&mut repr),
+            ..Default::default()
+        },
+    );
 
     let mut variants = Vec::new();
-    let mut discriminants = HashSet::new();
-    let mut prev_discriminant = None;
+    let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
         match variant.fields {
             Fields::Unit => {}
             _ => {
-                return Err(Error::new_spanned(
-                    variant,
-                    "enums with data are not supported yet",
-                ));
+                cx.error(variant, "enums with data are not supported yet");
+                break;
             }
         }
-        if variant.discriminant.is_none() && prev_discriminant == Some(u32::MAX) {
-            let msg = format!("discriminant overflow on value after {}", u32::MAX);
-            return Err(Error::new_spanned(variant, msg));
-        }
-        let discriminant =
-            parse_discriminant(&variant)?.unwrap_or_else(|| prev_discriminant.map_or(0, |n| n + 1));
-        if !discriminants.insert(discriminant) {
-            let msg = format!("discriminant value `{}` already exists", discriminant);
-            return Err(Error::new_spanned(variant, msg));
-        }
+        let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
+        let try_discriminant = match &expr {
+            Some(lit) => discriminants.insert(lit),
+            None => discriminants.insert_next(),
+        };
+        let discriminant = match try_discriminant {
+            Ok(discriminant) => discriminant,
+            Err(err) => {
+                cx.error(variant, err);
+                break;
+            }
+        };
+        let expr = variant.discriminant.map(|(_, expr)| expr);
         variants.push(Variant {
             ident: variant.ident,
             discriminant,
+            expr,
         });
-        prev_discriminant = Some(discriminant);
+    }
+
+    let enum_token = item.enum_token;
+    let brace_token = item.brace_token;
+
+    let mut repr = U8;
+    match discriminants.inferred_repr() {
+        Ok(inferred) => repr = inferred,
+        Err(err) => {
+            let span = quote_spanned!(brace_token.span=> #enum_token {});
+            cx.error(span, err);
+            variants.clear();
+        }
     }
 
     Ok(Api::Enum(Enum {
         doc,
-        enum_token: item.enum_token,
+        enum_token,
         ident: item.ident,
-        brace_token: item.brace_token,
+        brace_token,
         variants,
+        repr,
     }))
 }
 
-fn parse_discriminant(variant: &RustVariant) -> Result<Option<u32>> {
-    match &variant.discriminant {
-        None => Ok(None),
-        Some((
-            _,
-            Expr::Lit(ExprLit {
-                lit: Lit::Int(n), ..
-            }),
-        )) => match n.base10_parse() {
-            Ok(val) => Ok(Some(val)),
-            Err(_) => Err(Error::new_spanned(
-                variant,
-                "cannot parse enum discriminant as an integer",
-            )),
-        },
-        _ => Err(Error::new_spanned(
-            variant,
-            "enums with non-integer literal discriminants are not supported yet",
-        )),
-    }
-}
-
 fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
     let lang = match parse_lang(foreign_mod.abi) {
         Ok(lang) => lang,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 9a1fee0..4ed264a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
+    Atom, Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
     TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -75,6 +75,12 @@ impl ToTokens for Derive {
     }
 }
 
+impl ToTokens for Atom {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
+    }
+}
+
 impl ToTokens for ExternType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9457229..d4e96fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -44,7 +44,7 @@ pub mod ffi {
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
-        fn c_return_enum(n: u32) -> Enum;
+        fn c_return_enum(n: u16) -> Enum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -89,6 +89,7 @@ pub mod ffi {
         type COwnedEnum;
     }
 
+    #[repr(u32)]
     enum COwnedEnum {
         CVal1,
         CVal2,
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 21637d8..af7a4a0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -107,10 +107,10 @@ size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
 
-Enum c_return_enum(uint32_t n) {
-  if (n <= static_cast<uint32_t>(Enum::AVal)) {
+Enum c_return_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(Enum::AVal)) {
     return Enum::AVal;
-  } else if (n <= static_cast<uint32_t>(Enum::BVal)) {
+  } else if (n <= static_cast<uint16_t>(Enum::BVal)) {
     return Enum::BVal;
   } else {
     return Enum::CVal;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 795b4a9..1173a0a 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -7,7 +7,7 @@ namespace tests {
 
 struct R;
 struct Shared;
-enum class Enum : uint32_t;
+enum class Enum : uint16_t;
 
 class C {
 public:
@@ -46,7 +46,7 @@ rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
-Enum c_return_enum(uint32_t n);
+Enum c_return_enum(uint16_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
diff --git a/tests/ui/enum_inconsistent.rs b/tests/ui/enum_inconsistent.rs
new file mode 100644
index 0000000..cd5ffa5
--- /dev/null
+++ b/tests/ui/enum_inconsistent.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    enum Bad {
+        A = 1u16,
+        B = 2i64,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_inconsistent.stderr b/tests/ui/enum_inconsistent.stderr
new file mode 100644
index 0000000..c5b427a
--- /dev/null
+++ b/tests/ui/enum_inconsistent.stderr
@@ -0,0 +1,5 @@
+error: expected u16, found i64
+ --> $DIR/enum_inconsistent.rs:5:9
+  |
+5 |         B = 2i64,
+  |         ^^^^^^^^
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 93a8957..a5a0215 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A { repr: 2u32..=std::u32::MAX }` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=std::u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A { repr: 2u32..=std::u32::MAX }` not covered
+   |           ^ pattern `A { repr: 2u8..=std::u8::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`
diff --git a/tests/ui/enum_out_of_bounds.rs b/tests/ui/enum_out_of_bounds.rs
new file mode 100644
index 0000000..1aec5f0
--- /dev/null
+++ b/tests/ui/enum_out_of_bounds.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    #[repr(u32)]
+    enum Bad {
+        A = 0xFFFF_FFFF_FFFF_FFFF,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_out_of_bounds.stderr b/tests/ui/enum_out_of_bounds.stderr
new file mode 100644
index 0000000..f437ea1
--- /dev/null
+++ b/tests/ui/enum_out_of_bounds.stderr
@@ -0,0 +1,5 @@
+error: discriminant value `18446744073709551615` is outside the limits of u32
+ --> $DIR/enum_out_of_bounds.rs:5:9
+  |
+5 |         A = 0xFFFF_FFFF_FFFF_FFFF,
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/enum_overflows.rs b/tests/ui/enum_overflows.rs
index 3f351f0..29de1a0 100644
--- a/tests/ui/enum_overflows.rs
+++ b/tests/ui/enum_overflows.rs
@@ -1,14 +1,14 @@
 #[cxx::bridge]
 mod ffi {
     enum Good1 {
-        A = 0xffffffff,
+        A = 0xFFFF_FFFF_FFFF_FFFF,
     }
     enum Good2 {
-        B = 0xffffffff,
+        B = 0xFFFF_FFFF_FFFF_FFFF,
         C = 2020,
     }
     enum Bad {
-        D = 0xfffffffe,
+        D = 0xFFFF_FFFF_FFFF_FFFE,
         E,
         F,
     }
diff --git a/tests/ui/enum_overflows.stderr b/tests/ui/enum_overflows.stderr
index db92f7f..ed58b61 100644
--- a/tests/ui/enum_overflows.stderr
+++ b/tests/ui/enum_overflows.stderr
@@ -1,4 +1,4 @@
-error: discriminant overflow on value after 4294967295
+error: discriminant overflow on value after 18446744073709551615
   --> $DIR/enum_overflows.rs:13:9
    |
 13 |         F,
diff --git a/tests/ui/enum_unsatisfiable.rs b/tests/ui/enum_unsatisfiable.rs
new file mode 100644
index 0000000..6191287
--- /dev/null
+++ b/tests/ui/enum_unsatisfiable.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    enum Bad {
+        A = -0xFFFF_FFFF_FFFF_FFFF,
+        B = 0xFFFF_FFFF_FFFF_FFFF,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_unsatisfiable.stderr b/tests/ui/enum_unsatisfiable.stderr
new file mode 100644
index 0000000..99852ca
--- /dev/null
+++ b/tests/ui/enum_unsatisfiable.stderr
@@ -0,0 +1,8 @@
+error: these discriminant values do not fit in any supported enum repr type
+ --> $DIR/enum_unsatisfiable.rs:3:5
+  |
+3 | /     enum Bad {
+4 | |         A = -0xFFFF_FFFF_FFFF_FFFF,
+5 | |         B = 0xFFFF_FFFF_FFFF_FFFF,
+6 | |     }
+  | |_____^

From 8155e58ba1c8c26a2cb37ad054272359a507a928 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:15:12 +0000
Subject: [PATCH 609/2232] Treat unexpected tokens in repr attribute as unexpected repr


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 16541a3..4c76641 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -88,7 +88,9 @@ fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
     let ident: Ident = input.parse()?;
     if let Some(atom) = Atom::from(&ident) {
         match atom {
-            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize => return Ok(atom),
+            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => {
+                return Ok(atom);
+            }
             _ => {}
         }
     }

From 9f7c55acdee93a651fab5a9c74923615664d8519 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:19:02 +0000
Subject: [PATCH 610/2232] Rename discriminant Bounds to Limits


This is aligned with "limits" as used in std::numeric_limits in C++.

---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 67fa14d..35ef4cb 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -73,9 +73,9 @@ impl DiscriminantSet {
         }
         let min = *self.values.iter().next().unwrap();
         let max = *self.values.iter().next_back().unwrap();
-        for bounds in &BOUNDS {
-            if bounds.min <= min && max <= bounds.max {
-                return Ok(bounds.repr);
+        for limits in &LIMITS {
+            if limits.min <= min && max <= limits.max {
+                return Ok(limits.repr);
             }
         }
         let msg = "these discriminant values do not fit in any supported enum repr type";
@@ -109,11 +109,11 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
 
 fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discriminant> {
     if let Some(expected_repr) = set.repr {
-        for bounds in &BOUNDS {
-            if bounds.repr != expected_repr {
+        for limits in &LIMITS {
+            if limits.repr != expected_repr {
                 continue;
             }
-            if bounds.min <= discriminant && discriminant <= bounds.max {
+            if limits.min <= discriminant && discriminant <= limits.max {
                 break;
             }
             let msg = format!(
@@ -230,49 +230,49 @@ fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
     Err(Error::new(Span::call_site(), msg))
 }
 
-struct Bounds {
+struct Limits {
     repr: Atom,
     min: Discriminant,
     max: Discriminant,
 }
 
-const BOUNDS: [Bounds; 8] = [
-    Bounds {
+const LIMITS: [Limits; 8] = [
+    Limits {
         repr: U8,
         min: Discriminant::zero(),
         max: Discriminant::pos(std::u8::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: I8,
         min: Discriminant::neg(std::i8::MIN as i64),
         max: Discriminant::pos(std::i8::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: U16,
         min: Discriminant::zero(),
         max: Discriminant::pos(std::u16::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: I16,
         min: Discriminant::neg(std::i16::MIN as i64),
         max: Discriminant::pos(std::i16::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: U32,
         min: Discriminant::zero(),
         max: Discriminant::pos(std::u32::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: I32,
         min: Discriminant::neg(std::i32::MIN as i64),
         max: Discriminant::pos(std::i32::MAX as u64),
     },
-    Bounds {
+    Limits {
         repr: U64,
         min: Discriminant::zero(),
         max: Discriminant::pos(std::u64::MAX),
     },
-    Bounds {
+    Limits {
         repr: I64,
         min: Discriminant::neg(std::i64::MIN),
         max: Discriminant::pos(std::i64::MAX as u64),

From 65bc8e6af849243b56e032a9ca2c52df596e10e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:30:24 +0000
Subject: [PATCH 611/2232] Detect earlier untyped discriminants out of bounds of later suffix


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 35ef4cb..6a04d88 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -32,7 +32,21 @@ impl DiscriminantSet {
     pub fn insert(&mut self, expr: &Expr) -> Result<Discriminant> {
         let (discriminant, repr) = expr_to_discriminant(expr)?;
         match (self.repr, repr) {
-            (None, _) => self.repr = repr,
+            (None, Some(new_repr)) => {
+                if let Some(limits) = Limits::of(new_repr) {
+                    for &past in &self.values {
+                        if limits.min <= past && past <= limits.max {
+                            continue;
+                        }
+                        let msg = format!(
+                            "discriminant value `{}` is outside the limits of {}",
+                            past, new_repr,
+                        );
+                        return Err(Error::new(Span::call_site(), msg));
+                    }
+                }
+                self.repr = Some(new_repr);
+            }
             (Some(prev), Some(repr)) if prev != repr => {
                 let msg = format!("expected {}, found {}", prev, repr);
                 return Err(Error::new(Span::call_site(), msg));
@@ -109,18 +123,14 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
 
 fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discriminant> {
     if let Some(expected_repr) = set.repr {
-        for limits in &LIMITS {
-            if limits.repr != expected_repr {
-                continue;
-            }
-            if limits.min <= discriminant && discriminant <= limits.max {
-                break;
+        if let Some(limits) = Limits::of(expected_repr) {
+            if discriminant < limits.min || limits.max < discriminant {
+                let msg = format!(
+                    "discriminant value `{}` is outside the limits of {}",
+                    discriminant, expected_repr,
+                );
+                return Err(Error::new(Span::call_site(), msg));
             }
-            let msg = format!(
-                "discriminant value `{}` is outside the limits of {}",
-                discriminant, expected_repr,
-            );
-            return Err(Error::new(Span::call_site(), msg));
         }
     }
     if set.values.insert(discriminant) {
@@ -230,12 +240,24 @@ fn parse_int_suffix(suffix: &str) -> Result<Option<Atom>> {
     Err(Error::new(Span::call_site(), msg))
 }
 
+#[derive(Copy, Clone)]
 struct Limits {
     repr: Atom,
     min: Discriminant,
     max: Discriminant,
 }
 
+impl Limits {
+    fn of(repr: Atom) -> Option<Limits> {
+        for limits in &LIMITS {
+            if limits.repr == repr {
+                return Some(*limits);
+            }
+        }
+        None
+    }
+}
+
 const LIMITS: [Limits; 8] = [
     Limits {
         repr: U8,
diff --git a/tests/ui/enum_out_of_bounds.rs b/tests/ui/enum_out_of_bounds.rs
index 1aec5f0..9e0090b 100644
--- a/tests/ui/enum_out_of_bounds.rs
+++ b/tests/ui/enum_out_of_bounds.rs
@@ -1,9 +1,13 @@
 #[cxx::bridge]
 mod ffi {
     #[repr(u32)]
-    enum Bad {
+    enum Bad1 {
         A = 0xFFFF_FFFF_FFFF_FFFF,
     }
+    enum Bad2 {
+        A = 2000,
+        B = 1u8,
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/enum_out_of_bounds.stderr b/tests/ui/enum_out_of_bounds.stderr
index f437ea1..5d02e20 100644
--- a/tests/ui/enum_out_of_bounds.stderr
+++ b/tests/ui/enum_out_of_bounds.stderr
@@ -3,3 +3,9 @@ error: discriminant value `18446744073709551615` is outside the limits of u32
   |
 5 |         A = 0xFFFF_FFFF_FFFF_FFFF,
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: discriminant value `2000` is outside the limits of u8
+ --> $DIR/enum_out_of_bounds.rs:9:9
+  |
+9 |         B = 1u8,
+  |         ^^^^^^^

From 2967b66788f540a9ba98cced569c92d6f4aa121e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:53:06 +0000
Subject: [PATCH 612/2232] Move finding of bridge mod to its own module


---

diff --git a/gen/src/find.rs b/gen/src/find.rs
new file mode 100644
index 0000000..dc83431
--- /dev/null
+++ b/gen/src/find.rs
@@ -0,0 +1,36 @@
+use crate::gen::{Error, Input, Result};
+use crate::syntax::namespace::Namespace;
+use quote::quote;
+use syn::{Attribute, File, Item};
+
+pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
+    for item in syntax.items {
+        if let Item::Mod(item) = item {
+            for attr in &item.attrs {
+                let path = &attr.path;
+                if quote!(#path).to_string() == "cxx :: bridge" {
+                    let module = match item.content {
+                        Some(module) => module.1,
+                        None => {
+                            return Err(Error::Syn(syn::Error::new_spanned(
+                                item,
+                                Error::OutOfLineMod,
+                            )));
+                        }
+                    };
+                    let namespace = parse_args(attr)?;
+                    return Ok(Input { namespace, module });
+                }
+            }
+        }
+    }
+    Err(Error::NoBridgeMod)
+}
+
+fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
+    if attr.tokens.is_empty() {
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 6663e4b..fa69cb5 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -2,6 +2,7 @@
 // the cmd.
 
 mod error;
+mod find;
 pub(super) mod include;
 pub(super) mod out;
 mod write;
@@ -10,10 +11,9 @@ use self::error::{format_err, Error, Result};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
-use quote::quote;
 use std::fs;
 use std::path::Path;
-use syn::{Attribute, File, Item};
+use syn::Item;
 
 struct Input {
     namespace: Namespace,
@@ -45,7 +45,7 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         proc_macro2::fallback::force();
         let ref mut errors = Errors::new();
         let syntax = syn::parse_file(&source)?;
-        let bridge = find_bridge_mod(syntax)?;
+        let bridge = find::find_bridge_mod(syntax)?;
         let ref namespace = bridge.namespace;
         let ref apis = syntax::parse_items(errors, bridge.module);
         let ref types = Types::collect(errors, apis);
@@ -59,35 +59,3 @@ fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Err(err) => format_err(path, &source, err),
     }
 }
-
-fn find_bridge_mod(syntax: File) -> Result<Input> {
-    for item in syntax.items {
-        if let Item::Mod(item) = item {
-            for attr in &item.attrs {
-                let path = &attr.path;
-                if quote!(#path).to_string() == "cxx :: bridge" {
-                    let module = match item.content {
-                        Some(module) => module.1,
-                        None => {
-                            return Err(Error::Syn(syn::Error::new_spanned(
-                                item,
-                                Error::OutOfLineMod,
-                            )));
-                        }
-                    };
-                    let namespace = parse_args(attr)?;
-                    return Ok(Input { namespace, module });
-                }
-            }
-        }
-    }
-    Err(Error::NoBridgeMod)
-}
-
-fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
-    if attr.tokens.is_empty() {
-        Ok(Namespace::none())
-    } else {
-        attr.parse_args()
-    }
-}

From b4dba23910d0444291159647acc4a1ac0444ecdc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 07:55:40 +0000
Subject: [PATCH 613/2232] Bring gen module doc up to date


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index fa69cb5..b9d35d7 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,5 +1,5 @@
-// Functionality that is shared between the cxx::generate_bridge entry point and
-// the cmd.
+// Functionality that is shared between the cxx_build::bridge entry point and
+// the cxxbridge CLI command.
 
 mod error;
 mod find;

From 2498af39f2ffe63deed13a28d0c3fc515b029812 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 08:13:33 +0000
Subject: [PATCH 614/2232] Find cxx::bridge mod nested inside another mod


---

diff --git a/gen/src/find.rs b/gen/src/find.rs
index dc83431..86e1dc7 100644
--- a/gen/src/find.rs
+++ b/gen/src/find.rs
@@ -4,7 +4,14 @@ use quote::quote;
 use syn::{Attribute, File, Item};
 
 pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
-    for item in syntax.items {
+    match scan(syntax.items)? {
+        Some(input) => Ok(input),
+        None => Err(Error::NoBridgeMod),
+    }
+}
+
+fn scan(items: Vec<Item>) -> Result<Option<Input>> {
+    for item in items {
         if let Item::Mod(item) = item {
             for attr in &item.attrs {
                 let path = &attr.path;
@@ -19,12 +26,17 @@ pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
                         }
                     };
                     let namespace = parse_args(attr)?;
-                    return Ok(Input { namespace, module });
+                    return Ok(Some(Input { namespace, module }));
+                }
+            }
+            if let Some(module) = item.content {
+                if let Some(input) = scan(module.1)? {
+                    return Ok(Some(input));
                 }
             }
         }
     }
-    Err(Error::NoBridgeMod)
+    Ok(None)
 }
 
 fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {

From dbe7cb0721142651133befcbfa2a33f312fca6ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 08:20:00 +0000
Subject: [PATCH 615/2232] Merge pull request #197 from dtolnay/find


Find cxx::bridge mod nested inside another mod
---

diff --git a/gen/src/find.rs b/gen/src/find.rs
index dc83431..86e1dc7 100644
--- a/gen/src/find.rs
+++ b/gen/src/find.rs
@@ -4,7 +4,14 @@ use quote::quote;
 use syn::{Attribute, File, Item};
 
 pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
-    for item in syntax.items {
+    match scan(syntax.items)? {
+        Some(input) => Ok(input),
+        None => Err(Error::NoBridgeMod),
+    }
+}
+
+fn scan(items: Vec<Item>) -> Result<Option<Input>> {
+    for item in items {
         if let Item::Mod(item) = item {
             for attr in &item.attrs {
                 let path = &attr.path;
@@ -19,12 +26,17 @@ pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
                         }
                     };
                     let namespace = parse_args(attr)?;
-                    return Ok(Input { namespace, module });
+                    return Ok(Some(Input { namespace, module }));
+                }
+            }
+            if let Some(module) = item.content {
+                if let Some(input) = scan(module.1)? {
+                    return Ok(Some(input));
                 }
             }
         }
     }
-    Err(Error::NoBridgeMod)
+    Ok(None)
 }
 
 fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {

From f5ac0d9ffa6a6e531151fd2d109f541022fc5cf6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 20:19:14 +0000
Subject: [PATCH 616/2232] Fix permission denied failure in bazel CI job


This job started failing in GitHub Actions with this error:

    ## $ bazel run demo-rs --verbose_failures --noshow_progress
    Downloading https://releases.bazel.build/3.1.0/release/bazel-3.1.0-linux-x86_64...
    could not run Bazel: could not start Bazel: fork/exec /home/runner/work/cxx/cxx/tools/bazel: permission denied
    ##[error]Process completed with exit code 1.

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1040454..f0ca230 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -79,6 +79,7 @@ jobs:
           wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
+          echo ::add-path::$HOME/bin
       - name: Vendor dependencies
         run: |
           cp third-party/Cargo.lock .

From 43f3aee48d693176718c8047bb87bb637fbe7ddc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 20:26:45 +0000
Subject: [PATCH 617/2232] Merge pull request #200 from dtolnay/bazel


Fix permission denied failure in bazel CI job
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1040454..f0ca230 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -79,6 +79,7 @@ jobs:
           wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
+          echo ::add-path::$HOME/bin
       - name: Vendor dependencies
         run: |
           cp third-party/Cargo.lock .

From e3daefbf63c7ea9115450eb6fd7a5cc54abf01a7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 20:27:04 +0000
Subject: [PATCH 618/2232] Add crosslink icons to top of rustdoc


---

diff --git a/src/lib.rs b/src/lib.rs
index 3b37c5a..f0e89f0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,8 @@
-//! **[https://github.com/dtolnay/cxx]**
+//! [![github]](https://github.com/dtolnay/cxx)&ensp;[![crates-io]](https://crates.io/crates/cxx)&ensp;[![docs-rs]](https://docs.rs/cxx)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
 //!
 //! <br>
 //!

From 7fbfc95720961e16c511224d62485a4f2b312f27 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 11 2020 20:35:11 +0000
Subject: [PATCH 619/2232] Merge pull request #198 from dtolnay/icons


Add crosslink icons to top of rustdoc
---

diff --git a/src/lib.rs b/src/lib.rs
index 3b37c5a..f0e89f0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,8 @@
-//! **[https://github.com/dtolnay/cxx]**
+//! [![github]](https://github.com/dtolnay/cxx)&ensp;[![crates-io]](https://crates.io/crates/cxx)&ensp;[![docs-rs]](https://docs.rs/cxx)
+//!
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
 //!
 //! <br>
 //!

From bbcf2154e65a49ed9d24b35ed9aae4f448edeb22 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 02:04:25 +0000
Subject: [PATCH 620/2232] Accept bracketed in addition to quoted extra includes


Invoked as:

    cxxbridge path/to/file.rs -i '<path/to/bracketed>' -i path/to/quoted

Emits:

    #include <path/to/bracketed>
    #include "path/to/quoted"

---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 129a8e6..2f030ba 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -61,7 +61,11 @@ impl Extend<String> for Includes {
 impl Display for Includes {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for include in &self.custom {
-            writeln!(f, "#include \"{}\"", include.escape_default())?;
+            if include.starts_with('<') && include.ends_with('>') {
+                writeln!(f, "#include {}", include)?;
+            } else {
+                writeln!(f, "#include \"{}\"", include.escape_default())?;
+            }
         }
         if self.array {
             writeln!(f, "#include <array>")?;

From 891845141243f5b9ca579b2df0c6ed77bf838e0d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:05:56 +0000
Subject: [PATCH 621/2232] Pull in syn 1.0.20 for Macro::parse_body fix


https://github.com/dtolnay/syn/pull/791

This will give better error message in the upcoming implementation of
include!(<bracketed/path/to>).

---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 84ab6fe..d703c57 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -15,7 +15,7 @@ cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
-syn = { version = "1.0.19", features = ["full"] }
+syn = { version = "1.0.20", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index d14dc84..e8b600a 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -19,7 +19,7 @@ codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
-syn = { version = "1.0.19", features = ["full"] }
+syn = { version = "1.0.20", features = ["full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 0dc3038..8326e22 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -16,7 +16,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0.4"
-syn = { version = "1.0.19", features = ["full"] }
+syn = { version = "1.0.20", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "0.3", path = ".." }
diff --git a/third-party/BUCK b/third-party/BUCK
index e16bad2..d30eda0 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.19/src/**"]),
+    srcs = glob(["vendor/syn-1.0.20/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 45b1163..7112779 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.19/src/**"]),
+    srcs = glob(["vendor/syn-1.0.20/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index e54c293..f4daa91 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7"
+checksum = "dd1b5e337360b1fae433c59fcafa0c6b77c605e92540afa5221a7b81a9eca91d"
 dependencies = [
  "proc-macro2",
  "quote",

From 91e87fa51e42236006cc30e385886c56ceb2fa52 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:07:34 +0000
Subject: [PATCH 622/2232] Parse include!(<path/to/bracketed>)


For example:

    #[cxx::bridge]
    mod ffi {
        extern "C" {
            include!("path/to/quoted");
            include!(<path/to/bracketed>);

            ...
        }
    }

Emitted as:

    #include "path/to/quoted"
    #include <path/to/bracketed>

---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 2f030ba..be0bd8e 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -47,8 +47,8 @@ impl Includes {
         Includes::default()
     }
 
-    pub fn insert(&mut self, include: String) {
-        self.custom.push(include);
+    pub fn insert(&mut self, include: impl AsRef<str>) {
+        self.custom.push(include.as_ref().to_owned());
     }
 }
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0849d90..d5eae90 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -24,7 +24,7 @@ pub(super) fn gen(
     out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
-            out.include.insert(include.value());
+            out.include.insert(include);
         }
     }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4702a69..88c96e8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -23,7 +23,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Lifetime, LitStr, Token, Type as RustType};
+use syn::{Expr, Lifetime, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -32,7 +32,7 @@ pub use self::parse::parse_items;
 pub use self::types::Types;
 
 pub enum Api {
-    Include(LitStr),
+    Include(String),
     Struct(Struct),
     Enum(Enum),
     CxxType(ExternType),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a11a5c8..a1d31cf 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,14 +5,14 @@ use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
     Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::TokenStream;
+use proc_macro2::{TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Pat, PathArguments, Result,
-    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
+    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -187,7 +187,7 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
                 Err(err) => cx.push(err),
             },
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
-                match foreign.mac.parse_body() {
+                match foreign.mac.parse_body_with(parse_include) {
                     Ok(include) => items.push(Api::Include(include)),
                     Err(err) => cx.push(err),
                 }
@@ -389,6 +389,38 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
+fn parse_include(input: ParseStream) -> Result<String> {
+    if input.peek(LitStr) {
+        return Ok(input.parse::<LitStr>()?.value());
+    }
+
+    if input.peek(Token![<]) {
+        let mut path = String::new();
+        input.parse::<Token![<]>()?;
+        path.push('<');
+        while !input.is_empty() && !input.peek(Token![>]) {
+            let token: TokenTree = input.parse()?;
+            match token {
+                TokenTree::Ident(token) => path += &token.to_string(),
+                TokenTree::Literal(token)
+                    if token
+                        .to_string()
+                        .starts_with(|ch: char| ch.is_ascii_digit()) =>
+                {
+                    path += &token.to_string();
+                }
+                TokenTree::Punct(token) => path.push(token.as_char()),
+                _ => return Err(Error::new(token.span(), "unexpected token in include path")),
+            }
+        }
+        input.parse::<Token![>]>()?;
+        path.push('>');
+        return Ok(path);
+    }
+
+    Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
+}
+
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),

From cf96664b29e873e565e404d80231ff4cfbc08fcc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:07:34 +0000
Subject: [PATCH 623/2232] Test include parsing


---

diff --git a/tests/ui/include.rs b/tests/ui/include.rs
new file mode 100644
index 0000000..82fa8de
--- /dev/null
+++ b/tests/ui/include.rs
@@ -0,0 +1,12 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        include!("path/to" what);
+        include!(<path/to> what);
+        include!(<path/to);
+        include!(<path[to]>);
+        include!(...);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/include.stderr b/tests/ui/include.stderr
new file mode 100644
index 0000000..c85a83e
--- /dev/null
+++ b/tests/ui/include.stderr
@@ -0,0 +1,29 @@
+error: unexpected token
+ --> $DIR/include.rs:4:28
+  |
+4 |         include!("path/to" what);
+  |                            ^^^^
+
+error: unexpected token
+ --> $DIR/include.rs:5:28
+  |
+5 |         include!(<path/to> what);
+  |                            ^^^^
+
+error: expected `>`
+ --> $DIR/include.rs:6:17
+  |
+6 |         include!(<path/to);
+  |                 ^^^^^^^^^^
+
+error: unexpected token in include path
+ --> $DIR/include.rs:7:23
+  |
+7 |         include!(<path[to]>);
+  |                       ^^^^
+
+error: expected "quoted/path/to" or <bracketed/path/to>
+ --> $DIR/include.rs:8:18
+  |
+8 |         include!(...);
+  |                  ^^^

From 14db1e2049ab565122e0a3360a3b10720dd580e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:14:45 +0000
Subject: [PATCH 624/2232] Merge pull request #201 from dtolnay/include


Parse include!(<path/to/bracketed>)
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 2f030ba..be0bd8e 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -47,8 +47,8 @@ impl Includes {
         Includes::default()
     }
 
-    pub fn insert(&mut self, include: String) {
-        self.custom.push(include);
+    pub fn insert(&mut self, include: impl AsRef<str>) {
+        self.custom.push(include.as_ref().to_owned());
     }
 }
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0849d90..d5eae90 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -24,7 +24,7 @@ pub(super) fn gen(
     out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
-            out.include.insert(include.value());
+            out.include.insert(include);
         }
     }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4702a69..88c96e8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -23,7 +23,7 @@ use self::parse::kw;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Lifetime, LitStr, Token, Type as RustType};
+use syn::{Expr, Lifetime, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -32,7 +32,7 @@ pub use self::parse::parse_items;
 pub use self::types::Types;
 
 pub enum Api {
-    Include(LitStr),
+    Include(String),
     Struct(Struct),
     Enum(Enum),
     CxxType(ExternType),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a11a5c8..a1d31cf 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,14 +5,14 @@ use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
     Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::TokenStream;
+use proc_macro2::{TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, Pat, PathArguments, Result,
-    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
+    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -187,7 +187,7 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
                 Err(err) => cx.push(err),
             },
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
-                match foreign.mac.parse_body() {
+                match foreign.mac.parse_body_with(parse_include) {
                     Ok(include) => items.push(Api::Include(include)),
                     Err(err) => cx.push(err),
                 }
@@ -389,6 +389,38 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
+fn parse_include(input: ParseStream) -> Result<String> {
+    if input.peek(LitStr) {
+        return Ok(input.parse::<LitStr>()?.value());
+    }
+
+    if input.peek(Token![<]) {
+        let mut path = String::new();
+        input.parse::<Token![<]>()?;
+        path.push('<');
+        while !input.is_empty() && !input.peek(Token![>]) {
+            let token: TokenTree = input.parse()?;
+            match token {
+                TokenTree::Ident(token) => path += &token.to_string(),
+                TokenTree::Literal(token)
+                    if token
+                        .to_string()
+                        .starts_with(|ch: char| ch.is_ascii_digit()) =>
+                {
+                    path += &token.to_string();
+                }
+                TokenTree::Punct(token) => path.push(token.as_char()),
+                _ => return Err(Error::new(token.span(), "unexpected token in include path")),
+            }
+        }
+        input.parse::<Token![>]>()?;
+        path.push('>');
+        return Ok(path);
+    }
+
+    Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
+}
+
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
diff --git a/tests/ui/include.rs b/tests/ui/include.rs
new file mode 100644
index 0000000..82fa8de
--- /dev/null
+++ b/tests/ui/include.rs
@@ -0,0 +1,12 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C" {
+        include!("path/to" what);
+        include!(<path/to> what);
+        include!(<path/to);
+        include!(<path[to]>);
+        include!(...);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/include.stderr b/tests/ui/include.stderr
new file mode 100644
index 0000000..c85a83e
--- /dev/null
+++ b/tests/ui/include.stderr
@@ -0,0 +1,29 @@
+error: unexpected token
+ --> $DIR/include.rs:4:28
+  |
+4 |         include!("path/to" what);
+  |                            ^^^^
+
+error: unexpected token
+ --> $DIR/include.rs:5:28
+  |
+5 |         include!(<path/to> what);
+  |                            ^^^^
+
+error: expected `>`
+ --> $DIR/include.rs:6:17
+  |
+6 |         include!(<path/to);
+  |                 ^^^^^^^^^^
+
+error: unexpected token in include path
+ --> $DIR/include.rs:7:23
+  |
+7 |         include!(<path[to]>);
+  |                       ^^^^
+
+error: expected "quoted/path/to" or <bracketed/path/to>
+ --> $DIR/include.rs:8:18
+  |
+8 |         include!(...);
+  |                  ^^^

From 9808ef177cd75eecc30d4241cf604ff8cda2dacc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:30:44 +0000
Subject: [PATCH 625/2232] Add cargo cfgs for opt in to newer standards


Currently unused, but will be needed when integrating std::optional or
std::string_view support.

    [dependencies]
    cxx = { version = "0.3", features = ["c++17"] }

---

diff --git a/Cargo.toml b/Cargo.toml
index 829eac3..db3b5e1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,11 @@ exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
+[features]
+default = [] # c++11
+"c++14" = []
+"c++17" = []
+
 [dependencies]
 cxxbridge-macro = { version = "=0.3.2", path = "macro" }
 link-cplusplus = "1.0"
diff --git a/build.rs b/build.rs
index 9a071fe..a412dbd 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,13 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported(if cfg!(feature = "c++17") {
+            "-std=c++17"
+        } else if cfg!(feature = "c++14") {
+            "-std=c++14"
+        } else {
+            "-std=c++11"
+        })
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");

From c13ad23d9c1df66f73402042114de465539c0bb7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:38:19 +0000
Subject: [PATCH 626/2232] Switch demo code to using std::make_unique


---

diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
index 595a18b..f60200b 100644
--- a/demo-cxx/BUCK
+++ b/demo-cxx/BUCK
@@ -1,6 +1,7 @@
 cxx_library(
     name = "demo-cxx",
     srcs = ["demo.cc"],
+    compiler_flags = ["-std=c++14"],
     visibility = ["PUBLIC"],
     deps = [
         ":include",
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
index da97cfa..7b1860a 100644
--- a/demo-cxx/BUILD
+++ b/demo-cxx/BUILD
@@ -1,6 +1,7 @@
 cc_library(
     name = "demo-cxx",
     srcs = ["demo.cc"],
+    copts = ["-std=c++14"],
     visibility = ["//visibility:public"],
     deps = [
         ":include",
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..21bdad4 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -10,7 +10,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
+  return std::make_unique<ThingC>(std::string(appname));
 }
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index e4792c2..f32b8ef 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,7 +1,7 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported("-std=c++14")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");

From 4ab952da41a3ef952fb922fa069b23fc9a8875b7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:43:35 +0000
Subject: [PATCH 627/2232] Merge pull request #202 from dtolnay/stdflag


Add cargo cfgs for opt in to newer standards
---

diff --git a/Cargo.toml b/Cargo.toml
index 829eac3..db3b5e1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,11 @@ exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
+[features]
+default = [] # c++11
+"c++14" = []
+"c++17" = []
+
 [dependencies]
 cxxbridge-macro = { version = "=0.3.2", path = "macro" }
 link-cplusplus = "1.0"
diff --git a/build.rs b/build.rs
index 9a071fe..a412dbd 100644
--- a/build.rs
+++ b/build.rs
@@ -3,7 +3,13 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported(if cfg!(feature = "c++17") {
+            "-std=c++17"
+        } else if cfg!(feature = "c++14") {
+            "-std=c++14"
+        } else {
+            "-std=c++11"
+        })
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");

From 2b93b555608a9d6ed3e9461442df8ca14cc80868 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:48:12 +0000
Subject: [PATCH 628/2232] Merge pull request #203 from dtolnay/unique


Switch demo code to using std::make_unique
---

diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
index 595a18b..f60200b 100644
--- a/demo-cxx/BUCK
+++ b/demo-cxx/BUCK
@@ -1,6 +1,7 @@
 cxx_library(
     name = "demo-cxx",
     srcs = ["demo.cc"],
+    compiler_flags = ["-std=c++14"],
     visibility = ["PUBLIC"],
     deps = [
         ":include",
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
index da97cfa..7b1860a 100644
--- a/demo-cxx/BUILD
+++ b/demo-cxx/BUILD
@@ -1,6 +1,7 @@
 cc_library(
     name = "demo-cxx",
     srcs = ["demo.cc"],
+    copts = ["-std=c++14"],
     visibility = ["//visibility:public"],
     deps = [
         ":include",
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
index cd447ea..21bdad4 100644
--- a/demo-cxx/demo.cc
+++ b/demo-cxx/demo.cc
@@ -10,7 +10,7 @@ ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
 ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
 
 std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::unique_ptr<ThingC>(new ThingC(std::string(appname)));
+  return std::make_unique<ThingC>(std::string(appname));
 }
 
 const std::string &get_name(const ThingC &thing) { return thing.appname; }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
index e4792c2..f32b8ef 100644
--- a/demo-rs/build.rs
+++ b/demo-rs/build.rs
@@ -1,7 +1,7 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
         .file("../demo-cxx/demo.cc")
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported("-std=c++14")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");

From 0e078f74be2122bff458ff23e43e364a11abaa90 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:50:03 +0000
Subject: [PATCH 629/2232] Add release notes link to crate-level rustdoc


---

diff --git a/src/lib.rs b/src/lib.rs
index f0e89f0..23f2d60 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,8 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.42+*
+//! *Compiler support: requires rustc 1.42+*<br>
+//! *[Release notes](https://github.com/dtolnay/cxx/releases)*
 //!
 //! <br>
 //!

From cf223856623f4f44437e2471bc66d9f90af0e66d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:50:59 +0000
Subject: [PATCH 630/2232] Document c++ standard support


---

diff --git a/README.md b/README.md
index 9e397f2..5fd02a9 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ can be 100% safe.
 cxx = "0.3"
 ```
 
-*Compiler support: requires rustc 1.42+*<br>
+*Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
 *[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
diff --git a/src/lib.rs b/src/lib.rs
index 23f2d60..5ebc119 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.42+*<br>
+//! *Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
 //! *[Release notes](https://github.com/dtolnay/cxx/releases)*
 //!
 //! <br>

From 6aa34e4240c586647a788da3429622801c320ea9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 12 2020 03:56:51 +0000
Subject: [PATCH 631/2232] Release 0.3.3


---

diff --git a/Cargo.toml b/Cargo.toml
index db3b5e1..204a1c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.2" # remember to update html_root_url
+version = "0.3.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -19,14 +19,14 @@ default = [] # c++11
 "c++17" = []
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.2", path = "macro" }
+cxxbridge-macro = { version = "=0.3.3", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.2", path = "gen/build" }
+cxx-build = { version = "=0.3.3", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.27", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index d703c57..98b3497 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.2"
+version = "0.3.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e8b600a..ddf27c5 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.2"
+version = "0.3.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 8326e22..e4d35b8 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.2"
+version = "0.3.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 5ebc119..a657af7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.3")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/BUCK b/third-party/BUCK
index d30eda0..9641cd8 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -20,7 +20,7 @@ rust_library(
 
 rust_library(
     name = "clap",
-    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
     deps = [
         ":bitflags",
diff --git a/third-party/BUILD b/third-party/BUILD
index 7112779..ec896ec 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -25,7 +25,7 @@ rust_library(
 
 rust_library(
     name = "clap",
-    srcs = glob(["vendor/clap-2.33.0/src/**"]),
+    srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
     deps = [
         ":bitflags",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f4daa91..75cfa84 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -40,9 +40,9 @@ checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
 
 [[package]]
 name = "clap"
-version = "2.33.0"
+version = "2.33.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
+checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
 dependencies = [
  "ansi_term",
  "atty",
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.2"
+version = "0.3.3"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.2"
+version = "0.3.3"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.2"
+version = "0.3.3"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.2"
+version = "0.3.3"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -246,18 +246,18 @@ checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
 
 [[package]]
 name = "serde"
-version = "1.0.107"
+version = "1.0.110"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eba7550f2cdf88ffc23ab0f1607133486c390a8c0f89b57e589b9654ee15e04d"
+checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.107"
+version = "1.0.110"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10be45e22e5597d4b88afcc71f9d7bfadcd604bf0c78a3ab4582b8d2b37f39f3"
+checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -266,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.52"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd"
+checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
 dependencies = [
  "itoa",
  "ryu",

From 32ee9d3676ed272138f8a9388567b0f17657f129 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:01:15 +0000
Subject: [PATCH 632/2232] rust::Vec has a bitcopy constructor too


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index d5eae90..12f2839 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -244,7 +244,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    if needs_rust_string {
+    if needs_rust_string || needs_rust_vec {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }

From 8c54eeca6ce3b73f545c8a8dc1735a7690a70fe8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:08:20 +0000
Subject: [PATCH 633/2232] Add missing noexcept on a Slice constructor


---

diff --git a/include/cxx.h b/include/cxx.h
index d870442..8525313 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -98,7 +98,7 @@ public:
   Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
   Slice(const Slice<T> &) noexcept = default;
 
-  Slice(const T *s, size_t size) : repr(Repr{s, size}) {}
+  Slice(const T *s, size_t size) noexcept : repr(Repr{s, size}) {}
 
   Slice &operator=(Slice<T> other) noexcept {
     this->repr = other.repr;

From 1385ca42b2f94cd83b9556452316b5976842da35 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:15:20 +0000
Subject: [PATCH 634/2232] Add missing noexcept on Vec<T>::const_iterator methods


---

diff --git a/include/cxx.h b/include/cxx.h
index 8525313..b56c14a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -243,21 +243,25 @@ public:
         typename std::add_const<T>::type>::type;
     using iterator_category = std::forward_iterator_tag;
 
-    const T &operator*() const { return *static_cast<const T *>(this->pos); }
-    const T *operator->() const { return static_cast<const T *>(this->pos); }
-    const_iterator &operator++() {
+    const T &operator*() const noexcept {
+      return *static_cast<const T *>(this->pos);
+    }
+    const T *operator->() const noexcept {
+      return static_cast<const T *>(this->pos);
+    }
+    const_iterator &operator++() noexcept {
       this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
       return *this;
     }
-    const_iterator operator++(int) {
+    const_iterator operator++(int) noexcept {
       auto ret = const_iterator(*this);
       this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
       return ret;
     }
-    bool operator==(const const_iterator &other) const {
+    bool operator==(const const_iterator &other) const noexcept {
       return this->pos == other.pos;
     }
-    bool operator!=(const const_iterator &other) const {
+    bool operator!=(const const_iterator &other) const noexcept {
       return this->pos != other.pos;
     }
 

From e54f338188c61d6fdddfb8a6454eb786f2bc4201 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:43:20 +0000
Subject: [PATCH 635/2232] Support multiple cxx.h header sections for the same guard


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index be0bd8e..0ed76ac 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,21 +1,42 @@
+use crate::gen::out::OutFile;
 use std::fmt::{self, Display};
 
 pub static HEADER: &str = include_str!("include/cxx.h");
 
-pub fn get(guard: &str) -> &'static str {
+pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {
     let ifndef = format!("#ifndef {}", guard);
+    let define = format!("#define {}", guard);
     let endif = format!("#endif // {}", guard);
-    let begin = find_line(&ifndef);
-    let end = find_line(&endif);
-    if let (Some(begin), Some(end)) = (begin, end) {
-        &HEADER[begin..end + endif.len()]
-    } else {
-        panic!("not found in cxx.h header: {}", guard)
+
+    let mut offset = 0;
+    loop {
+        let begin = find_line(offset, &ifndef);
+        let end = find_line(offset, &endif);
+        if let (Some(begin), Some(end)) = (begin, end) {
+            if !needed {
+                return;
+            }
+            out.next_section();
+            if offset == 0 {
+                writeln!(out, "{}", ifndef);
+                writeln!(out, "{}", define);
+            }
+            for line in HEADER[begin + ifndef.len()..end].trim().lines() {
+                if line != define && !line.trim_start().starts_with("//") {
+                    writeln!(out, "{}", line);
+                }
+            }
+            offset = end + endif.len();
+        } else if offset == 0 {
+            panic!("not found in cxx.h header: {}", guard)
+        } else {
+            writeln!(out, "{}", endif);
+            return;
+        }
     }
 }
 
-fn find_line(line: &str) -> Option<usize> {
-    let mut offset = 0;
+fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     loop {
         offset += HEADER[offset..].find(line)?;
         let rest = &HEADER[offset + line.len()..];
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 12f2839..c06fce9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -249,15 +249,15 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    write_header_section(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
-    write_header_section(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
-    write_header_section(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
-    write_header_section(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
-    write_header_section(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
-    write_header_section(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
-    write_header_section(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
-    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
+    include::write(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
+    include::write(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
+    include::write(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
+    include::write(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
+    include::write(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
+    include::write(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
+    include::write(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
+    include::write(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
+    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();
@@ -311,18 +311,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
-    let section = include::get(section);
-    if needed {
-        out.next_section();
-        for line in section.lines() {
-            if !line.trim_start().starts_with("//") {
-                writeln!(out, "{}", line);
-            }
-        }
-    }
-}
-
 fn write_struct(out: &mut OutFile, strct: &Struct) {
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);

From 2a2b9ad1f527c45b237cef8757ee20bb7b790282 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:43:20 +0000
Subject: [PATCH 636/2232] Move implementation details to the bottom of cxx.h


---

diff --git a/.clang-format b/.clang-format
index 181605d..2085997 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1 +1,2 @@
 AlwaysBreakTemplateDeclarations: true
+MaxEmptyLinesToKeep: 3
diff --git a/include/cxx.h b/include/cxx.h
index b56c14a..9f4fb47 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,13 +15,7 @@
 namespace rust {
 inline namespace cxxbridge03 {
 
-#ifndef CXXBRIDGE03_RUST_BITCOPY
-#define CXXBRIDGE03_RUST_BITCOPY
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE03_RUST_BITCOPY
+struct unsafe_bitcopy_t;
 
 #ifndef CXXBRIDGE03_RUST_STRING
 #define CXXBRIDGE03_RUST_STRING
@@ -91,23 +85,18 @@ private:
 #endif // CXXBRIDGE03_RUST_STR
 
 #ifndef CXXBRIDGE03_RUST_SLICE
-#define CXXBRIDGE03_RUST_SLICE
 template <typename T>
 class Slice final {
 public:
-  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
-  Slice(const Slice<T> &) noexcept = default;
-
-  Slice(const T *s, size_t size) noexcept : repr(Repr{s, size}) {}
+  Slice() noexcept;
+  Slice(const Slice<T> &) noexcept;
+  Slice(const T *, size_t count) noexcept;
 
-  Slice &operator=(Slice<T> other) noexcept {
-    this->repr = other.repr;
-    return *this;
-  }
+  Slice &operator=(Slice<T>) noexcept;
 
-  const T *data() const noexcept { return this->repr.ptr; }
-  size_t size() const noexcept { return this->repr.len; }
-  size_t length() const noexcept { return this->repr.len; }
+  const T *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
 
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
@@ -118,8 +107,8 @@ public:
     const T *ptr;
     size_t len;
   };
-  Slice(Repr repr_) noexcept : repr(repr_) {}
-  explicit operator Repr() noexcept { return this->repr; }
+  Slice(Repr) noexcept;
+  explicit operator Repr() noexcept;
 
 private:
   Repr repr;
@@ -127,7 +116,6 @@ private:
 #endif // CXXBRIDGE03_RUST_SLICE
 
 #ifndef CXXBRIDGE03_RUST_BOX
-#define CXXBRIDGE03_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -136,70 +124,32 @@ public:
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
 
-  Box(const Box &other) : Box(*other) {}
-  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  explicit Box(const T &val) {
-    this->uninit();
-    ::new (this->ptr) T(val);
-  }
-  explicit Box(T &&val) {
-    this->uninit();
-    ::new (this->ptr) T(std::move(val));
-  }
-  Box &operator=(const Box &other) {
-    if (this != &other) {
-      if (this->ptr) {
-        **this = *other;
-      } else {
-        this->uninit();
-        ::new (this->ptr) T(*other);
-      }
-    }
-    return *this;
-  }
-  Box &operator=(Box &&other) noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-    this->ptr = other.ptr;
-    other.ptr = nullptr;
-    return *this;
-  }
-  ~Box() noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-  }
+  Box(const Box &);
+  Box(Box &&) noexcept;
+  ~Box() noexcept;
 
-  const T *operator->() const noexcept { return this->ptr; }
-  const T &operator*() const noexcept { return *this->ptr; }
-  T *operator->() noexcept { return this->ptr; }
-  T &operator*() noexcept { return *this->ptr; }
+  explicit Box(const T &);
+  explicit Box(T &&);
+
+  Box &operator=(const Box &);
+  Box &operator=(Box &&) noexcept;
+
+  const T *operator->() const noexcept;
+  const T &operator*() const noexcept;
+  T *operator->() noexcept;
+  T &operator*() noexcept;
 
   template <typename... Fields>
-  static Box in_place(Fields &&... fields) {
-    Box box;
-    box.uninit();
-    ::new (box.ptr) T{std::forward<Fields>(fields)...};
-    return box;
-  }
+  static Box in_place(Fields &&...);
 
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
-  static Box from_raw(T *raw) noexcept {
-    Box box;
-    box.ptr = raw;
-    return box;
-  }
+  static Box from_raw(T *) noexcept;
 
-  T *into_raw() noexcept {
-    T *raw = this->ptr;
-    this->ptr = nullptr;
-    return raw;
-  }
+  T *into_raw() noexcept;
 
 private:
-  Box() noexcept {}
+  Box() noexcept;
   void uninit() noexcept;
   void drop() noexcept;
   T *ptr;
@@ -207,30 +157,19 @@ private:
 #endif // CXXBRIDGE03_RUST_BOX
 
 #ifndef CXXBRIDGE03_RUST_VEC
-#define CXXBRIDGE03_RUST_VEC
 template <typename T>
 class Vec final {
 public:
   using value_type = T;
 
   Vec() noexcept;
-  Vec(Vec &&other) noexcept {
-    this->repr = other.repr;
-    new (&other) Vec();
-  }
-  ~Vec() noexcept { this->drop(); }
+  Vec(Vec &&) noexcept;
+  ~Vec() noexcept;
 
-  Vec &operator=(Vec &&other) noexcept {
-    if (this != &other) {
-      this->drop();
-      this->repr = other.repr;
-      new (&other) Vec();
-    }
-    return *this;
-  }
+  Vec &operator=(Vec &&) noexcept;
 
   size_t size() const noexcept;
-  bool empty() const noexcept { return size() == 0; }
+  bool empty() const noexcept;
   const T *data() const noexcept;
 
   class const_iterator {
@@ -243,27 +182,12 @@ public:
         typename std::add_const<T>::type>::type;
     using iterator_category = std::forward_iterator_tag;
 
-    const T &operator*() const noexcept {
-      return *static_cast<const T *>(this->pos);
-    }
-    const T *operator->() const noexcept {
-      return static_cast<const T *>(this->pos);
-    }
-    const_iterator &operator++() noexcept {
-      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-      return *this;
-    }
-    const_iterator operator++(int) noexcept {
-      auto ret = const_iterator(*this);
-      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-      return ret;
-    }
-    bool operator==(const const_iterator &other) const noexcept {
-      return this->pos == other.pos;
-    }
-    bool operator!=(const const_iterator &other) const noexcept {
-      return this->pos != other.pos;
-    }
+    const T &operator*() const noexcept;
+    const T *operator->() const noexcept;
+    const_iterator &operator++() noexcept;
+    const_iterator operator++(int) noexcept;
+    bool operator==(const const_iterator &) const noexcept;
+    bool operator!=(const const_iterator &) const noexcept;
 
   private:
     friend class Vec;
@@ -271,20 +195,11 @@ public:
     size_t stride;
   };
 
-  const_iterator begin() const noexcept {
-    const_iterator it;
-    it.pos = this->data();
-    it.stride = this->stride();
-    return it;
-  }
-  const_iterator end() const noexcept {
-    const_iterator it = this->begin();
-    it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
-    return it;
-  }
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
 
   // Internal API only intended for the cxxbridge code generator.
-  Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+  Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
 private:
   static size_t stride() noexcept;
@@ -353,6 +268,11 @@ using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
 
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// end public API, begin implementation details
+
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -363,5 +283,238 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 
+#ifndef CXXBRIDGE03_RUST_BITCOPY
+#define CXXBRIDGE03_RUST_BITCOPY
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+#endif // CXXBRIDGE03_RUST_BITCOPY
+
+#ifndef CXXBRIDGE03_RUST_SLICE
+#define CXXBRIDGE03_RUST_SLICE
+template <typename T>
+Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+
+template <typename T>
+Slice<T>::Slice(const Slice<T> &) noexcept = default;
+
+template <typename T>
+Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
+
+template <typename T>
+Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
+  this->repr = other.repr;
+  return *this;
+}
+
+template <typename T>
+const T *Slice<T>::data() const noexcept {
+  return this->repr.ptr;
+}
+
+template <typename T>
+size_t Slice<T>::size() const noexcept {
+  return this->repr.len;
+}
+
+template <typename T>
+size_t Slice<T>::length() const noexcept {
+  return this->repr.len;
+}
+
+template <typename T>
+Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
+
+template <typename T>
+Slice<T>::operator Repr() noexcept {
+  return this->repr;
+}
+#endif // CXXBRIDGE03_RUST_SLICE
+
+#ifndef CXXBRIDGE03_RUST_BOX
+#define CXXBRIDGE03_RUST_BOX
+template <typename T>
+Box<T>::Box(const Box &other) : Box(*other) {}
+
+template <typename T>
+Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
+  other.ptr = nullptr;
+}
+
+template <typename T>
+Box<T>::Box(const T &val) {
+  this->uninit();
+  ::new (this->ptr) T(val);
+}
+
+template <typename T>
+Box<T>::Box(T &&val) {
+  this->uninit();
+  ::new (this->ptr) T(std::move(val));
+}
+
+template <typename T>
+Box<T>::~Box() noexcept {
+  if (this->ptr) {
+    this->drop();
+  }
+}
+
+template <typename T>
+Box<T> &Box<T>::operator=(const Box &other) {
+  if (this != &other) {
+    if (this->ptr) {
+      **this = *other;
+    } else {
+      this->uninit();
+      ::new (this->ptr) T(*other);
+    }
+  }
+  return *this;
+}
+
+template <typename T>
+Box<T> &Box<T>::operator=(Box &&other) noexcept {
+  if (this->ptr) {
+    this->drop();
+  }
+  this->ptr = other.ptr;
+  other.ptr = nullptr;
+  return *this;
+}
+
+template <typename T>
+const T *Box<T>::operator->() const noexcept {
+  return this->ptr;
+}
+
+template <typename T>
+const T &Box<T>::operator*() const noexcept {
+  return *this->ptr;
+}
+
+template <typename T>
+T *Box<T>::operator->() noexcept {
+  return this->ptr;
+}
+
+template <typename T>
+T &Box<T>::operator*() noexcept {
+  return *this->ptr;
+}
+
+template <typename T>
+template <typename... Fields>
+Box<T> Box<T>::in_place(Fields &&... fields) {
+  Box box;
+  box.uninit();
+  ::new (box.ptr) T{std::forward<Fields>(fields)...};
+  return box;
+}
+
+template <typename T>
+Box<T> Box<T>::from_raw(T *raw) noexcept {
+  Box box;
+  box.ptr = raw;
+  return box;
+}
+
+template <typename T>
+T *Box<T>::into_raw() noexcept {
+  T *raw = this->ptr;
+  this->ptr = nullptr;
+  return raw;
+}
+
+template <typename T>
+Box<T>::Box() noexcept {}
+#endif // CXXBRIDGE03_RUST_BOX
+
+#ifndef CXXBRIDGE03_RUST_VEC
+#define CXXBRIDGE03_RUST_VEC
+template <typename T>
+Vec<T>::Vec(Vec &&other) noexcept {
+  this->repr = other.repr;
+  new (&other) Vec();
+}
+
+template <typename T>
+Vec<T>::~Vec() noexcept {
+  this->drop();
+}
+
+template <typename T>
+Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
+  if (this != &other) {
+    this->drop();
+    this->repr = other.repr;
+    new (&other) Vec();
+  }
+  return *this;
+}
+
+template <typename T>
+bool Vec<T>::empty() const noexcept {
+  return size() == 0;
+}
+
+template <typename T>
+const T &Vec<T>::const_iterator::operator*() const noexcept {
+  return *static_cast<const T *>(this->pos);
+}
+
+template <typename T>
+const T *Vec<T>::const_iterator::operator->() const noexcept {
+  return static_cast<const T *>(this->pos);
+}
+
+template <typename T>
+typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
+  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator
+Vec<T>::const_iterator::operator++(int) noexcept {
+  auto ret = const_iterator(*this);
+  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+  return ret;
+}
+
+template <typename T>
+bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
+    noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
+    noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
+  const_iterator it;
+  it.pos = this->data();
+  it.stride = this->stride();
+  return it;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
+  const_iterator it = this->begin();
+  it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+  return it;
+}
+
+// Internal API only intended for the cxxbridge code generator.
+template <typename T>
+Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+#endif // CXXBRIDGE03_RUST_VEC
+
 } // namespace cxxbridge03
 } // namespace rust

From 9846d08d40d69ca36be4d4b6b757e80b596d7079 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 03:59:17 +0000
Subject: [PATCH 637/2232] Merge pull request #206 from dtolnay/include


Move all function implementations to the bottom of cxx.h
---

diff --git a/.clang-format b/.clang-format
index 181605d..2085997 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1 +1,2 @@
 AlwaysBreakTemplateDeclarations: true
+MaxEmptyLinesToKeep: 3
diff --git a/gen/src/include.rs b/gen/src/include.rs
index be0bd8e..0ed76ac 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,21 +1,42 @@
+use crate::gen::out::OutFile;
 use std::fmt::{self, Display};
 
 pub static HEADER: &str = include_str!("include/cxx.h");
 
-pub fn get(guard: &str) -> &'static str {
+pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {
     let ifndef = format!("#ifndef {}", guard);
+    let define = format!("#define {}", guard);
     let endif = format!("#endif // {}", guard);
-    let begin = find_line(&ifndef);
-    let end = find_line(&endif);
-    if let (Some(begin), Some(end)) = (begin, end) {
-        &HEADER[begin..end + endif.len()]
-    } else {
-        panic!("not found in cxx.h header: {}", guard)
+
+    let mut offset = 0;
+    loop {
+        let begin = find_line(offset, &ifndef);
+        let end = find_line(offset, &endif);
+        if let (Some(begin), Some(end)) = (begin, end) {
+            if !needed {
+                return;
+            }
+            out.next_section();
+            if offset == 0 {
+                writeln!(out, "{}", ifndef);
+                writeln!(out, "{}", define);
+            }
+            for line in HEADER[begin + ifndef.len()..end].trim().lines() {
+                if line != define && !line.trim_start().starts_with("//") {
+                    writeln!(out, "{}", line);
+                }
+            }
+            offset = end + endif.len();
+        } else if offset == 0 {
+            panic!("not found in cxx.h header: {}", guard)
+        } else {
+            writeln!(out, "{}", endif);
+            return;
+        }
     }
 }
 
-fn find_line(line: &str) -> Option<usize> {
-    let mut offset = 0;
+fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     loop {
         offset += HEADER[offset..].find(line)?;
         let rest = &HEADER[offset + line.len()..];
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 12f2839..c06fce9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -249,15 +249,15 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    write_header_section(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
-    write_header_section(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
-    write_header_section(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
-    write_header_section(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
-    write_header_section(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
-    write_header_section(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
-    write_header_section(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
-    write_header_section(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
-    write_header_section(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
+    include::write(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
+    include::write(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
+    include::write(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
+    include::write(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
+    include::write(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
+    include::write(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
+    include::write(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
+    include::write(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
+    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();
@@ -311,18 +311,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_header_section(out: &mut OutFile, needed: bool, section: &str) {
-    let section = include::get(section);
-    if needed {
-        out.next_section();
-        for line in section.lines() {
-            if !line.trim_start().starts_with("//") {
-                writeln!(out, "{}", line);
-            }
-        }
-    }
-}
-
 fn write_struct(out: &mut OutFile, strct: &Struct) {
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
diff --git a/include/cxx.h b/include/cxx.h
index b56c14a..9f4fb47 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,13 +15,7 @@
 namespace rust {
 inline namespace cxxbridge03 {
 
-#ifndef CXXBRIDGE03_RUST_BITCOPY
-#define CXXBRIDGE03_RUST_BITCOPY
-struct unsafe_bitcopy_t {
-  explicit unsafe_bitcopy_t() = default;
-};
-constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE03_RUST_BITCOPY
+struct unsafe_bitcopy_t;
 
 #ifndef CXXBRIDGE03_RUST_STRING
 #define CXXBRIDGE03_RUST_STRING
@@ -91,23 +85,18 @@ private:
 #endif // CXXBRIDGE03_RUST_STR
 
 #ifndef CXXBRIDGE03_RUST_SLICE
-#define CXXBRIDGE03_RUST_SLICE
 template <typename T>
 class Slice final {
 public:
-  Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
-  Slice(const Slice<T> &) noexcept = default;
-
-  Slice(const T *s, size_t size) noexcept : repr(Repr{s, size}) {}
+  Slice() noexcept;
+  Slice(const Slice<T> &) noexcept;
+  Slice(const T *, size_t count) noexcept;
 
-  Slice &operator=(Slice<T> other) noexcept {
-    this->repr = other.repr;
-    return *this;
-  }
+  Slice &operator=(Slice<T>) noexcept;
 
-  const T *data() const noexcept { return this->repr.ptr; }
-  size_t size() const noexcept { return this->repr.len; }
-  size_t length() const noexcept { return this->repr.len; }
+  const T *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
 
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
@@ -118,8 +107,8 @@ public:
     const T *ptr;
     size_t len;
   };
-  Slice(Repr repr_) noexcept : repr(repr_) {}
-  explicit operator Repr() noexcept { return this->repr; }
+  Slice(Repr) noexcept;
+  explicit operator Repr() noexcept;
 
 private:
   Repr repr;
@@ -127,7 +116,6 @@ private:
 #endif // CXXBRIDGE03_RUST_SLICE
 
 #ifndef CXXBRIDGE03_RUST_BOX
-#define CXXBRIDGE03_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -136,70 +124,32 @@ public:
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
 
-  Box(const Box &other) : Box(*other) {}
-  Box(Box &&other) noexcept : ptr(other.ptr) { other.ptr = nullptr; }
-  explicit Box(const T &val) {
-    this->uninit();
-    ::new (this->ptr) T(val);
-  }
-  explicit Box(T &&val) {
-    this->uninit();
-    ::new (this->ptr) T(std::move(val));
-  }
-  Box &operator=(const Box &other) {
-    if (this != &other) {
-      if (this->ptr) {
-        **this = *other;
-      } else {
-        this->uninit();
-        ::new (this->ptr) T(*other);
-      }
-    }
-    return *this;
-  }
-  Box &operator=(Box &&other) noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-    this->ptr = other.ptr;
-    other.ptr = nullptr;
-    return *this;
-  }
-  ~Box() noexcept {
-    if (this->ptr) {
-      this->drop();
-    }
-  }
+  Box(const Box &);
+  Box(Box &&) noexcept;
+  ~Box() noexcept;
 
-  const T *operator->() const noexcept { return this->ptr; }
-  const T &operator*() const noexcept { return *this->ptr; }
-  T *operator->() noexcept { return this->ptr; }
-  T &operator*() noexcept { return *this->ptr; }
+  explicit Box(const T &);
+  explicit Box(T &&);
+
+  Box &operator=(const Box &);
+  Box &operator=(Box &&) noexcept;
+
+  const T *operator->() const noexcept;
+  const T &operator*() const noexcept;
+  T *operator->() noexcept;
+  T &operator*() noexcept;
 
   template <typename... Fields>
-  static Box in_place(Fields &&... fields) {
-    Box box;
-    box.uninit();
-    ::new (box.ptr) T{std::forward<Fields>(fields)...};
-    return box;
-  }
+  static Box in_place(Fields &&...);
 
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
-  static Box from_raw(T *raw) noexcept {
-    Box box;
-    box.ptr = raw;
-    return box;
-  }
+  static Box from_raw(T *) noexcept;
 
-  T *into_raw() noexcept {
-    T *raw = this->ptr;
-    this->ptr = nullptr;
-    return raw;
-  }
+  T *into_raw() noexcept;
 
 private:
-  Box() noexcept {}
+  Box() noexcept;
   void uninit() noexcept;
   void drop() noexcept;
   T *ptr;
@@ -207,30 +157,19 @@ private:
 #endif // CXXBRIDGE03_RUST_BOX
 
 #ifndef CXXBRIDGE03_RUST_VEC
-#define CXXBRIDGE03_RUST_VEC
 template <typename T>
 class Vec final {
 public:
   using value_type = T;
 
   Vec() noexcept;
-  Vec(Vec &&other) noexcept {
-    this->repr = other.repr;
-    new (&other) Vec();
-  }
-  ~Vec() noexcept { this->drop(); }
+  Vec(Vec &&) noexcept;
+  ~Vec() noexcept;
 
-  Vec &operator=(Vec &&other) noexcept {
-    if (this != &other) {
-      this->drop();
-      this->repr = other.repr;
-      new (&other) Vec();
-    }
-    return *this;
-  }
+  Vec &operator=(Vec &&) noexcept;
 
   size_t size() const noexcept;
-  bool empty() const noexcept { return size() == 0; }
+  bool empty() const noexcept;
   const T *data() const noexcept;
 
   class const_iterator {
@@ -243,27 +182,12 @@ public:
         typename std::add_const<T>::type>::type;
     using iterator_category = std::forward_iterator_tag;
 
-    const T &operator*() const noexcept {
-      return *static_cast<const T *>(this->pos);
-    }
-    const T *operator->() const noexcept {
-      return static_cast<const T *>(this->pos);
-    }
-    const_iterator &operator++() noexcept {
-      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-      return *this;
-    }
-    const_iterator operator++(int) noexcept {
-      auto ret = const_iterator(*this);
-      this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-      return ret;
-    }
-    bool operator==(const const_iterator &other) const noexcept {
-      return this->pos == other.pos;
-    }
-    bool operator!=(const const_iterator &other) const noexcept {
-      return this->pos != other.pos;
-    }
+    const T &operator*() const noexcept;
+    const T *operator->() const noexcept;
+    const_iterator &operator++() noexcept;
+    const_iterator operator++(int) noexcept;
+    bool operator==(const const_iterator &) const noexcept;
+    bool operator!=(const const_iterator &) const noexcept;
 
   private:
     friend class Vec;
@@ -271,20 +195,11 @@ public:
     size_t stride;
   };
 
-  const_iterator begin() const noexcept {
-    const_iterator it;
-    it.pos = this->data();
-    it.stride = this->stride();
-    return it;
-  }
-  const_iterator end() const noexcept {
-    const_iterator it = this->begin();
-    it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
-    return it;
-  }
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
 
   // Internal API only intended for the cxxbridge code generator.
-  Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+  Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
 private:
   static size_t stride() noexcept;
@@ -353,6 +268,11 @@ using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
 
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// end public API, begin implementation details
+
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -363,5 +283,238 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 
+#ifndef CXXBRIDGE03_RUST_BITCOPY
+#define CXXBRIDGE03_RUST_BITCOPY
+struct unsafe_bitcopy_t {
+  explicit unsafe_bitcopy_t() = default;
+};
+
+constexpr unsafe_bitcopy_t unsafe_bitcopy{};
+#endif // CXXBRIDGE03_RUST_BITCOPY
+
+#ifndef CXXBRIDGE03_RUST_SLICE
+#define CXXBRIDGE03_RUST_SLICE
+template <typename T>
+Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+
+template <typename T>
+Slice<T>::Slice(const Slice<T> &) noexcept = default;
+
+template <typename T>
+Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
+
+template <typename T>
+Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
+  this->repr = other.repr;
+  return *this;
+}
+
+template <typename T>
+const T *Slice<T>::data() const noexcept {
+  return this->repr.ptr;
+}
+
+template <typename T>
+size_t Slice<T>::size() const noexcept {
+  return this->repr.len;
+}
+
+template <typename T>
+size_t Slice<T>::length() const noexcept {
+  return this->repr.len;
+}
+
+template <typename T>
+Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
+
+template <typename T>
+Slice<T>::operator Repr() noexcept {
+  return this->repr;
+}
+#endif // CXXBRIDGE03_RUST_SLICE
+
+#ifndef CXXBRIDGE03_RUST_BOX
+#define CXXBRIDGE03_RUST_BOX
+template <typename T>
+Box<T>::Box(const Box &other) : Box(*other) {}
+
+template <typename T>
+Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
+  other.ptr = nullptr;
+}
+
+template <typename T>
+Box<T>::Box(const T &val) {
+  this->uninit();
+  ::new (this->ptr) T(val);
+}
+
+template <typename T>
+Box<T>::Box(T &&val) {
+  this->uninit();
+  ::new (this->ptr) T(std::move(val));
+}
+
+template <typename T>
+Box<T>::~Box() noexcept {
+  if (this->ptr) {
+    this->drop();
+  }
+}
+
+template <typename T>
+Box<T> &Box<T>::operator=(const Box &other) {
+  if (this != &other) {
+    if (this->ptr) {
+      **this = *other;
+    } else {
+      this->uninit();
+      ::new (this->ptr) T(*other);
+    }
+  }
+  return *this;
+}
+
+template <typename T>
+Box<T> &Box<T>::operator=(Box &&other) noexcept {
+  if (this->ptr) {
+    this->drop();
+  }
+  this->ptr = other.ptr;
+  other.ptr = nullptr;
+  return *this;
+}
+
+template <typename T>
+const T *Box<T>::operator->() const noexcept {
+  return this->ptr;
+}
+
+template <typename T>
+const T &Box<T>::operator*() const noexcept {
+  return *this->ptr;
+}
+
+template <typename T>
+T *Box<T>::operator->() noexcept {
+  return this->ptr;
+}
+
+template <typename T>
+T &Box<T>::operator*() noexcept {
+  return *this->ptr;
+}
+
+template <typename T>
+template <typename... Fields>
+Box<T> Box<T>::in_place(Fields &&... fields) {
+  Box box;
+  box.uninit();
+  ::new (box.ptr) T{std::forward<Fields>(fields)...};
+  return box;
+}
+
+template <typename T>
+Box<T> Box<T>::from_raw(T *raw) noexcept {
+  Box box;
+  box.ptr = raw;
+  return box;
+}
+
+template <typename T>
+T *Box<T>::into_raw() noexcept {
+  T *raw = this->ptr;
+  this->ptr = nullptr;
+  return raw;
+}
+
+template <typename T>
+Box<T>::Box() noexcept {}
+#endif // CXXBRIDGE03_RUST_BOX
+
+#ifndef CXXBRIDGE03_RUST_VEC
+#define CXXBRIDGE03_RUST_VEC
+template <typename T>
+Vec<T>::Vec(Vec &&other) noexcept {
+  this->repr = other.repr;
+  new (&other) Vec();
+}
+
+template <typename T>
+Vec<T>::~Vec() noexcept {
+  this->drop();
+}
+
+template <typename T>
+Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
+  if (this != &other) {
+    this->drop();
+    this->repr = other.repr;
+    new (&other) Vec();
+  }
+  return *this;
+}
+
+template <typename T>
+bool Vec<T>::empty() const noexcept {
+  return size() == 0;
+}
+
+template <typename T>
+const T &Vec<T>::const_iterator::operator*() const noexcept {
+  return *static_cast<const T *>(this->pos);
+}
+
+template <typename T>
+const T *Vec<T>::const_iterator::operator->() const noexcept {
+  return static_cast<const T *>(this->pos);
+}
+
+template <typename T>
+typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
+  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator
+Vec<T>::const_iterator::operator++(int) noexcept {
+  auto ret = const_iterator(*this);
+  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
+  return ret;
+}
+
+template <typename T>
+bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
+    noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
+    noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
+  const_iterator it;
+  it.pos = this->data();
+  it.stride = this->stride();
+  return it;
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
+  const_iterator it = this->begin();
+  it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+  return it;
+}
+
+// Internal API only intended for the cxxbridge code generator.
+template <typename T>
+Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
+#endif // CXXBRIDGE03_RUST_VEC
+
 } // namespace cxxbridge03
 } // namespace rust

From dd3af090b78e861a786a6d9056ce60a0b6aa6854 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 13 2020 05:19:46 +0000
Subject: [PATCH 638/2232] Try out new style of readme badges


---

diff --git a/README.md b/README.md
index 5fd02a9..768b394 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,10 @@
 CXX &mdash; safe FFI between Rust and C++
 =========================================
 
-[![Build Status](https://img.shields.io/github/workflow/status/dtolnay/cxx/CI/master)](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster)
-[![Latest Version](https://img.shields.io/crates/v/cxx.svg)](https://crates.io/crates/cxx)
-[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/cxx)
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/cxx-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/cxx)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/cxx.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/cxx)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/cxx)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/cxx/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster)
 
 This library provides a **safe** mechanism for calling C++ code from Rust and
 Rust code from C++, not subject to the many ways that things can go wrong when

From d963bf97b78a53a09a034eb635f27d285b914387 Mon Sep 17 00:00:00 2001
From: Myron Ahn <myronahn@gmail.com>
Date: May 17 2020 05:32:42 +0000
Subject: [PATCH 639/2232] Fix for when std::os::raw::c_char is u8 (armv7)


---

diff --git a/tests/test.rs b/tests/test.rs
index ddf8f70..91bd25e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -141,7 +141,7 @@ fn test_c_call_r() {
         }
         let failure = unsafe { cxx_run_test() };
         if !failure.is_null() {
-            let msg = unsafe { CStr::from_ptr(failure) };
+            let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) };
             eprintln!("{}", msg.to_string_lossy());
         }
     }

From ecafa897c1f54cbc69c79ae045fe4150d8e8af44 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 17 2020 07:35:49 +0000
Subject: [PATCH 640/2232] Merge pull request #209 from myronahn/master


Fix for when std::os::raw::c_char is u8 (armv7)
---

diff --git a/tests/test.rs b/tests/test.rs
index ddf8f70..91bd25e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -141,7 +141,7 @@ fn test_c_call_r() {
         }
         let failure = unsafe { cxx_run_test() };
         if !failure.is_null() {
-            let msg = unsafe { CStr::from_ptr(failure) };
+            let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) };
             eprintln!("{}", msg.to_string_lossy());
         }
     }

From ef8fd19a3bbb5098ea13021073daf9a840c6bcc1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 22 2020 08:27:30 +0000
Subject: [PATCH 641/2232] Account for character based offsets in proc-macro2


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 98b3497..a5878b9 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,7 +13,7 @@ categories = ["development-tools::ffi"]
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.14", features = ["span-locations"] }
 quote = "1.0"
 syn = { version = "1.0.20", features = ["full"] }
 
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index ddf27c5..919d5c8 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -16,7 +16,7 @@ path = "src/main.rs"
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.12", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.14", features = ["span-locations"] }
 quote = "1.0"
 structopt = "0.3"
 syn = { version = "1.0.20", features = ["full"] }
diff --git a/gen/src/error.rs b/gen/src/error.rs
index b91c166..51dbbe7 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -88,17 +88,26 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err
     for _ in 1..start.line {
         start_offset += source[start_offset..].find('\n').unwrap() + 1;
     }
-    start_offset += start.column;
+    let start_column = source[start_offset..]
+        .chars()
+        .take(start.column)
+        .map(char::len_utf8)
+        .sum::<usize>();
+    start_offset += start_column;
 
     let mut end_offset = start_offset;
     if start.line == end.line {
-        end_offset -= start.column;
+        end_offset -= start_column;
     } else {
         for _ in 0..end.line - start.line {
             end_offset += source[end_offset..].find('\n').unwrap() + 1;
         }
     }
-    end_offset += end.column;
+    end_offset += source[end_offset..]
+        .chars()
+        .take(end.column)
+        .map(char::len_utf8)
+        .sum::<usize>();
 
     let mut files = SimpleFiles::new();
     let file = files.add(path.to_string_lossy(), source);
diff --git a/third-party/BUCK b/third-party/BUCK
index 9641cd8..cc64883 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.12/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.14/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
diff --git a/third-party/BUILD b/third-party/BUILD
index ec896ec..313481e 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.12/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.14/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 75cfa84..6e3a5b9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -211,9 +211,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.12"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
+checksum = "de40dd4ff82d9c9bab6dae29dbab1167e515f8df9ed17d2987cb6012db206933"
 dependencies = [
  "unicode-xid",
 ]

From e3b78ea4092bd52202168fd27ee888259e5f3a1e Mon Sep 17 00:00:00 2001
From: myronahn <myronahn@gmail.com>
Date: May 22 2020 18:08:13 +0000
Subject: [PATCH 642/2232] Fix issue with indirect return for C++ member function w/no args



---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index c06fce9..2cf9faf 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -424,7 +424,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
     }
     let indirect_return = indirect_return(efn, types);
     if indirect_return {
-        if !efn.args.is_empty() {
+        if !efn.args.is_empty() || efn.receiver.is_some() {
             write!(out, ", ");
         }
         write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
diff --git a/src/exception.rs b/src/exception.rs
index 125e484..e16916a 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,7 +1,7 @@
 use std::fmt::{self, Debug, Display};
 
 /// Exception thrown from an `extern "C"` function.
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 pub struct Exception {
     pub(crate) what: Box<str>,
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d4e96fc..51716e0 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -83,6 +83,8 @@ pub mod ffi {
         fn set(self: &mut C, n: usize) -> usize;
         fn get2(&self) -> usize;
         fn set2(&mut self, n: usize) -> usize;
+        fn set_succeed(&mut self, n: usize) -> Result<usize>;
+        fn get_fail(&mut self) -> Result<usize>;
     }
 
     extern "C" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index af7a4a0..677a55d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -28,6 +28,10 @@ size_t C::set2(size_t n) {
   return this->n;
 }
 
+size_t C::set_succeed(size_t n) { return this->set2(n); }
+
+size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
+
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
 size_t c_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 1173a0a..c1a08d2 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -16,6 +16,8 @@ public:
   size_t set(size_t n);
   size_t get2() const;
   size_t set2(size_t n);
+  size_t set_succeed(size_t n);
+  size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
 
 private:
diff --git a/tests/test.rs b/tests/test.rs
index 91bd25e..836e2d3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -157,7 +157,9 @@ fn test_c_method_calls() {
     assert_eq!(2021, unique_ptr.set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(old_value, unique_ptr.set2(old_value));
-    assert_eq!(old_value, unique_ptr.get2())
+    assert_eq!(old_value, unique_ptr.get2());
+    assert_eq!(Ok(2022), unique_ptr.set_succeed(2022));
+    assert!(unique_ptr.get_fail().is_err());
 }
 
 #[test]

From eedf737d91722868277c0aadc34e5a2c880ed00a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 22 2020 18:08:50 +0000
Subject: [PATCH 643/2232] Revert exception change from PR 210


---

diff --git a/src/exception.rs b/src/exception.rs
index e16916a..125e484 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,7 +1,7 @@
 use std::fmt::{self, Debug, Display};
 
 /// Exception thrown from an `extern "C"` function.
-#[derive(Debug, PartialEq)]
+#[derive(Debug)]
 pub struct Exception {
     pub(crate) what: Box<str>,
 }

From ae7143655df336a0bd44f7f4c41d93142298df33 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 22 2020 18:12:35 +0000
Subject: [PATCH 644/2232] Test c method calls without needing PartialEq on Exception


---

diff --git a/tests/test.rs b/tests/test.rs
index 836e2d3..ecfec84 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -158,7 +158,7 @@ fn test_c_method_calls() {
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(old_value, unique_ptr.set2(old_value));
     assert_eq!(old_value, unique_ptr.get2());
-    assert_eq!(Ok(2022), unique_ptr.set_succeed(2022));
+    assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
     assert!(unique_ptr.get_fail().is_err());
 }
 

From 2de2e17bc9c94c86d4362cd2116c9f58e424dbfc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 22 2020 18:12:35 +0000
Subject: [PATCH 645/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index cc64883..c64e728 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -2,7 +2,7 @@
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.28/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.31/src/**"]),
     visibility = ["PUBLIC"],
     features = ["std"],
 )
@@ -14,7 +14,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.52/src/**"]),
+    srcs = glob(["vendor/cc-1.0.54/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.3/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.4/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.14/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.15/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -99,7 +99,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.4/src/**"]),
+    srcs = glob(["vendor/quote-1.0.6/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.20/src/**"]),
+    srcs = glob(["vendor/syn-1.0.23/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 313481e..abdebd6 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -7,7 +7,7 @@ load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.28/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.31/src/**"]),
     crate_features = ["std"],
     visibility = ["//visibility:public"],
 )
@@ -19,7 +19,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.52/src/**"]),
+    srcs = glob(["vendor/cc-1.0.54/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -36,7 +36,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.3/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.4/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.14/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.15/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -104,7 +104,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.4/src/**"]),
+    srcs = glob(["vendor/quote-1.0.6/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.20/src/**"]),
+    srcs = glob(["vendor/syn-1.0.23/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6e3a5b9..906d7fd 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -11,9 +11,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.28"
+version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
+checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
 
 [[package]]
 name = "atty"
@@ -34,9 +34,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.52"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
+checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
 
 [[package]]
 name = "clap"
@@ -55,9 +55,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5680df8512a0e825b9edc41b619ec88b367644d394b4d862a04b4d6387c65da"
+checksum = "2ceface2475f2f57a7ece9ba239b96e06bda8323ee68aa6df539752f13a74f60"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -149,9 +149,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.12"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
+checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
 dependencies = [
  "libc",
 ]
@@ -170,9 +170,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.69"
+version = "0.2.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
+checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
 
 [[package]]
 name = "link-cplusplus"
@@ -211,18 +211,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de40dd4ff82d9c9bab6dae29dbab1167e515f8df9ed17d2987cb6012db206933"
+checksum = "70a50b9351bfa8d65a7d93ce712dc63d2fd15ddbf2c36990fc7cac344859c04f"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
+checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
 dependencies = [
  "proc-macro2",
 ]
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.20"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd1b5e337360b1fae433c59fcafa0c6b77c605e92540afa5221a7b81a9eca91d"
+checksum = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269"
 dependencies = [
  "proc-macro2",
  "quote",

From 57d3c68a23833dde3fc86734fefdb5476a539fa8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 22 2020 18:13:47 +0000
Subject: [PATCH 646/2232] Release 0.3.4


---

diff --git a/Cargo.toml b/Cargo.toml
index 204a1c9..6a8c1a4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.3" # remember to update html_root_url
+version = "0.3.4" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -19,14 +19,14 @@ default = [] # c++11
 "c++17" = []
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.3", path = "macro" }
+cxxbridge-macro = { version = "=0.3.4", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.3", path = "gen/build" }
+cxx-build = { version = "=0.3.4", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.27", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index a5878b9..c6dab56 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.3"
+version = "0.3.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 919d5c8..0609dc6 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.3"
+version = "0.3.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e4d35b8..21c4318 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.3"
+version = "0.3.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index a657af7..0ad7255 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.3")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 906d7fd..d58fb5e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "anyhow",
  "codespan-reporting",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "cxx",
  "proc-macro2",

From caef2b9589bee04c2f683241c610af8efba2a8d3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 23 2020 21:58:20 +0000
Subject: [PATCH 647/2232] Remove dependency on proc-macro2/proc-macro feature


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index c6dab56..b43a37e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,9 +13,9 @@ categories = ["development-tools::ffi"]
 anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.14", features = ["span-locations"] }
-quote = "1.0"
-syn = { version = "1.0.20", features = ["full"] }
+proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
+quote = { version = "1.0", default-features = false }
+syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 0609dc6..7a80a2f 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -16,10 +16,10 @@ path = "src/main.rs"
 [dependencies]
 anyhow = "1.0"
 codespan-reporting = "0.9"
-proc-macro2 = { version = "1.0.14", features = ["span-locations"] }
-quote = "1.0"
+proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
+quote = { version = "1.0", default-features = false }
 structopt = "0.3"
-syn = { version = "1.0.20", features = ["full"] }
+syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/third-party/BUCK b/third-party/BUCK
index c64e728..479fbfc 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.15/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.17/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
diff --git a/third-party/BUILD b/third-party/BUILD
index abdebd6..8734f30 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.15/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.17/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index d58fb5e..0ca0a3c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -211,9 +211,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.15"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70a50b9351bfa8d65a7d93ce712dc63d2fd15ddbf2c36990fc7cac344859c04f"
+checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
 dependencies = [
  "unicode-xid",
 ]

From b8d211d35917184433fcab4c6ab903392d8ac551 Mon Sep 17 00:00:00 2001
From: Christopher Durham <cad97@cad97.com>
Date: May 24 2020 15:56:32 +0000
Subject: [PATCH 648/2232] Small typo fix


s/when manipulation a/when manipulating a/
---

diff --git a/README.md b/README.md
index 768b394..260c272 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ CXX guarantees an ABI-compatible signature that both sides understand, based on
 builtin bindings for key standard library types to expose an idiomatic API on
 those types to the other language. For example when manipulating a C++ string
 from Rust, its `len()` method becomes a call of the `size()` member function
-defined by C++; when manipulation a Rust string from C++, its `size()` member
+defined by C++; when manipulating a Rust string from C++, its `size()` member
 function calls Rust's `len()`.
 
 <br>

From 63c55b6cc39ba8ae280b390f3a1ba7cff24d297c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: May 24 2020 16:02:14 +0000
Subject: [PATCH 649/2232] Merge pull request #212 from CAD97/patch-1


Small typo fix
---

diff --git a/README.md b/README.md
index 768b394..260c272 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ CXX guarantees an ABI-compatible signature that both sides understand, based on
 builtin bindings for key standard library types to expose an idiomatic API on
 those types to the other language. For example when manipulating a C++ string
 from Rust, its `len()` method becomes a call of the `size()` member function
-defined by C++; when manipulation a Rust string from C++, its `size()` member
+defined by C++; when manipulating a Rust string from C++, its `size()` member
 function calls Rust's `len()`.
 
 <br>

From bbd2620921e921825575810a9fd40712c378d6aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jun 14 2020 02:17:21 +0000
Subject: [PATCH 650/2232] Update ui tests to nightly-2020-06-14


---

diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index a5a0215..9ef72ca 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=std::u8::MAX }` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A { repr: 2u8..=std::u8::MAX }` not covered
+   |           ^ pattern `A { repr: 2u8..=u8::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`

From 0c8c0f26fa0fa5d72ed7d95df976773c4c0a3e41 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 22 2020 00:57:46 +0000
Subject: [PATCH 651/2232] Unbreak ui test on c_take_callback warning


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 51716e0..84a746b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -64,7 +64,10 @@ pub mod ffi {
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
+        /*
+        // https://github.com/dtolnay/cxx/issues/232
         fn c_take_callback(callback: fn(String) -> usize);
+        */
         fn c_take_enum(e: Enum);
 
         fn c_try_return_void() -> Result<()>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 677a55d..d70d5a0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -249,9 +249,12 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
+/*
+// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
+*/
 
 void c_take_enum(Enum e) {
   if (e == Enum::AVal) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index c1a08d2..7121cb2 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -69,7 +69,10 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
+/*
+// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
+*/
 void c_take_enum(Enum e);
 
 void c_try_return_void();
diff --git a/tests/test.rs b/tests/test.rs
index ecfec84..f2f670c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -121,6 +121,8 @@ fn test_c_take() {
     check!(ffi::c_take_enum(ffi::Enum::AVal));
 }
 
+/*
+// https://github.com/dtolnay/cxx/issues/232
 #[test]
 fn test_c_callback() {
     fn callback(s: String) -> usize {
@@ -132,6 +134,7 @@ fn test_c_callback() {
 
     check!(ffi::c_take_callback(callback));
 }
+*/
 
 #[test]
 fn test_c_call_r() {

From b3d5e600a71bce16f981887f20911dced8f3000e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 22 2020 00:58:14 +0000
Subject: [PATCH 652/2232] Update ui tests to nightly-2020-06-27


---

diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 9ef72ca..85cc0c5 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=u8::MAX }` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A { repr: 2u8..=u8::MAX }` not covered
+   |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`

From 006723621740fee74ae1ffae522ff22523afb9b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 22 2020 01:02:36 +0000
Subject: [PATCH 653/2232] Update ui tests to nightly-2020-07-07


---

diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index 5b4f6c6..cb3ae15 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+error[E0271]: type mismatch resolving `<here::StringPiece as cxx::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
    --> $DIR/wrong_type_id.rs:11:9
     |
 11  |         type ByteRange = crate::here::StringPiece;
@@ -7,7 +7,7 @@ error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::E
    ::: $WORKSPACE/src/extern_type.rs:110:41
     |
 110 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
-    |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+    |                                         ------- required by this bound in `cxx::private::verify_extern_type`
     |
     = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
                found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`

From 6911d6d604845be37fbc2f9eb66e14b553845a67 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 22 2020 01:05:48 +0000
Subject: [PATCH 654/2232] Update ui tests to nightly-2020-07-15


---

diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 0baa70a..efd1144 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -5,5 +5,4 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
     |              ^^^^^ doesn't have a size known at compile-time
     |
     = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
-    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
     = note: required because it appears within the type `TypeR`

From 2b87b16679a674a8cb838b72a6ff7dec5eccf717 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 22 2020 01:26:07 +0000
Subject: [PATCH 655/2232] Merge pull request #233 from dtolnay/ui


Unbreak ui tests
---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 51716e0..84a746b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -64,7 +64,10 @@ pub mod ffi {
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
+        /*
+        // https://github.com/dtolnay/cxx/issues/232
         fn c_take_callback(callback: fn(String) -> usize);
+        */
         fn c_take_enum(e: Enum);
 
         fn c_try_return_void() -> Result<()>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 677a55d..d70d5a0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -249,9 +249,12 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
+/*
+// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
+*/
 
 void c_take_enum(Enum e) {
   if (e == Enum::AVal) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index c1a08d2..7121cb2 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -69,7 +69,10 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
+/*
+// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
+*/
 void c_take_enum(Enum e);
 
 void c_try_return_void();
diff --git a/tests/test.rs b/tests/test.rs
index ecfec84..f2f670c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -121,6 +121,8 @@ fn test_c_take() {
     check!(ffi::c_take_enum(ffi::Enum::AVal));
 }
 
+/*
+// https://github.com/dtolnay/cxx/issues/232
 #[test]
 fn test_c_callback() {
     fn callback(s: String) -> usize {
@@ -132,6 +134,7 @@ fn test_c_callback() {
 
     check!(ffi::c_take_callback(callback));
 }
+*/
 
 #[test]
 fn test_c_call_r() {
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 9ef72ca..85cc0c5 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,11 +1,11 @@
-error[E0004]: non-exhaustive patterns: `A { repr: 2u8..=u8::MAX }` not covered
+error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 1  | #[cxx::bridge]
    | -------------- `ffi::A` defined here
 ...
 12 |     match a {
-   |           ^ pattern `A { repr: 2u8..=u8::MAX }` not covered
+   |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `ffi::A`
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 0baa70a..efd1144 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -5,5 +5,4 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
     |              ^^^^^ doesn't have a size known at compile-time
     |
     = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
-    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
     = note: required because it appears within the type `TypeR`
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index 5b4f6c6..cb3ae15 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+error[E0271]: type mismatch resolving `<here::StringPiece as cxx::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
    --> $DIR/wrong_type_id.rs:11:9
     |
 11  |         type ByteRange = crate::here::StringPiece;
@@ -7,7 +7,7 @@ error[E0271]: type mismatch resolving `<here::StringPiece as cxx::extern_type::E
    ::: $WORKSPACE/src/extern_type.rs:110:41
     |
 110 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
-    |                                         ------- required by this bound in `cxx::extern_type::verify_extern_type`
+    |                                         ------- required by this bound in `cxx::private::verify_extern_type`
     |
     = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
                found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`

From 0ecd05a9bf0096d5c05a44e82d4221cc291a9ef5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 29 2020 23:32:03 +0000
Subject: [PATCH 656/2232] Include <new> when placement new is used


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 0ed76ac..4309c9c 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -56,6 +56,7 @@ pub struct Includes {
     pub cstring: bool,
     pub exception: bool,
     pub memory: bool,
+    pub new: bool,
     pub string: bool,
     pub type_traits: bool,
     pub utility: bool,
@@ -106,6 +107,9 @@ impl Display for Includes {
         if self.memory {
             writeln!(f, "#include <memory>")?;
         }
+        if self.new {
+            writeln!(f, "#include <new>")?;
+        }
         if self.string {
             writeln!(f, "#include <string>")?;
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2cf9faf..46b6151 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -149,11 +149,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     for ty in types {
         match ty {
             Type::RustBox(_) => {
+                out.include.new = true;
                 out.include.type_traits = true;
                 needs_rust_box = true;
             }
             Type::RustVec(_) => {
                 out.include.array = true;
+                out.include.new = true;
                 out.include.type_traits = true;
                 needs_rust_vec = true;
             }
@@ -463,6 +465,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "        ");
     }
     if indirect_return {
+        out.include.new = true;
         write!(out, "new (return$) ");
         write_indirect_return_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
@@ -1149,6 +1152,7 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
 fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.new = true;
     out.include.utility = true;
     let inner = to_typename(&out.namespace, ty);
     let instance = to_mangled(&out.namespace, ty);
diff --git a/include/cxx.h b/include/cxx.h
index 9f4fb47..f211b3b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -4,6 +4,7 @@
 #include <cstdint>
 #include <exception>
 #include <iosfwd>
+#include <new>
 #include <string>
 #include <type_traits>
 #include <utility>

From 4caede68764f2ed0a57fba26f10c3728fc1849b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 29 2020 23:37:28 +0000
Subject: [PATCH 657/2232] Merge pull request #239 from dtolnay/new


Include <new> when placement new is used
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 0ed76ac..4309c9c 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -56,6 +56,7 @@ pub struct Includes {
     pub cstring: bool,
     pub exception: bool,
     pub memory: bool,
+    pub new: bool,
     pub string: bool,
     pub type_traits: bool,
     pub utility: bool,
@@ -106,6 +107,9 @@ impl Display for Includes {
         if self.memory {
             writeln!(f, "#include <memory>")?;
         }
+        if self.new {
+            writeln!(f, "#include <new>")?;
+        }
         if self.string {
             writeln!(f, "#include <string>")?;
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2cf9faf..46b6151 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -149,11 +149,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     for ty in types {
         match ty {
             Type::RustBox(_) => {
+                out.include.new = true;
                 out.include.type_traits = true;
                 needs_rust_box = true;
             }
             Type::RustVec(_) => {
                 out.include.array = true;
+                out.include.new = true;
                 out.include.type_traits = true;
                 needs_rust_vec = true;
             }
@@ -463,6 +465,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         write!(out, "        ");
     }
     if indirect_return {
+        out.include.new = true;
         write!(out, "new (return$) ");
         write_indirect_return_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
@@ -1149,6 +1152,7 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
 fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+    out.include.new = true;
     out.include.utility = true;
     let inner = to_typename(&out.namespace, ty);
     let instance = to_mangled(&out.namespace, ty);
diff --git a/include/cxx.h b/include/cxx.h
index 9f4fb47..f211b3b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -4,6 +4,7 @@
 #include <cstdint>
 #include <exception>
 #include <iosfwd>
+#include <new>
 #include <string>
 #include <type_traits>
 #include <utility>

From 21f0ff042445cf6f0574a583231b5c68e50263f5 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Jul 30 2020 00:31:16 +0000
Subject: [PATCH 658/2232] Allow DSO export for C Rust bindings.


This option to the 'cxxbridge' command line tool allows
users to specify (for example)

  __attribute__((visibility("default")))
or
  __declspec(dllexport)

on C functions which may be exported from a shared object
as they may be required by Rust code in different binaries.

---

diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index a20179f..701f77f 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -35,6 +35,15 @@ struct Opt {
     #[structopt(long)]
     header: bool,
 
+    /// Optional annotation for implementations of C++ function
+    /// wrappers that may be exposed to Rust. You may for example
+    /// need to provide __declspec(dllexport) or
+    /// __attribute__((visibility("default"))) if Rust code from
+    /// one shared object or executable depends on these C++ functions
+    /// in another.
+    #[structopt(long)]
+    cxx_impl_annotations: Option<String>,
+
     /// Any additional headers to #include
     #[structopt(short, long)]
     include: Vec<String>,
@@ -49,6 +58,7 @@ fn main() {
 
     let gen = gen::Opt {
         include: opt.include,
+        cxx_impl_annotations: opt.cxx_impl_annotations,
     };
 
     match (opt.input, opt.header) {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index b9d35d7..65d6c67 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -24,6 +24,9 @@ struct Input {
 pub(super) struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,
+    /// Whether to set __attribute__((visibility("default")))
+    /// or similar annotations on function implementations.
+    pub cxx_impl_annotations: Option<String>,
 }
 
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 46b6151..04d8e3e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -86,13 +86,13 @@ pub(super) fn gen(
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
-            let (efn, write): (_, fn(_, _, _)) = match api {
+            let (efn, write): (_, fn(_, _, _, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
                 Api::RustFunction(efn) => (efn, write_rust_function_decl),
                 _ => continue,
             };
             out.next_section();
-            write(out, efn, types);
+            write(out, efn, types, &opt.cxx_impl_annotations);
         }
         out.end_block("extern \"C\"");
     }
@@ -399,7 +399,17 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+fn write_cxx_function_shim(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    types: &Types,
+    impl_annotations: &Option<String>,
+) {
+    if !out.header {
+        if let Some(annotation) = impl_annotations {
+            write!(out, "{} ", annotation);
+        }
+    }
     if efn.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
@@ -560,7 +570,7 @@ fn write_function_pointer_trampoline(
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
     let link_name = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);

From 8205e625c11e432f892439a82dfd80950c8ec798 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@google.com>
Date: Jul 30 2020 00:31:16 +0000
Subject: [PATCH 659/2232] Adding test for new annotations.


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 65d6c67..77a0c65 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -31,34 +31,74 @@ pub(super) struct Opt {
 
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
-    generate(path, opt, header)
+    generate_from_path(path, opt, header)
 }
 
 pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     let header = true;
-    generate(path, opt, header)
+    generate_from_path(path, opt, header)
 }
 
-fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
+fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match (|| -> Result<_> {
-        proc_macro2::fallback::force();
-        let ref mut errors = Errors::new();
-        let syntax = syn::parse_file(&source)?;
-        let bridge = find::find_bridge_mod(syntax)?;
-        let ref namespace = bridge.namespace;
-        let ref apis = syntax::parse_items(errors, bridge.module);
-        let ref types = Types::collect(errors, apis);
-        errors.propagate()?;
-        check::typecheck(errors, namespace, apis, types);
-        errors.propagate()?;
-        let out = write::gen(namespace, apis, types, opt, header);
-        Ok(out)
-    })() {
-        Ok(out) => out.content(),
+    match generate(&source, opt, header) {
+        Ok(out) => out,
         Err(err) => format_err(path, &source, err),
     }
 }
+
+fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+    proc_macro2::fallback::force();
+    let ref mut errors = Errors::new();
+    let syntax = syn::parse_file(&source)?;
+    let bridge = find::find_bridge_mod(syntax)?;
+    let ref namespace = bridge.namespace;
+    let ref apis = syntax::parse_items(errors, bridge.module);
+    let ref types = Types::collect(errors, apis);
+    errors.propagate()?;
+    check::typecheck(errors, namespace, apis, types);
+    errors.propagate()?;
+    let out = write::gen(namespace, apis, types, opt, header);
+    Ok(out.content())
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::gen::{generate, Opt};
+
+    const CPP_EXAMPLE: &'static str = r#"
+        #[cxx::bridge]
+        mod ffi {
+            extern "C" {
+                pub fn do_cpp_thing(foo: &str);
+            }
+        }
+        "#;
+
+    #[test]
+    fn test_cpp() {
+        let opts = Opt {
+            include: Vec::new(),
+            cxx_impl_annotations: None,
+        };
+        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+        let output = std::str::from_utf8(&output).unwrap();
+        // To avoid continual breakage we won't test every byte.
+        // Let's look for the major features.
+        assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    }
+
+    #[test]
+    fn test_annotation() {
+        let opts = Opt {
+            include: Vec::new(),
+            cxx_impl_annotations: Some("ANNOTATION".to_string()),
+        };
+        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+        let output = std::str::from_utf8(&output).unwrap();
+        assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    }
+}

From b1dced5711b32a12c7b78aab31cd95d18e5580d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 30 2020 00:37:56 +0000
Subject: [PATCH 660/2232] Merge pull request #231 from adetaylor/set-visibility


Allow DSO export for C Rust bindings.
---

diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index a20179f..701f77f 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -35,6 +35,15 @@ struct Opt {
     #[structopt(long)]
     header: bool,
 
+    /// Optional annotation for implementations of C++ function
+    /// wrappers that may be exposed to Rust. You may for example
+    /// need to provide __declspec(dllexport) or
+    /// __attribute__((visibility("default"))) if Rust code from
+    /// one shared object or executable depends on these C++ functions
+    /// in another.
+    #[structopt(long)]
+    cxx_impl_annotations: Option<String>,
+
     /// Any additional headers to #include
     #[structopt(short, long)]
     include: Vec<String>,
@@ -49,6 +58,7 @@ fn main() {
 
     let gen = gen::Opt {
         include: opt.include,
+        cxx_impl_annotations: opt.cxx_impl_annotations,
     };
 
     match (opt.input, opt.header) {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index b9d35d7..77a0c65 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -24,38 +24,81 @@ struct Input {
 pub(super) struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,
+    /// Whether to set __attribute__((visibility("default")))
+    /// or similar annotations on function implementations.
+    pub cxx_impl_annotations: Option<String>,
 }
 
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
-    generate(path, opt, header)
+    generate_from_path(path, opt, header)
 }
 
 pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     let header = true;
-    generate(path, opt, header)
+    generate_from_path(path, opt, header)
 }
 
-fn generate(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
+fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match (|| -> Result<_> {
-        proc_macro2::fallback::force();
-        let ref mut errors = Errors::new();
-        let syntax = syn::parse_file(&source)?;
-        let bridge = find::find_bridge_mod(syntax)?;
-        let ref namespace = bridge.namespace;
-        let ref apis = syntax::parse_items(errors, bridge.module);
-        let ref types = Types::collect(errors, apis);
-        errors.propagate()?;
-        check::typecheck(errors, namespace, apis, types);
-        errors.propagate()?;
-        let out = write::gen(namespace, apis, types, opt, header);
-        Ok(out)
-    })() {
-        Ok(out) => out.content(),
+    match generate(&source, opt, header) {
+        Ok(out) => out,
         Err(err) => format_err(path, &source, err),
     }
 }
+
+fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+    proc_macro2::fallback::force();
+    let ref mut errors = Errors::new();
+    let syntax = syn::parse_file(&source)?;
+    let bridge = find::find_bridge_mod(syntax)?;
+    let ref namespace = bridge.namespace;
+    let ref apis = syntax::parse_items(errors, bridge.module);
+    let ref types = Types::collect(errors, apis);
+    errors.propagate()?;
+    check::typecheck(errors, namespace, apis, types);
+    errors.propagate()?;
+    let out = write::gen(namespace, apis, types, opt, header);
+    Ok(out.content())
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::gen::{generate, Opt};
+
+    const CPP_EXAMPLE: &'static str = r#"
+        #[cxx::bridge]
+        mod ffi {
+            extern "C" {
+                pub fn do_cpp_thing(foo: &str);
+            }
+        }
+        "#;
+
+    #[test]
+    fn test_cpp() {
+        let opts = Opt {
+            include: Vec::new(),
+            cxx_impl_annotations: None,
+        };
+        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+        let output = std::str::from_utf8(&output).unwrap();
+        // To avoid continual breakage we won't test every byte.
+        // Let's look for the major features.
+        assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    }
+
+    #[test]
+    fn test_annotation() {
+        let opts = Opt {
+            include: Vec::new(),
+            cxx_impl_annotations: Some("ANNOTATION".to_string()),
+        };
+        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+        let output = std::str::from_utf8(&output).unwrap();
+        assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    }
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 46b6151..04d8e3e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -86,13 +86,13 @@ pub(super) fn gen(
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
-            let (efn, write): (_, fn(_, _, _)) = match api {
+            let (efn, write): (_, fn(_, _, _, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
                 Api::RustFunction(efn) => (efn, write_rust_function_decl),
                 _ => continue,
             };
             out.next_section();
-            write(out, efn, types);
+            write(out, efn, types, &opt.cxx_impl_annotations);
         }
         out.end_block("extern \"C\"");
     }
@@ -399,7 +399,17 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+fn write_cxx_function_shim(
+    out: &mut OutFile,
+    efn: &ExternFn,
+    types: &Types,
+    impl_annotations: &Option<String>,
+) {
+    if !out.header {
+        if let Some(annotation) = impl_annotations {
+            write!(out, "{} ", annotation);
+        }
+    }
     if efn.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
@@ -560,7 +570,7 @@ fn write_function_pointer_trampoline(
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
     let link_name = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);

From c2bbd952d2dee6005562d309e10855b177610463 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 30 2020 01:17:19 +0000
Subject: [PATCH 661/2232] Add rust::String(const char *, size_t) constructor


---

diff --git a/include/cxx.h b/include/cxx.h
index f211b3b..5a33a7a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -29,6 +29,7 @@ public:
 
   String(const std::string &);
   String(const char *);
+  String(const char *, size_t);
 
   String &operator=(const String &) noexcept;
   String &operator=(String &&) noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index eb86d3d..8614d39 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -55,16 +55,11 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge03$string$drop(this); }
 
-String::String(const std::string &s) {
-  auto ptr = s.data();
-  auto len = s.length();
-  if (!cxxbridge03$string$from(this, ptr, len)) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
-}
+String::String(const std::string &s) : String(s.data(), s.length()) {}
+
+String::String(const char *s) : String(s, std::strlen(s)) {}
 
-String::String(const char *s) {
-  auto len = std::strlen(s);
+String::String(const char *s, size_t len) {
   if (!cxxbridge03$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }

From 894c5e45dcaa7b4eac7dce16bfcd86819f185e79 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 30 2020 01:21:50 +0000
Subject: [PATCH 662/2232] Add rust::Str(const char *, size_t) constructor


---

diff --git a/include/cxx.h b/include/cxx.h
index 5a33a7a..c3231fd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -59,6 +59,7 @@ public:
 
   Str(const std::string &);
   Str(const char *);
+  Str(const char *, size_t);
   Str(std::string &&) = delete;
 
   Str &operator=(Str) noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index 8614d39..da05ee2 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -106,13 +106,11 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
-}
+Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
+
+Str::Str(const char *s) : Str(s, std::strlen(s)) {}
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
   if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }

From 28da250d243949be488964ffffeb1c4962285611 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 30 2020 01:41:43 +0000
Subject: [PATCH 663/2232] Merge pull request #242 from dtolnay/str-ptr-len


Add rust::String(const char *, size_t) constructor
---

diff --git a/include/cxx.h b/include/cxx.h
index f211b3b..c3231fd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -29,6 +29,7 @@ public:
 
   String(const std::string &);
   String(const char *);
+  String(const char *, size_t);
 
   String &operator=(const String &) noexcept;
   String &operator=(String &&) noexcept;
@@ -58,6 +59,7 @@ public:
 
   Str(const std::string &);
   Str(const char *);
+  Str(const char *, size_t);
   Str(std::string &&) = delete;
 
   Str &operator=(Str) noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index eb86d3d..da05ee2 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -55,16 +55,11 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge03$string$drop(this); }
 
-String::String(const std::string &s) {
-  auto ptr = s.data();
-  auto len = s.length();
-  if (!cxxbridge03$string$from(this, ptr, len)) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
-}
+String::String(const std::string &s) : String(s.data(), s.length()) {}
 
-String::String(const char *s) {
-  auto len = std::strlen(s);
+String::String(const char *s) : String(s, std::strlen(s)) {}
+
+String::String(const char *s, size_t len) {
   if (!cxxbridge03$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
@@ -111,13 +106,11 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
-}
+Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
+
+Str::Str(const char *s) : Str(s, std::strlen(s)) {}
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
   if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }

From 0d47a535769d3511e6e5ecb978e739abab8b7a77 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 02:39:04 +0000
Subject: [PATCH 664/2232] Move C++ code generator unit tests to module


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 77a0c65..710bca2 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -7,6 +7,9 @@ pub(super) mod include;
 pub(super) mod out;
 mod write;
 
+#[cfg(test)]
+mod tests;
+
 use self::error::{format_err, Error, Result};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
@@ -64,41 +67,3 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     let out = write::gen(namespace, apis, types, opt, header);
     Ok(out.content())
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::gen::{generate, Opt};
-
-    const CPP_EXAMPLE: &'static str = r#"
-        #[cxx::bridge]
-        mod ffi {
-            extern "C" {
-                pub fn do_cpp_thing(foo: &str);
-            }
-        }
-        "#;
-
-    #[test]
-    fn test_cpp() {
-        let opts = Opt {
-            include: Vec::new(),
-            cxx_impl_annotations: None,
-        };
-        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
-        let output = std::str::from_utf8(&output).unwrap();
-        // To avoid continual breakage we won't test every byte.
-        // Let's look for the major features.
-        assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
-    }
-
-    #[test]
-    fn test_annotation() {
-        let opts = Opt {
-            include: Vec::new(),
-            cxx_impl_annotations: Some("ANNOTATION".to_string()),
-        };
-        let output = generate(CPP_EXAMPLE, opts, false).unwrap();
-        let output = std::str::from_utf8(&output).unwrap();
-        assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
-    }
-}
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
new file mode 100644
index 0000000..0e7a910
--- /dev/null
+++ b/gen/src/tests.rs
@@ -0,0 +1,34 @@
+use crate::gen::{generate, Opt};
+
+const CPP_EXAMPLE: &'static str = r#"
+    #[cxx::bridge]
+    mod ffi {
+        extern "C" {
+            pub fn do_cpp_thing(foo: &str);
+        }
+    }
+    "#;
+
+#[test]
+fn test_cpp() {
+    let opts = Opt {
+        include: Vec::new(),
+        cxx_impl_annotations: None,
+    };
+    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = std::str::from_utf8(&output).unwrap();
+    // To avoid continual breakage we won't test every byte.
+    // Let's look for the major features.
+    assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+}
+
+#[test]
+fn test_annotation() {
+    let opts = Opt {
+        include: Vec::new(),
+        cxx_impl_annotations: Some("ANNOTATION".to_string()),
+    };
+    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = std::str::from_utf8(&output).unwrap();
+    assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+}

From 829b0707e6c44d0c9b2286bd2b48787f5d87e16e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:24:22 +0000
Subject: [PATCH 665/2232] Update bazel build to rust 1.44


---

diff --git a/WORKSPACE b/WORKSPACE
index 4269fbc..cafb78c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,13 +24,13 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_43_linux",
+    name = "rust_1_44_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.43.0",
+    version = "1.44.0",
 )
 
 rust_repository_set(
-    name = "rust_1_43_darwin",
+    name = "rust_1_44_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.43.0",
+    version = "1.44.0",
 )

From a96213c6006665ed14adbe9a9b8f69226ae34b5f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:24:22 +0000
Subject: [PATCH 666/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 479fbfc..9890a71 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -2,7 +2,7 @@
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.31/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.32/src/**"]),
     visibility = ["PUBLIC"],
     features = ["std"],
 )
@@ -14,7 +14,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.54/src/**"]),
+    srcs = glob(["vendor/cc-1.0.58/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.4/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
@@ -53,13 +53,13 @@ rust_library(
 
 rust_library(
     name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
     visibility = ["PUBLIC"],
 )
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.2/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -71,7 +71,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.2/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
     proc_macro = True,
     deps = [
         ":proc-macro2",
@@ -83,7 +83,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.17/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -99,7 +99,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.6/src/**"]),
+    srcs = glob(["vendor/quote-1.0.7/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
@@ -107,7 +107,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.14/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":clap",
@@ -118,7 +118,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.7/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
     proc_macro = True,
     deps = [
         ":heck",
@@ -131,7 +131,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.23/src/**"]),
+    srcs = glob(["vendor/syn-1.0.36/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
@@ -177,10 +177,10 @@ rust_library(
 
 rust_library(
     name = "unicode-width",
-    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+    srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
 
 rust_library(
     name = "unicode-xid",
-    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+    srcs = glob(["vendor/unicode-xid-0.2.1/src/**"]),
 )
diff --git a/third-party/BUILD b/third-party/BUILD
index 8734f30..9aaf4f6 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -7,7 +7,7 @@ load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.31/src/**"]),
+    srcs = glob(["vendor/anyhow-1.0.32/src/**"]),
     crate_features = ["std"],
     visibility = ["//visibility:public"],
 )
@@ -19,7 +19,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.54/src/**"]),
+    srcs = glob(["vendor/cc-1.0.58/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -36,7 +36,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.4/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
@@ -58,13 +58,13 @@ rust_library(
 
 rust_library(
     name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.1/src/**"]),
+    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
     visibility = ["//visibility:public"],
 )
 
 rust_library(
     name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.2/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
         ":proc-macro-error-attr",
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.2/src/**"]),
+    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":proc-macro2",
@@ -88,7 +88,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.17/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -104,7 +104,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.6/src/**"]),
+    srcs = glob(["vendor/quote-1.0.7/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
@@ -112,7 +112,7 @@ rust_library(
 
 rust_library(
     name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.14/src/**"]),
+    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
@@ -123,7 +123,7 @@ rust_library(
 
 rust_library(
     name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.7/src/**"]),
+    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
     crate_type = "proc-macro",
     deps = [
         ":heck",
@@ -136,7 +136,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.23/src/**"]),
+    srcs = glob(["vendor/syn-1.0.36/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
@@ -182,10 +182,10 @@ rust_library(
 
 rust_library(
     name = "unicode-width",
-    srcs = glob(["vendor/unicode-width-0.1.7/src/**"]),
+    srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
 
 rust_library(
     name = "unicode-xid",
-    srcs = glob(["vendor/unicode-xid-0.2.0/src/**"]),
+    srcs = glob(["vendor/unicode-xid-0.2.1/src/**"]),
 )
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 0ca0a3c..8f40664 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -11,9 +11,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.31"
+version = "1.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
+checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
 
 [[package]]
 name = "atty"
@@ -34,9 +34,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.54"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
+checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
 
 [[package]]
 name = "clap"
@@ -55,9 +55,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ceface2475f2f57a7ece9ba239b96e06bda8323ee68aa6df539752f13a74f60"
+checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -128,9 +128,9 @@ dependencies = [
 
 [[package]]
 name = "dissimilar"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39de161cd2ebbd6e5783db53a82a47b6a47dcfef754130839603561745528b94"
+checksum = "fc4b29f4b9bb94bf267d57269fd0706d343a160937108e9619fe380645428abb"
 
 [[package]]
 name = "glob"
@@ -149,18 +149,18 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.13"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
+checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "itoa"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
+checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
 
 [[package]]
 name = "lazy_static"
@@ -170,24 +170,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.70"
+version = "0.2.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
+checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
 
 [[package]]
 name = "link-cplusplus"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628cd9d7b5c99cb930617438a3d7896f5eb734647bc2838ded9ca50689507295"
+checksum = "f563b3814ea63e830e3e321206e4e2b5177854586ebe3f595795ed7053b217f5"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "proc-macro-error"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
+checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
 dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
@@ -198,9 +198,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-error-attr"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
+checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -211,27 +211,27 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.17"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101"
+checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
+checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "rustversion"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3bba175698996010c4f6dce5e7f173b6eb781fce25d2cfc45e27091ce0b79f6"
+checksum = "b9bdc5e856e51e685846fb6c13a1f5e5432946c2c90501bdc76a1319f19e29da"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -240,24 +240,24 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1"
+checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
 
 [[package]]
 name = "serde"
-version = "1.0.110"
+version = "1.0.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
+checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.110"
+version = "1.0.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
+checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -266,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.53"
+version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
+checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
 dependencies = [
  "itoa",
  "ryu",
@@ -283,9 +283,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "structopt"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
+checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
 dependencies = [
  "clap",
  "lazy_static",
@@ -294,9 +294,9 @@ dependencies = [
 
 [[package]]
 name = "structopt-derive"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
+checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.23"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269"
+checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -356,9 +356,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.27"
+version = "1.0.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "744665442556a91933cee5e75b0371376eb03498c4d0bfbcebd2a9882b4fb5ef"
+checksum = "7a4d94e6adf00b96b1ab94fcfcd8c3cf916733b39adf90c8f72693629887b9b8"
 dependencies = [
  "dissimilar",
  "glob",
@@ -377,15 +377,15 @@ checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
+checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
 
 [[package]]
 name = "unicode-xid"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
+checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
 
 [[package]]
 name = "vec_map"
@@ -395,15 +395,15 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
 [[package]]
 name = "version_check"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
+checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
 
 [[package]]
 name = "winapi"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
 dependencies = [
  "winapi-i686-pc-windows-gnu",
  "winapi-x86_64-pc-windows-gnu",

From dd24719b97c1d26d1db9add7668e1fec21f9eb5e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:30:02 +0000
Subject: [PATCH 667/2232] Update bazel Rust rules


---

diff --git a/BUILD b/BUILD
index d63fea7..4d2b33a 100644
--- a/BUILD
+++ b/BUILD
@@ -3,10 +3,12 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
+    proc_macro_deps = [
+        ":cxxbridge-macro",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
-        ":cxxbridge-macro",
         "//third-party:link-cplusplus",
     ],
 )
diff --git a/WORKSPACE b/WORKSPACE
index cafb78c..cd2a2e8 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "b83154a58f95618e06845b774b079000e0c39830e185db4c7bf46e79896cb3a1",
-    strip_prefix = "rules_rust-0deef6dd8180cd3bc610878558bb26921b4e8de1",
-    # Master branch as of 2020-03-07
-    url = "https://github.com/bazelbuild/rules_rust/archive/0deef6dd8180cd3bc610878558bb26921b4e8de1.tar.gz",
+    sha256 = "5ed804fcd10a506a5b8e9e59bc6b3b7f43bc30c87ce4670e6f78df43604894fd",
+    strip_prefix = "rules_rust-fdf9655ba95616e0314b4e0ebab40bb0c5fe005c",
+    # Master branch as of 2020-07-30
+    url = "https://github.com/bazelbuild/rules_rust/archive/fdf9655ba95616e0314b4e0ebab40bb0c5fe005c.tar.gz",
 )
 
 http_archive(
diff --git a/third-party/BUILD b/third-party/BUILD
index 9aaf4f6..a01d4b7 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -65,9 +65,11 @@ rust_library(
 rust_library(
     name = "proc-macro-error",
     srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
+    proc_macro_deps = [
+        ":proc-macro-error-attr",
+    ],
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
-        ":proc-macro-error-attr",
         ":proc-macro2",
         ":quote",
         ":syn",
@@ -113,11 +115,13 @@ rust_library(
 rust_library(
     name = "structopt",
     srcs = glob(["vendor/structopt-0.3.15/src/**"]),
+    proc_macro_deps = [
+        ":structopt-derive",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
         ":lazy_static",
-        ":structopt-derive",
     ],
 )
 

From bf0e48bdb0bc10aeb71f005a1239db6ea8dc106d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:41:39 +0000
Subject: [PATCH 668/2232] Merge pull request #244 from dtolnay/bazel


Update bazel Rust rules repo
---

diff --git a/BUILD b/BUILD
index d63fea7..4d2b33a 100644
--- a/BUILD
+++ b/BUILD
@@ -3,10 +3,12 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 rust_library(
     name = "cxx",
     srcs = glob(["src/**/*.rs"]),
+    proc_macro_deps = [
+        ":cxxbridge-macro",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         ":core-lib",
-        ":cxxbridge-macro",
         "//third-party:link-cplusplus",
     ],
 )
diff --git a/WORKSPACE b/WORKSPACE
index cafb78c..cd2a2e8 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,10 +2,10 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 http_archive(
     name = "io_bazel_rules_rust",
-    sha256 = "b83154a58f95618e06845b774b079000e0c39830e185db4c7bf46e79896cb3a1",
-    strip_prefix = "rules_rust-0deef6dd8180cd3bc610878558bb26921b4e8de1",
-    # Master branch as of 2020-03-07
-    url = "https://github.com/bazelbuild/rules_rust/archive/0deef6dd8180cd3bc610878558bb26921b4e8de1.tar.gz",
+    sha256 = "5ed804fcd10a506a5b8e9e59bc6b3b7f43bc30c87ce4670e6f78df43604894fd",
+    strip_prefix = "rules_rust-fdf9655ba95616e0314b4e0ebab40bb0c5fe005c",
+    # Master branch as of 2020-07-30
+    url = "https://github.com/bazelbuild/rules_rust/archive/fdf9655ba95616e0314b4e0ebab40bb0c5fe005c.tar.gz",
 )
 
 http_archive(
diff --git a/third-party/BUILD b/third-party/BUILD
index 9aaf4f6..a01d4b7 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -65,9 +65,11 @@ rust_library(
 rust_library(
     name = "proc-macro-error",
     srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
+    proc_macro_deps = [
+        ":proc-macro-error-attr",
+    ],
     rustc_flags = ["--cfg=use_fallback"],
     deps = [
-        ":proc-macro-error-attr",
         ":proc-macro2",
         ":quote",
         ":syn",
@@ -113,11 +115,13 @@ rust_library(
 rust_library(
     name = "structopt",
     srcs = glob(["vendor/structopt-0.3.15/src/**"]),
+    proc_macro_deps = [
+        ":structopt-derive",
+    ],
     visibility = ["//visibility:public"],
     deps = [
         ":clap",
         ":lazy_static",
-        ":structopt-derive",
     ],
 )
 

From 39fa366897a7d8fe9bfedfff0d7d45aebe1e7f1f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:41:52 +0000
Subject: [PATCH 669/2232] Switch cli arg parsing from structopt to clap


---

diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 7a80a2f..b9d4b78 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -15,10 +15,10 @@ path = "src/main.rs"
 
 [dependencies]
 anyhow = "1.0"
+clap = "2.33"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-structopt = "0.3"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
new file mode 100644
index 0000000..37934e5
--- /dev/null
+++ b/gen/cmd/src/app.rs
@@ -0,0 +1,112 @@
+use super::Opt;
+use clap::AppSettings;
+use std::ffi::{OsStr, OsString};
+use std::path::PathBuf;
+
+type App = clap::App<'static, 'static>;
+type Arg = clap::Arg<'static, 'static>;
+
+const USAGE: &str = "\
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit rust/cxx.h header to stdout\
+";
+
+const TEMPLATE: &str = "\
+{bin} {version}
+David Tolnay <dtolnay@gmail.com>
+https://github.com/dtolnay/cxx
+
+USAGE:
+    {usage}
+
+ARGS:
+{positionals}
+OPTIONS:
+{unified}\
+";
+
+fn app() -> App {
+    let mut app = App::new("cxxbridge")
+        .usage(USAGE)
+        .template(TEMPLATE)
+        .setting(AppSettings::NextLineHelp)
+        .arg(arg_input())
+        .arg(arg_cxx_impl_annotations())
+        .arg(arg_header())
+        .arg(arg_include())
+        .help_message("Print help information.")
+        .version_message("Print version information.");
+    if let Some(version) = option_env!("CARGO_PKG_VERSION") {
+        app = app.version(version);
+    }
+    app
+}
+
+const INPUT: &str = "input";
+const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
+const HEADER: &str = "header";
+const INCLUDE: &str = "include";
+
+pub(super) fn from_args() -> Opt {
+    let matches = app().get_matches();
+    Opt {
+        input: matches.value_of_os(INPUT).map(PathBuf::from),
+        cxx_impl_annotations: matches.value_of(CXX_IMPL_ANNOTATIONS).map(str::to_owned),
+        header: matches.is_present(HEADER),
+        include: matches
+            .values_of(INCLUDE)
+            .map_or_else(Vec::new, |v| v.map(str::to_owned).collect()),
+    }
+}
+
+fn validate_utf8(arg: &OsStr) -> Result<(), OsString> {
+    if arg.to_str().is_some() {
+        Ok(())
+    } else {
+        Err(OsString::from("invalid utf-8 sequence"))
+    }
+}
+
+fn arg_input() -> Arg {
+    Arg::with_name(INPUT)
+        .help("Input Rust source file containing #[cxx::bridge].")
+        .required_unless(HEADER)
+}
+
+fn arg_cxx_impl_annotations() -> Arg {
+    const HELP: &str = "\
+Optional annotation for implementations of C++ function wrappers
+that may be exposed to Rust. You may for example need to provide
+__declspec(dllexport) or __attribute__((visibility(\"default\")))
+if Rust code from one shared object or executable depends on
+these C++ functions in another.
+    ";
+    Arg::with_name(CXX_IMPL_ANNOTATIONS)
+        .long(CXX_IMPL_ANNOTATIONS)
+        .takes_value(true)
+        .value_name("annotation")
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
+
+fn arg_header() -> Arg {
+    Arg::with_name(HEADER)
+        .long(HEADER)
+        .help("Emit header with declarations only.")
+}
+
+fn arg_include() -> Arg {
+    const HELP: &str = "\
+Any additional headers to #include. The cxxbridge tool does not
+parse or even require the given paths to exist; they simply go
+into the generated C++ code as #include lines.
+    ";
+    Arg::with_name(INCLUDE)
+        .long(INCLUDE)
+        .short("i")
+        .takes_value(true)
+        .multiple(true)
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 701f77f..0160913 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -6,46 +6,19 @@
     clippy::toplevel_ref_arg
 )]
 
+mod app;
 mod gen;
 mod syntax;
 
 use gen::include;
 use std::io::{self, Write};
 use std::path::PathBuf;
-use structopt::StructOpt;
 
-#[derive(StructOpt, Debug)]
-#[structopt(
-    name = "cxxbridge",
-    author = "David Tolnay <dtolnay@gmail.com>",
-    about = "https://github.com/dtolnay/cxx",
-    usage = "\
-    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
-    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout",
-    help_message = "Print help information",
-    version_message = "Print version information"
-)]
+#[derive(Debug)]
 struct Opt {
-    /// Input Rust source file containing #[cxx::bridge]
-    #[structopt(parse(from_os_str), required_unless = "header")]
     input: Option<PathBuf>,
-
-    /// Emit header with declarations only
-    #[structopt(long)]
     header: bool,
-
-    /// Optional annotation for implementations of C++ function
-    /// wrappers that may be exposed to Rust. You may for example
-    /// need to provide __declspec(dllexport) or
-    /// __attribute__((visibility("default"))) if Rust code from
-    /// one shared object or executable depends on these C++ functions
-    /// in another.
-    #[structopt(long)]
     cxx_impl_annotations: Option<String>,
-
-    /// Any additional headers to #include
-    #[structopt(short, long)]
     include: Vec<String>,
 }
 
@@ -54,7 +27,7 @@ fn write(content: impl AsRef<[u8]>) {
 }
 
 fn main() {
-    let opt = Opt::from_args();
+    let opt = app::from_args();
 
     let gen = gen::Opt {
         include: opt.include,

From b316d0bb1c34a8421579fc0301fbdc9dfb1b1d33 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 05:42:34 +0000
Subject: [PATCH 670/2232] Remove structopt from third-party


---

diff --git a/BUCK b/BUCK
index 241d7b3..c554e1f 100644
--- a/BUCK
+++ b/BUCK
@@ -17,10 +17,10 @@ rust_binary(
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:anyhow",
+        "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
-        "//third-party:structopt",
         "//third-party:syn",
     ],
 )
diff --git a/BUILD b/BUILD
index 4d2b33a..d5255a8 100644
--- a/BUILD
+++ b/BUILD
@@ -20,10 +20,10 @@ rust_binary(
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
+        "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
-        "//third-party:structopt",
         "//third-party:syn",
     ],
 )
diff --git a/third-party/BUCK b/third-party/BUCK
index 9890a71..78fb2a9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -22,6 +22,7 @@ rust_library(
     name = "clap",
     srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
+    visibility = ["PUBLIC"],
     deps = [
         ":bitflags",
         ":textwrap",
@@ -40,13 +41,6 @@ rust_library(
 )
 
 rust_library(
-    name = "heck",
-    srcs = glob(["vendor/heck-0.3.1/src/**"]),
-    edition = "2015",
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
 )
@@ -58,30 +52,6 @@ rust_library(
 )
 
 rust_library(
-    name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
-    rustc_flags = ["--cfg=use_fallback"],
-    deps = [
-        ":proc-macro-error-attr",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
-    name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
-    proc_macro = True,
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-        ":syn-mid",
-    ],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
@@ -106,30 +76,6 @@ rust_library(
 )
 
 rust_library(
-    name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
-    visibility = ["PUBLIC"],
-    deps = [
-        ":clap",
-        ":lazy_static",
-        ":structopt-derive",
-    ],
-)
-
-rust_library(
-    name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
-    proc_macro = True,
-    deps = [
-        ":heck",
-        ":proc-macro-error",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.36/src/**"]),
     visibility = ["PUBLIC"],
@@ -149,16 +95,6 @@ rust_library(
 )
 
 rust_library(
-    name = "syn-mid",
-    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "termcolor",
     srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
 )
@@ -170,12 +106,6 @@ rust_library(
 )
 
 rust_library(
-    name = "unicode-segmentation",
-    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
-    edition = "2015",
-)
-
-rust_library(
     name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
diff --git a/third-party/BUILD b/third-party/BUILD
index a01d4b7..3e0e30b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -27,6 +27,7 @@ rust_library(
     name = "clap",
     srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
+    visibility = ["//visibility:public"],
     deps = [
         ":bitflags",
         ":textwrap",
@@ -45,13 +46,6 @@ rust_library(
 )
 
 rust_library(
-    name = "heck",
-    srcs = glob(["vendor/heck-0.3.1/src/**"]),
-    edition = "2015",
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
 )
@@ -63,32 +57,6 @@ rust_library(
 )
 
 rust_library(
-    name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
-    proc_macro_deps = [
-        ":proc-macro-error-attr",
-    ],
-    rustc_flags = ["--cfg=use_fallback"],
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
-    name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
-    crate_type = "proc-macro",
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-        ":syn-mid",
-    ],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     crate_features = [
@@ -113,32 +81,6 @@ rust_library(
 )
 
 rust_library(
-    name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
-    proc_macro_deps = [
-        ":structopt-derive",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":clap",
-        ":lazy_static",
-    ],
-)
-
-rust_library(
-    name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
-    crate_type = "proc-macro",
-    deps = [
-        ":heck",
-        ":proc-macro-error",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.36/src/**"]),
     crate_features = [
@@ -158,16 +100,6 @@ rust_library(
 )
 
 rust_library(
-    name = "syn-mid",
-    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "termcolor",
     srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
 )
@@ -179,12 +111,6 @@ rust_library(
 )
 
 rust_library(
-    name = "unicode-segmentation",
-    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
-    edition = "2015",
-)
-
-rust_library(
     name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8f40664..521c030 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -101,10 +101,10 @@ name = "cxxbridge-cmd"
 version = "0.3.4"
 dependencies = [
  "anyhow",
+ "clap",
  "codespan-reporting",
  "proc-macro2",
  "quote",
- "structopt",
  "syn",
 ]
 
@@ -139,15 +139,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "hermit-abi"
 version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -184,32 +175,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "proc-macro-error"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "syn-mid",
- "version_check",
-]
-
-[[package]]
 name = "proc-macro2"
 version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -282,30 +247,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
-name = "structopt"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "syn"
 version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -317,17 +258,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "syn-mid"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "termcolor"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -370,12 +300,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "unicode-segmentation"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
-
-[[package]]
 name = "unicode-width"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -394,12 +318,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
 [[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From f4632ded18bd464bbd23e00206afd1151f5803b8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 17:46:55 +0000
Subject: [PATCH 671/2232] #pragma once needs to be above includes


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 4309c9c..54a359f 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -127,9 +127,6 @@ impl Display for Includes {
             writeln!(f, "#include <BaseTsd.h>")?;
             writeln!(f, "#endif")?;
         }
-        if *self != Self::default() {
-            writeln!(f)?;
-        }
         Ok(())
     }
 }
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 08bf85f..f07a0d3 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -51,16 +51,15 @@ impl OutFile {
         }
     }
 
-    pub fn prepend(&mut self, section: String) {
-        let content = self.content.get_mut();
-        content.bytes.splice(..0, section.into_bytes());
-    }
-
     pub fn write_fmt(&self, args: Arguments) {
         let content = &mut *self.content.borrow_mut();
         Write::write_fmt(content, args).unwrap();
     }
 
+    pub fn extend(&self, other: &Self) {
+        self.content.borrow_mut().write_bytes(&other.content.borrow().bytes);
+    }
+
     pub fn content(&self) -> Vec<u8> {
         self.content.borrow().bytes.clone()
     }
@@ -68,7 +67,14 @@ impl OutFile {
 
 impl Write for Content {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        if !s.is_empty() {
+        self.write_bytes(s.as_bytes());
+        Ok(())
+    }
+}
+
+impl Content {
+    fn write_bytes(&mut self, b: &[u8]) {
+        if !b.is_empty() {
             if !self.blocks_pending.is_empty() {
                 if !self.bytes.is_empty() {
                     self.bytes.push(b'\n');
@@ -84,8 +90,7 @@ impl Write for Content {
                 }
                 self.section_pending = false;
             }
-            self.bytes.extend_from_slice(s.as_bytes());
+            self.bytes.extend_from_slice(b);
         }
-        Ok(())
     }
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 04d8e3e..88a0734 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -17,10 +17,6 @@ pub(super) fn gen(
     let mut out_file = OutFile::new(namespace.clone(), header);
     let out = &mut out_file;
 
-    if header {
-        writeln!(out, "#pragma once");
-    }
-
     out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
@@ -114,9 +110,17 @@ pub(super) fn gen(
         write_generic_instantiations(out, types);
     }
 
-    out.prepend(out.include.to_string());
-
-    out_file
+    // We collected necessary includes lazily while generating the above. Now
+    // put it all together.
+    let mut full_file = OutFile::new(namespace.clone(), header);
+    let full = &mut full_file;
+    if header {
+        writeln!(full, "#pragma once");
+    }
+    write!(full, "{}", out.include);
+    full.next_section();
+    full.extend(out);
+    full_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {

From a05bb4ecd48660df9f22f3b879da2b63a93cabfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 18:16:02 +0000
Subject: [PATCH 672/2232] Merge pull request #246 from dtolnay/pragma


#pragma once needs to be above includes
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 4309c9c..54a359f 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -127,9 +127,6 @@ impl Display for Includes {
             writeln!(f, "#include <BaseTsd.h>")?;
             writeln!(f, "#endif")?;
         }
-        if *self != Self::default() {
-            writeln!(f)?;
-        }
         Ok(())
     }
 }
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 08bf85f..f07a0d3 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -51,16 +51,15 @@ impl OutFile {
         }
     }
 
-    pub fn prepend(&mut self, section: String) {
-        let content = self.content.get_mut();
-        content.bytes.splice(..0, section.into_bytes());
-    }
-
     pub fn write_fmt(&self, args: Arguments) {
         let content = &mut *self.content.borrow_mut();
         Write::write_fmt(content, args).unwrap();
     }
 
+    pub fn extend(&self, other: &Self) {
+        self.content.borrow_mut().write_bytes(&other.content.borrow().bytes);
+    }
+
     pub fn content(&self) -> Vec<u8> {
         self.content.borrow().bytes.clone()
     }
@@ -68,7 +67,14 @@ impl OutFile {
 
 impl Write for Content {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        if !s.is_empty() {
+        self.write_bytes(s.as_bytes());
+        Ok(())
+    }
+}
+
+impl Content {
+    fn write_bytes(&mut self, b: &[u8]) {
+        if !b.is_empty() {
             if !self.blocks_pending.is_empty() {
                 if !self.bytes.is_empty() {
                     self.bytes.push(b'\n');
@@ -84,8 +90,7 @@ impl Write for Content {
                 }
                 self.section_pending = false;
             }
-            self.bytes.extend_from_slice(s.as_bytes());
+            self.bytes.extend_from_slice(b);
         }
-        Ok(())
     }
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 04d8e3e..88a0734 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -17,10 +17,6 @@ pub(super) fn gen(
     let mut out_file = OutFile::new(namespace.clone(), header);
     let out = &mut out_file;
 
-    if header {
-        writeln!(out, "#pragma once");
-    }
-
     out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
@@ -114,9 +110,17 @@ pub(super) fn gen(
         write_generic_instantiations(out, types);
     }
 
-    out.prepend(out.include.to_string());
-
-    out_file
+    // We collected necessary includes lazily while generating the above. Now
+    // put it all together.
+    let mut full_file = OutFile::new(namespace.clone(), header);
+    let full = &mut full_file;
+    if header {
+        writeln!(full, "#pragma once");
+    }
+    write!(full, "{}", out.include);
+    full.next_section();
+    full.extend(out);
+    full_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {

From 54702b9839f4ebb8f0808435980afb6ae372dd42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jul 31 2020 18:50:09 +0000
Subject: [PATCH 673/2232] Use 'write!(out.front, ...)' to write to the front matter


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index f07a0d3..c21ad78 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -7,10 +7,11 @@ pub(crate) struct OutFile {
     pub namespace: Namespace,
     pub header: bool,
     pub include: Includes,
+    pub front: Content,
     content: RefCell<Content>,
 }
 
-struct Content {
+pub struct Content {
     bytes: Vec<u8>,
     section_pending: bool,
     blocks_pending: Vec<&'static str>,
@@ -22,11 +23,8 @@ impl OutFile {
             namespace,
             header,
             include: Includes::new(),
-            content: RefCell::new(Content {
-                bytes: Vec::new(),
-                section_pending: false,
-                blocks_pending: Vec::new(),
-            }),
+            front: Content::new(),
+            content: RefCell::new(Content::new()),
         }
     }
 
@@ -56,12 +54,17 @@ impl OutFile {
         Write::write_fmt(content, args).unwrap();
     }
 
-    pub fn extend(&self, other: &Self) {
-        self.content.borrow_mut().write_bytes(&other.content.borrow().bytes);
-    }
-
     pub fn content(&self) -> Vec<u8> {
-        self.content.borrow().bytes.clone()
+        let front = &self.front.bytes;
+        let content = &self.content.borrow().bytes;
+        let len = front.len() + !front.is_empty() as usize + content.len();
+        let mut out = Vec::with_capacity(len);
+        out.extend_from_slice(front);
+        if !front.is_empty() {
+            out.push(b'\n');
+        }
+        out.extend_from_slice(content);
+        out
     }
 }
 
@@ -73,6 +76,18 @@ impl Write for Content {
 }
 
 impl Content {
+    pub fn write_fmt(&mut self, args: Arguments) {
+        Write::write_fmt(self, args).unwrap();
+    }
+
+    fn new() -> Self {
+        Content {
+            bytes: Vec::new(),
+            section_pending: false,
+            blocks_pending: Vec::new(),
+        }
+    }
+
     fn write_bytes(&mut self, b: &[u8]) {
         if !b.is_empty() {
             if !self.blocks_pending.is_empty() {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 88a0734..ae90047 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -17,6 +17,10 @@ pub(super) fn gen(
     let mut out_file = OutFile::new(namespace.clone(), header);
     let out = &mut out_file;
 
+    if header {
+        writeln!(out.front, "#pragma once");
+    }
+
     out.include.extend(opt.include);
     for api in apis {
         if let Api::Include(include) = api {
@@ -110,17 +114,9 @@ pub(super) fn gen(
         write_generic_instantiations(out, types);
     }
 
-    // We collected necessary includes lazily while generating the above. Now
-    // put it all together.
-    let mut full_file = OutFile::new(namespace.clone(), header);
-    let full = &mut full_file;
-    if header {
-        writeln!(full, "#pragma once");
-    }
-    write!(full, "{}", out.include);
-    full.next_section();
-    full.extend(out);
-    full_file
+    write!(out.front, "{}", out.include);
+
+    out_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {

From a1f890b46877ce06259a44eb7b10faaa7678bd5b Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Jul 31 2020 22:35:34 +0000
Subject: [PATCH 674/2232] Writing include guards around each type.


This avoids problems with duplicate definitions when the
generated .cc ends up including the generated .h via intermediate
includes.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 88a0734..098137e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -58,20 +58,20 @@ pub(super) fn gen(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                write_struct(out, strct);
+                write_struct(out, strct, namespace);
             }
             Api::Enum(enm) => {
                 out.next_section();
                 if types.cxx.contains(&enm.ident) {
                     check_enum(out, enm);
                 } else {
-                    write_enum(out, enm);
+                    write_enum(out, enm, namespace);
                 }
             }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
                     out.next_section();
-                    write_struct_with_methods(out, ety, methods);
+                    write_struct_with_methods(out, ety, methods, namespace);
                 }
             }
             _ => {}
@@ -317,7 +317,8 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct) {
+fn write_struct(out: &mut OutFile, strct: &Struct, namespace: &Namespace) {
+    write_include_guard_start(out, namespace, &strct.ident);
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -328,6 +329,7 @@ fn write_struct(out: &mut OutFile, strct: &Struct) {
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, namespace, &strct.ident);
 }
 
 fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
@@ -338,7 +340,36 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+const INCLUDE_GUARD_PREFIX: &'static str = "CXXBRIDGE03_TYPE_";
+
+fn write_include_guard_start(out: &mut OutFile, namespace: &Namespace, ident: &Ident) {
+    writeln!(
+        out,
+        "#ifndef {}{}{}",
+        INCLUDE_GUARD_PREFIX, namespace, ident
+    );
+    writeln!(
+        out,
+        "#define {}{}{}",
+        INCLUDE_GUARD_PREFIX, namespace, ident
+    );
+}
+
+fn write_include_guard_end(out: &mut OutFile, namespace: &Namespace, ident: &Ident) {
+    writeln!(
+        out,
+        "#endif // {}{}{}",
+        INCLUDE_GUARD_PREFIX, namespace, ident
+    );
+}
+
+fn write_struct_with_methods(
+    out: &mut OutFile,
+    ety: &ExternType,
+    methods: &[&ExternFn],
+    namespace: &Namespace,
+) {
+    write_include_guard_start(out, namespace, &ety.ident);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -353,9 +384,11 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
         writeln!(out, ";");
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, namespace, &ety.ident);
 }
 
-fn write_enum(out: &mut OutFile, enm: &Enum) {
+fn write_enum(out: &mut OutFile, enm: &Enum, namespace: &Namespace) {
+    write_include_guard_start(out, namespace, &enm.ident);
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -366,6 +399,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, namespace, &enm.ident);
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {

From 3be1a7fc534ce26bb123306162653eeee957c47b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 01 2020 01:29:15 +0000
Subject: [PATCH 675/2232] Merge pull request #245 from dtolnay/clap


Switch cli arg parsing from structopt to clap
---

diff --git a/BUCK b/BUCK
index 241d7b3..c554e1f 100644
--- a/BUCK
+++ b/BUCK
@@ -17,10 +17,10 @@ rust_binary(
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:anyhow",
+        "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
-        "//third-party:structopt",
         "//third-party:syn",
     ],
 )
diff --git a/BUILD b/BUILD
index 4d2b33a..d5255a8 100644
--- a/BUILD
+++ b/BUILD
@@ -20,10 +20,10 @@ rust_binary(
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",
+        "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
         "//third-party:quote",
-        "//third-party:structopt",
         "//third-party:syn",
     ],
 )
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 7a80a2f..b9d4b78 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -15,10 +15,10 @@ path = "src/main.rs"
 
 [dependencies]
 anyhow = "1.0"
+clap = "2.33"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-structopt = "0.3"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
new file mode 100644
index 0000000..37934e5
--- /dev/null
+++ b/gen/cmd/src/app.rs
@@ -0,0 +1,112 @@
+use super::Opt;
+use clap::AppSettings;
+use std::ffi::{OsStr, OsString};
+use std::path::PathBuf;
+
+type App = clap::App<'static, 'static>;
+type Arg = clap::Arg<'static, 'static>;
+
+const USAGE: &str = "\
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit rust/cxx.h header to stdout\
+";
+
+const TEMPLATE: &str = "\
+{bin} {version}
+David Tolnay <dtolnay@gmail.com>
+https://github.com/dtolnay/cxx
+
+USAGE:
+    {usage}
+
+ARGS:
+{positionals}
+OPTIONS:
+{unified}\
+";
+
+fn app() -> App {
+    let mut app = App::new("cxxbridge")
+        .usage(USAGE)
+        .template(TEMPLATE)
+        .setting(AppSettings::NextLineHelp)
+        .arg(arg_input())
+        .arg(arg_cxx_impl_annotations())
+        .arg(arg_header())
+        .arg(arg_include())
+        .help_message("Print help information.")
+        .version_message("Print version information.");
+    if let Some(version) = option_env!("CARGO_PKG_VERSION") {
+        app = app.version(version);
+    }
+    app
+}
+
+const INPUT: &str = "input";
+const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
+const HEADER: &str = "header";
+const INCLUDE: &str = "include";
+
+pub(super) fn from_args() -> Opt {
+    let matches = app().get_matches();
+    Opt {
+        input: matches.value_of_os(INPUT).map(PathBuf::from),
+        cxx_impl_annotations: matches.value_of(CXX_IMPL_ANNOTATIONS).map(str::to_owned),
+        header: matches.is_present(HEADER),
+        include: matches
+            .values_of(INCLUDE)
+            .map_or_else(Vec::new, |v| v.map(str::to_owned).collect()),
+    }
+}
+
+fn validate_utf8(arg: &OsStr) -> Result<(), OsString> {
+    if arg.to_str().is_some() {
+        Ok(())
+    } else {
+        Err(OsString::from("invalid utf-8 sequence"))
+    }
+}
+
+fn arg_input() -> Arg {
+    Arg::with_name(INPUT)
+        .help("Input Rust source file containing #[cxx::bridge].")
+        .required_unless(HEADER)
+}
+
+fn arg_cxx_impl_annotations() -> Arg {
+    const HELP: &str = "\
+Optional annotation for implementations of C++ function wrappers
+that may be exposed to Rust. You may for example need to provide
+__declspec(dllexport) or __attribute__((visibility(\"default\")))
+if Rust code from one shared object or executable depends on
+these C++ functions in another.
+    ";
+    Arg::with_name(CXX_IMPL_ANNOTATIONS)
+        .long(CXX_IMPL_ANNOTATIONS)
+        .takes_value(true)
+        .value_name("annotation")
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
+
+fn arg_header() -> Arg {
+    Arg::with_name(HEADER)
+        .long(HEADER)
+        .help("Emit header with declarations only.")
+}
+
+fn arg_include() -> Arg {
+    const HELP: &str = "\
+Any additional headers to #include. The cxxbridge tool does not
+parse or even require the given paths to exist; they simply go
+into the generated C++ code as #include lines.
+    ";
+    Arg::with_name(INCLUDE)
+        .long(INCLUDE)
+        .short("i")
+        .takes_value(true)
+        .multiple(true)
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 701f77f..0160913 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -6,46 +6,19 @@
     clippy::toplevel_ref_arg
 )]
 
+mod app;
 mod gen;
 mod syntax;
 
 use gen::include;
 use std::io::{self, Write};
 use std::path::PathBuf;
-use structopt::StructOpt;
 
-#[derive(StructOpt, Debug)]
-#[structopt(
-    name = "cxxbridge",
-    author = "David Tolnay <dtolnay@gmail.com>",
-    about = "https://github.com/dtolnay/cxx",
-    usage = "\
-    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
-    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout",
-    help_message = "Print help information",
-    version_message = "Print version information"
-)]
+#[derive(Debug)]
 struct Opt {
-    /// Input Rust source file containing #[cxx::bridge]
-    #[structopt(parse(from_os_str), required_unless = "header")]
     input: Option<PathBuf>,
-
-    /// Emit header with declarations only
-    #[structopt(long)]
     header: bool,
-
-    /// Optional annotation for implementations of C++ function
-    /// wrappers that may be exposed to Rust. You may for example
-    /// need to provide __declspec(dllexport) or
-    /// __attribute__((visibility("default"))) if Rust code from
-    /// one shared object or executable depends on these C++ functions
-    /// in another.
-    #[structopt(long)]
     cxx_impl_annotations: Option<String>,
-
-    /// Any additional headers to #include
-    #[structopt(short, long)]
     include: Vec<String>,
 }
 
@@ -54,7 +27,7 @@ fn write(content: impl AsRef<[u8]>) {
 }
 
 fn main() {
-    let opt = Opt::from_args();
+    let opt = app::from_args();
 
     let gen = gen::Opt {
         include: opt.include,
diff --git a/third-party/BUCK b/third-party/BUCK
index 9890a71..78fb2a9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -22,6 +22,7 @@ rust_library(
     name = "clap",
     srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
+    visibility = ["PUBLIC"],
     deps = [
         ":bitflags",
         ":textwrap",
@@ -40,13 +41,6 @@ rust_library(
 )
 
 rust_library(
-    name = "heck",
-    srcs = glob(["vendor/heck-0.3.1/src/**"]),
-    edition = "2015",
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
 )
@@ -58,30 +52,6 @@ rust_library(
 )
 
 rust_library(
-    name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
-    rustc_flags = ["--cfg=use_fallback"],
-    deps = [
-        ":proc-macro-error-attr",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
-    name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
-    proc_macro = True,
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-        ":syn-mid",
-    ],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
@@ -106,30 +76,6 @@ rust_library(
 )
 
 rust_library(
-    name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
-    visibility = ["PUBLIC"],
-    deps = [
-        ":clap",
-        ":lazy_static",
-        ":structopt-derive",
-    ],
-)
-
-rust_library(
-    name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
-    proc_macro = True,
-    deps = [
-        ":heck",
-        ":proc-macro-error",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.36/src/**"]),
     visibility = ["PUBLIC"],
@@ -149,16 +95,6 @@ rust_library(
 )
 
 rust_library(
-    name = "syn-mid",
-    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "termcolor",
     srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
 )
@@ -170,12 +106,6 @@ rust_library(
 )
 
 rust_library(
-    name = "unicode-segmentation",
-    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
-    edition = "2015",
-)
-
-rust_library(
     name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
diff --git a/third-party/BUILD b/third-party/BUILD
index a01d4b7..3e0e30b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -27,6 +27,7 @@ rust_library(
     name = "clap",
     srcs = glob(["vendor/clap-2.33.1/src/**"]),
     edition = "2015",
+    visibility = ["//visibility:public"],
     deps = [
         ":bitflags",
         ":textwrap",
@@ -45,13 +46,6 @@ rust_library(
 )
 
 rust_library(
-    name = "heck",
-    srcs = glob(["vendor/heck-0.3.1/src/**"]),
-    edition = "2015",
-    deps = [":unicode-segmentation"],
-)
-
-rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
 )
@@ -63,32 +57,6 @@ rust_library(
 )
 
 rust_library(
-    name = "proc-macro-error",
-    srcs = glob(["vendor/proc-macro-error-1.0.3/src/**"]),
-    proc_macro_deps = [
-        ":proc-macro-error-attr",
-    ],
-    rustc_flags = ["--cfg=use_fallback"],
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
-    name = "proc-macro-error-attr",
-    srcs = glob(["vendor/proc-macro-error-attr-1.0.3/src/**"]),
-    crate_type = "proc-macro",
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-        ":syn-mid",
-    ],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     crate_features = [
@@ -113,32 +81,6 @@ rust_library(
 )
 
 rust_library(
-    name = "structopt",
-    srcs = glob(["vendor/structopt-0.3.15/src/**"]),
-    proc_macro_deps = [
-        ":structopt-derive",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":clap",
-        ":lazy_static",
-    ],
-)
-
-rust_library(
-    name = "structopt-derive",
-    srcs = glob(["vendor/structopt-derive-0.4.8/src/**"]),
-    crate_type = "proc-macro",
-    deps = [
-        ":heck",
-        ":proc-macro-error",
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.36/src/**"]),
     crate_features = [
@@ -158,16 +100,6 @@ rust_library(
 )
 
 rust_library(
-    name = "syn-mid",
-    srcs = glob(["vendor/syn-mid-0.5.0/src/**"]),
-    deps = [
-        ":proc-macro2",
-        ":quote",
-        ":syn",
-    ],
-)
-
-rust_library(
     name = "termcolor",
     srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
 )
@@ -179,12 +111,6 @@ rust_library(
 )
 
 rust_library(
-    name = "unicode-segmentation",
-    srcs = glob(["vendor/unicode-segmentation-1.6.0/src/**"]),
-    edition = "2015",
-)
-
-rust_library(
     name = "unicode-width",
     srcs = glob(["vendor/unicode-width-0.1.8/src/**"]),
 )
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8f40664..521c030 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -101,10 +101,10 @@ name = "cxxbridge-cmd"
 version = "0.3.4"
 dependencies = [
  "anyhow",
+ "clap",
  "codespan-reporting",
  "proc-macro2",
  "quote",
- "structopt",
  "syn",
 ]
 
@@ -139,15 +139,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
 name = "hermit-abi"
 version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -184,32 +175,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "proc-macro-error"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2",
- "quote",
- "syn",
- "version_check",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "syn-mid",
- "version_check",
-]
-
-[[package]]
 name = "proc-macro2"
 version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -282,30 +247,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
-name = "structopt"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
-dependencies = [
- "heck",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "syn"
 version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -317,17 +258,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "syn-mid"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "termcolor"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -370,12 +300,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "unicode-segmentation"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
-
-[[package]]
 name = "unicode-width"
 version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -394,12 +318,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
 [[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From df4ca02003c07ed6e008ef5ceb2c824e1da18076 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 01 2020 01:33:44 +0000
Subject: [PATCH 676/2232] Access namespace via OutFile


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 098137e..e088e2c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -58,20 +58,20 @@ pub(super) fn gen(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                write_struct(out, strct, namespace);
+                write_struct(out, strct);
             }
             Api::Enum(enm) => {
                 out.next_section();
                 if types.cxx.contains(&enm.ident) {
                     check_enum(out, enm);
                 } else {
-                    write_enum(out, enm, namespace);
+                    write_enum(out, enm);
                 }
             }
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident) {
                     out.next_section();
-                    write_struct_with_methods(out, ety, methods, namespace);
+                    write_struct_with_methods(out, ety, methods);
                 }
             }
             _ => {}
@@ -317,8 +317,8 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct, namespace: &Namespace) {
-    write_include_guard_start(out, namespace, &strct.ident);
+fn write_struct(out: &mut OutFile, strct: &Struct) {
+    write_include_guard_start(out, &strct.ident);
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -329,7 +329,7 @@ fn write_struct(out: &mut OutFile, strct: &Struct, namespace: &Namespace) {
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, namespace, &strct.ident);
+    write_include_guard_end(out, &strct.ident);
 }
 
 fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
@@ -342,34 +342,29 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
 
 const INCLUDE_GUARD_PREFIX: &'static str = "CXXBRIDGE03_TYPE_";
 
-fn write_include_guard_start(out: &mut OutFile, namespace: &Namespace, ident: &Ident) {
+fn write_include_guard_start(out: &mut OutFile, ident: &Ident) {
     writeln!(
         out,
         "#ifndef {}{}{}",
-        INCLUDE_GUARD_PREFIX, namespace, ident
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
     );
     writeln!(
         out,
         "#define {}{}{}",
-        INCLUDE_GUARD_PREFIX, namespace, ident
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
     );
 }
 
-fn write_include_guard_end(out: &mut OutFile, namespace: &Namespace, ident: &Ident) {
+fn write_include_guard_end(out: &mut OutFile, ident: &Ident) {
     writeln!(
         out,
         "#endif // {}{}{}",
-        INCLUDE_GUARD_PREFIX, namespace, ident
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
     );
 }
 
-fn write_struct_with_methods(
-    out: &mut OutFile,
-    ety: &ExternType,
-    methods: &[&ExternFn],
-    namespace: &Namespace,
-) {
-    write_include_guard_start(out, namespace, &ety.ident);
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+    write_include_guard_start(out, &ety.ident);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -384,11 +379,11 @@ fn write_struct_with_methods(
         writeln!(out, ";");
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, namespace, &ety.ident);
+    write_include_guard_end(out, &ety.ident);
 }
 
-fn write_enum(out: &mut OutFile, enm: &Enum, namespace: &Namespace) {
-    write_include_guard_start(out, namespace, &enm.ident);
+fn write_enum(out: &mut OutFile, enm: &Enum) {
+    write_include_guard_start(out, &enm.ident);
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -399,7 +394,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum, namespace: &Namespace) {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, namespace, &enm.ident);
+    write_include_guard_end(out, &enm.ident);
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {

From 8cfdd7ddd69c7dc326c9014cd585a9df1de01a7c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 01 2020 02:05:48 +0000
Subject: [PATCH 677/2232] Merge pull request #247 from adetaylor/include-guards


Writing include guards around each type.
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ae90047..51c4b02 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -314,6 +314,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
+    write_include_guard_start(out, &strct.ident);
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -324,6 +325,7 @@ fn write_struct(out: &mut OutFile, strct: &Struct) {
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, &strct.ident);
 }
 
 fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
@@ -334,7 +336,31 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
+const INCLUDE_GUARD_PREFIX: &'static str = "CXXBRIDGE03_TYPE_";
+
+fn write_include_guard_start(out: &mut OutFile, ident: &Ident) {
+    writeln!(
+        out,
+        "#ifndef {}{}{}",
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
+    );
+    writeln!(
+        out,
+        "#define {}{}{}",
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
+    );
+}
+
+fn write_include_guard_end(out: &mut OutFile, ident: &Ident) {
+    writeln!(
+        out,
+        "#endif // {}{}{}",
+        INCLUDE_GUARD_PREFIX, out.namespace, ident
+    );
+}
+
 fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+    write_include_guard_start(out, &ety.ident);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -349,9 +375,11 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
         writeln!(out, ";");
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, &ety.ident);
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
+    write_include_guard_start(out, &enm.ident);
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -362,6 +390,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
+    write_include_guard_end(out, &enm.ident);
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {

From 291a8b87a16e0c738b8caaeae1d28670416dda9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 09 2020 23:46:45 +0000
Subject: [PATCH 678/2232] Update to trybuild 1.0.32


---

diff --git a/Cargo.toml b/Cargo.toml
index 6a8c1a4..1e0ad0f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,7 +29,7 @@ cc = "1.0.49"
 cxx-build = { version = "=0.3.4", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = { version = "1.0.27", features = ["diff"] }
+trybuild = { version = "1.0.32", features = ["diff"] }
 
 [workspace]
 members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index cb3ae15..e448a22 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -4,9 +4,9 @@ error[E0271]: type mismatch resolving `<here::StringPiece as cxx::ExternType>::I
 11  |         type ByteRange = crate::here::StringPiece;
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements
     |
-   ::: $WORKSPACE/src/extern_type.rs:110:41
+   ::: $WORKSPACE/src/extern_type.rs
     |
-110 | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+    | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
     |                                         ------- required by this bound in `cxx::private::verify_extern_type`
     |
     = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 521c030..763a429 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -286,9 +286,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.31"
+version = "1.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a4d94e6adf00b96b1ab94fcfcd8c3cf916733b39adf90c8f72693629887b9b8"
+checksum = "d3fe571fc1c805a7dc57340d2be54d72a96010a46a05c57018863f3b1cb93d28"
 dependencies = [
  "dissimilar",
  "glob",

From 9e48d5b5c6f88477106cd34b990c3ea5eda2cc09 Mon Sep 17 00:00:00 2001
From: Stephen Crane <sjc@immunant.com>
Date: Aug 21 2020 19:17:02 +0000
Subject: [PATCH 679/2232] Add rust::Vec accessors


Adds operator[], at(), front(), and back() to rust::Vec.

---

diff --git a/include/cxx.h b/include/cxx.h
index c3231fd..786dbb3 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -5,6 +5,7 @@
 #include <exception>
 #include <iosfwd>
 #include <new>
+#include <stdexcept>
 #include <string>
 #include <type_traits>
 #include <utility>
@@ -13,6 +14,26 @@
 #include <BaseTsd.h>
 #endif
 
+#ifndef __has_feature
+#define __has_feature(__x) 0
+#endif
+
+#if !__has_feature(cxx_exceptions)
+#  define _CXXBRIDGE03_NO_EXCEPTIONS
+#endif
+#if !__EXCEPTIONS
+#  define _CXXBRIDGE03_NO_EXCEPTIONS
+#endif
+
+[[noreturn]] inline static void throw_out_of_range(const char *msg) {
+#ifndef _CXXBRIDGE03_NO_EXCEPTIONS
+  throw std::out_of_range(msg);
+#else
+  ((void)msg);
+  std::abort();
+#endif
+}
+
 namespace rust {
 inline namespace cxxbridge03 {
 
@@ -175,6 +196,12 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
 
+  const T &operator[](size_t n) const noexcept;
+  const T &at(size_t n) const;
+
+  const T &front() const;
+  const T &back() const;
+
   class const_iterator {
   public:
     using difference_type = ptrdiff_t;
@@ -464,6 +491,29 @@ bool Vec<T>::empty() const noexcept {
 }
 
 template <typename T>
+const T &Vec<T>::operator[](size_t n) const noexcept {
+  auto data = reinterpret_cast<const char *>(this->data());
+  return *reinterpret_cast<const T *>(data + n * this->stride());
+}
+
+template <typename T>
+const T &Vec<T>::at(size_t n) const {
+  if (n >= this->size())
+    throw_out_of_range("Vec");
+  return (*this)[n];
+}
+
+template <typename T>
+const T &Vec<T>::front() const {
+  return (*this)[0];
+}
+
+template <typename T>
+const T &Vec<T>::back() const {
+  return (*this)[this->size()-1];
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 84a746b..e491343 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -11,6 +11,7 @@ use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
+    #[derive(Clone)]
     struct Shared {
         z: usize,
     }
@@ -61,8 +62,11 @@ pub mod ffi {
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
         fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_rust_vec_index(v: Vec<u8>);
+        fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
+        fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         /*
         // https://github.com/dtolnay/cxx/issues/232
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d70d5a0..76fe8b7 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -208,6 +208,8 @@ void c_take_ref_vector(const std::vector<uint8_t> &v) {
 
 void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
 
+void c_take_rust_vec_index(rust::Vec<uint8_t> v) { c_take_ref_rust_vec_index(v); }
+
 void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   uint32_t sum = 0;
   for (auto i : v) {
@@ -230,6 +232,17 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
+  if (v[0].z == 1010 &&
+      v.at(0).z == 1010 &&
+      v.front().z == 1010 &&
+      v[1].z == 1011 &&
+      v.at(1).z == 1011 &&
+      v.back().z == 1011) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
@@ -237,6 +250,19 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   }
 }
 
+void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
+  if (v[0] == 86 &&
+      v.at(0) == 86 &&
+      v.front() == 86 &&
+      v[1] == 75 &&
+      v.at(1) == 75 &&
+      v[3] == 9 &&
+      v.at(3) == 9 &&
+      v.back() == 9) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
   // requirements for std::iterator_traits.
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7121cb2..7b7d273 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -65,9 +65,12 @@ void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
+void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 /*
 // https://github.com/dtolnay/cxx/issues/232
diff --git a/tests/test.rs b/tests/test.rs
index f2f670c..55c28d2 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -108,15 +108,16 @@ fn test_c_take() {
     check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
     let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
     check!(ffi::c_take_rust_vec(test_vec.clone()));
-    check!(ffi::c_take_rust_vec_shared(vec![
+    check!(ffi::c_take_rust_vec_index(test_vec.clone()));
+    let shared_test_vec = vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
-    ]));
-    check!(ffi::c_take_rust_vec_shared_forward_iterator(vec![
-        ffi::Shared { z: 1010 },
-        ffi::Shared { z: 1011 }
-    ]));
+    ];
+    check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_forward_iterator(shared_test_vec));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
+    check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
     check!(ffi::c_take_enum(ffi::Enum::AVal));
 }

From 9fc0846261d66412f95ab6d9dc5b319491641926 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Aug 22 2020 06:27:29 +0000
Subject: [PATCH 680/2232] Adding library for high-level code generators.


The intention here is to provide a way for high level code generators
to convert a Rust TokenStream into C++ bindings code without the need
to write files to disk or invoke an external command.

---

diff --git a/Cargo.toml b/Cargo.toml
index 1e0ad0f..23d7cf7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,7 +32,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.32", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
+members = ["demo-rs", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/README.md b/gen/README.md
index 9786911..fc8d10f 100644
--- a/gen/README.md
+++ b/gen/README.md
@@ -1,4 +1,5 @@
-This directory contains CXX's C++ code generator. This code generator has two
+This directory contains CXX's C++ code generator. This code generator has three
 public frontends, one a command-line application (binary) in the *cmd* directory
-and the other a library intended to be used from a build.rs in the *build*
-directory.
+a library intended to be used from a build.rs in the *build* directory, and
+a library intended to be used from arbitrary other places (e.g. higher-level
+code generators) in the *lib* directory.
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
new file mode 100644
index 0000000..3a5d938
--- /dev/null
+++ b/gen/lib/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "cxx-gen"
+version = "0.3.4"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into higher level tools."
+repository = "https://github.com/dtolnay/cxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi"]
+
+[dependencies]
+anyhow = "1.0"
+cc = "1.0.49"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
+quote = { version = "1.0", default-features = false }
+syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/LICENSE-APACHE b/gen/lib/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/lib/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/lib/LICENSE-MIT b/gen/lib/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/lib/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/lib/src/gen b/gen/lib/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/lib/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
new file mode 100644
index 0000000..ba125d9
--- /dev/null
+++ b/gen/lib/src/lib.rs
@@ -0,0 +1,17 @@
+//! The CXX code generator for constructing and compiling C++ code.
+//!
+//! This is intended to be embedded into higher-level code generators.
+
+mod gen;
+mod syntax;
+
+use crate::gen::Opt;
+use proc_macro2::TokenStream;
+
+pub use crate::gen::{Error, Result, GeneratedCode};
+
+/// Generate C++ bindings code from a Rust token stream. This should be a Rust
+/// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
+pub fn generate_header_and_cc(rust_source: TokenStream) -> Result<GeneratedCode> {
+    gen::do_generate_from_tokens(rust_source, Opt::default())
+}
diff --git a/gen/lib/src/syntax b/gen/lib/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/lib/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/src/error.rs b/gen/src/error.rs
index 51dbbe7..61afd4d 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -11,13 +11,18 @@ use std::ops::Range;
 use std::path::Path;
 use std::process;
 
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+pub type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
-pub(super) enum Error {
+pub enum Error {
+    /// No `#[cxx::bridge]` module could be found.
     NoBridgeMod,
+    /// `#[cxx::bridge]` was attached to something other than
+    /// an inline module.
     OutOfLineMod,
+    /// An IO error occurred when reading Rust code.
     Io(io::Error),
+    /// A syntax error occurred when parsing Rust code.
     Syn(syn::Error),
 }
 
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 710bca2..acc7669 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -10,20 +10,23 @@ mod write;
 #[cfg(test)]
 mod tests;
 
-use self::error::{format_err, Error, Result};
+use self::error::format_err;
+pub use self::error::{Error, Result};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
+use proc_macro2::TokenStream;
+use std::clone::Clone;
 use std::fs;
 use std::path::Path;
-use syn::Item;
+use syn::{File, Item};
 
 struct Input {
     namespace: Namespace,
     module: Vec<Item>,
 }
 
-#[derive(Default)]
+#[derive(Default, Clone)]
 pub(super) struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,
@@ -32,6 +35,14 @@ pub(super) struct Opt {
     pub cxx_impl_annotations: Option<String>,
 }
 
+/// Results of code generation.
+pub struct GeneratedCode {
+    /// The bytes of a C++ header file.
+    pub header: Vec<u8>,
+    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
+    pub cxx: Vec<u8>,
+}
+
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)
@@ -42,21 +53,43 @@ pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     generate_from_path(path, opt, header)
 }
 
+pub(super) fn do_generate_from_tokens(
+    tokens: TokenStream,
+    opt: Opt,
+) -> std::result::Result<GeneratedCode, Error> {
+    let syntax = syn::parse2::<File>(tokens)?;
+    match generate(syntax, opt, true, true) {
+        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx } ),
+        Err(err) => Err(err),
+        _ => panic!("Unexpected generation"),
+    }
+}
+
 fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match generate(&source, opt, header) {
+    let syntax = match syn::parse_file(&source) {
         Ok(out) => out,
+        Err(err) => format_err(path, "", Error::Syn(err)),
+    };
+    match generate(syntax, opt, header, !header) {
+        Ok((Some(hdr), None)) => hdr,
+        Ok((None, Some(cxx))) => cxx,
         Err(err) => format_err(path, &source, err),
+        _ => panic!("Unexpected generation"),
     }
 }
 
-fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+fn generate(
+    syntax: File,
+    opt: Opt,
+    gen_header: bool,
+    gen_cxx: bool,
+) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>)> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
-    let syntax = syn::parse_file(&source)?;
     let bridge = find::find_bridge_mod(syntax)?;
     let ref namespace = bridge.namespace;
     let ref apis = syntax::parse_items(errors, bridge.module);
@@ -64,6 +97,18 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
-    let out = write::gen(namespace, apis, types, opt, header);
-    Ok(out.content())
+    // Some callers may wish to generate both header and C++
+    // from the same token stream to avoid parsing twice. But others
+    // only need to generate one or the other.
+    let hdr = if gen_header {
+        Some(write::gen(namespace, apis, types, opt.clone(), true).content())
+    } else {
+        None
+    };
+    let cxx = if gen_cxx {
+        Some(write::gen(namespace, apis, types, opt, false).content())
+    } else {
+        None
+    };
+    Ok((hdr, cxx))
 }

From 593eddb017d6715715551a6cb79801ac21ee6daf Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Aug 22 2020 06:46:08 +0000
Subject: [PATCH 681/2232] Adding tests, fixing older tests.


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index ba125d9..de76d80 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -8,10 +8,39 @@ mod syntax;
 use crate::gen::Opt;
 use proc_macro2::TokenStream;
 
-pub use crate::gen::{Error, Result, GeneratedCode};
+pub use crate::gen::{Error, GeneratedCode, Result};
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
 pub fn generate_header_and_cc(rust_source: TokenStream) -> Result<GeneratedCode> {
     gen::do_generate_from_tokens(rust_source, Opt::default())
 }
+
+#[cfg(test)]
+mod test {
+    use quote::quote;
+
+    #[test]
+    fn test_positive() {
+        let rs = quote! {
+            #[cxx::bridge]
+            mod ffi {
+                extern "C" {
+                    fn in_C();
+                }
+                extern "Rust" {
+                    fn in_rs();
+                }
+            }
+        };
+        let code = crate::generate_header_and_cc(rs).unwrap();
+        assert!(code.cxx.len() > 0);
+        assert!(code.header.len() > 0);
+    }
+
+    #[test]
+    fn test_negative() {
+        let rs = quote! {};
+        assert!(crate::generate_header_and_cc(rs).is_err())
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index acc7669..3139ed3 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -59,7 +59,7 @@ pub(super) fn do_generate_from_tokens(
 ) -> std::result::Result<GeneratedCode, Error> {
     let syntax = syn::parse2::<File>(tokens)?;
     match generate(syntax, opt, true, true) {
-        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx } ),
+        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
         Err(err) => Err(err),
         _ => panic!("Unexpected generation"),
     }
@@ -70,14 +70,18 @@ fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    let syntax = match syn::parse_file(&source) {
+    match generate_from_string(&source, opt, header) {
         Ok(out) => out,
-        Err(err) => format_err(path, "", Error::Syn(err)),
-    };
-    match generate(syntax, opt, header, !header) {
-        Ok((Some(hdr), None)) => hdr,
-        Ok((None, Some(cxx))) => cxx,
         Err(err) => format_err(path, &source, err),
+    }
+}
+
+fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+    let syntax = syn::parse_file(&source).map_err(Error::Syn)?;
+    let results = generate(syntax, opt, header, !header)?;
+    match results {
+        (Some(hdr), None) => Ok(hdr),
+        (None, Some(cxx)) => Ok(cxx),
         _ => panic!("Unexpected generation"),
     }
 }
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 0e7a910..7621643 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -1,4 +1,4 @@
-use crate::gen::{generate, Opt};
+use crate::gen::{generate_from_string, Opt};
 
 const CPP_EXAMPLE: &'static str = r#"
     #[cxx::bridge]
@@ -15,7 +15,7 @@ fn test_cpp() {
         include: Vec::new(),
         cxx_impl_annotations: None,
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
@@ -28,7 +28,7 @@ fn test_annotation() {
         include: Vec::new(),
         cxx_impl_annotations: Some("ANNOTATION".to_string()),
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From 0e79bc8fdeb4e21c5a69057c74c51f874fb35348 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 22 2020 12:57:03 +0000
Subject: [PATCH 682/2232] Update bazel build to rust 1.45


---

diff --git a/WORKSPACE b/WORKSPACE
index cd2a2e8..08e7c80 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,13 +24,13 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_44_linux",
+    name = "rust_1_45_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.44.0",
+    version = "1.45.0",
 )
 
 rust_repository_set(
-    name = "rust_1_44_darwin",
+    name = "rust_1_45_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.44.0",
+    version = "1.45.0",
 )

From 85487b00f8790fe28e8d82e9dfab3b3145503631 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 22 2020 13:13:27 +0000
Subject: [PATCH 683/2232] Add Option<T> to todo list


---

diff --git a/README.md b/README.md
index 260c272..345ce7d 100644
--- a/README.md
+++ b/README.md
@@ -330,6 +330,7 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
diff --git a/src/lib.rs b/src/lib.rs
index 0ad7255..91e0098 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -341,6 +341,7 @@
 //! <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+//! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>

From 7ca810b1e81d32f4d912d0fb752aadfa056363c2 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Aug 25 2020 00:58:36 +0000
Subject: [PATCH 684/2232] Guess at BUCK and BUILD rules.


---

diff --git a/BUCK b/BUCK
index c554e1f..a58e0a2 100644
--- a/BUCK
+++ b/BUCK
@@ -68,3 +68,17 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "lib",
+    srcs = glob(["gen/lib/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/BUILD b/BUILD
index d5255a8..017b7cc 100644
--- a/BUILD
+++ b/BUILD
@@ -67,3 +67,18 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "lib",
+    srcs = glob(["gen/lib/src/**/*.rs"]),
+    data = ["gen/build/src/gen/include/cxx.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)

From 0926f644ee592d0d65065991fe8263c1b657cc8d Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Aug 25 2020 20:08:06 +0000
Subject: [PATCH 685/2232] Allow configurable options during C++ codegen.


This commit allows a higher-level code generator to pass options
into the cxx code generator.

---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index de76d80..cecf654 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -5,15 +5,15 @@
 mod gen;
 mod syntax;
 
-use crate::gen::Opt;
+pub use crate::gen::Opt;
 use proc_macro2::TokenStream;
 
 pub use crate::gen::{Error, GeneratedCode, Result};
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
-pub fn generate_header_and_cc(rust_source: TokenStream) -> Result<GeneratedCode> {
-    gen::do_generate_from_tokens(rust_source, Opt::default())
+pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
+    gen::do_generate_from_tokens(rust_source, opt)
 }
 
 #[cfg(test)]
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 3139ed3..f2e5c9b 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -26,8 +26,9 @@ struct Input {
     module: Vec<Item>,
 }
 
+/// Options for C++ code generation.
 #[derive(Default, Clone)]
-pub(super) struct Opt {
+pub struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,
     /// Whether to set __attribute__((visibility("default")))

From 5a6c7b534d33680606570ffe78b025c145fe6655 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Aug 25 2020 20:08:38 +0000
Subject: [PATCH 686/2232] Add option to omit type definitions.


A higher-level code generator may provide instructions to cxx
based on existing defined C++ types. In such an instance, we don't want
cxx to redefine those types, because this will cause violations of the
one-definition-rule. This commit provides an option to prevent such
redefinition.

As this is only likely to be used from higher-level code generators,
we do not expose this option via 'cmd' or 'build' front-ends for
code generation.

---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index f2e5c9b..1c84a23 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -34,6 +34,8 @@ pub struct Opt {
     /// Whether to set __attribute__((visibility("default")))
     /// or similar annotations on function implementations.
     pub cxx_impl_annotations: Option<String>,
+    /// Whether to omit definitions of types.
+    pub omit_type_definitions: bool,
 }
 
 /// Results of code generation.
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 51c4b02..b184b52 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -60,7 +60,7 @@ pub(super) fn gen(
 
     for api in apis {
         match api {
-            Api::Struct(strct) => {
+            Api::Struct(strct) if !opt.omit_type_definitions => {
                 out.next_section();
                 write_struct(out, strct);
             }
@@ -68,7 +68,7 @@ pub(super) fn gen(
                 out.next_section();
                 if types.cxx.contains(&enm.ident) {
                     check_enum(out, enm);
-                } else {
+                } else if !opt.omit_type_definitions {
                     write_enum(out, enm);
                 }
             }

From a08b19f5b1908939642ada54a343eae339edf4dc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 26 2020 02:21:16 +0000
Subject: [PATCH 687/2232] Add include required for back_inserter


See failure in https://github.com/dtolnay/cxx/issues/260.

---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d70d5a0..060b8aa 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,6 +1,7 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs.h"
 #include <cstring>
+#include <iterator>
 #include <numeric>
 #include <stdexcept>
 

From 691dc171b5f0f34478a02129a7e1e784c591911e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 26 2020 02:56:12 +0000
Subject: [PATCH 688/2232] Update ui tests with rust-src component installed


---

diff --git a/Cargo.toml b/Cargo.toml
index 1e0ad0f..234b098 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,7 +29,7 @@ cc = "1.0.49"
 cxx-build = { version = "=0.3.4", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
-trybuild = { version = "1.0.32", features = ["diff"] }
+trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
 members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index efd1144..698fda7 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -4,5 +4,10 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
 4   |         type TypeR;
     |              ^^^^^ doesn't have a size known at compile-time
     |
+   ::: $RUST/core/src/ptr/mod.rs
+    |
+    | pub unsafe fn read<T>(src: *const T) -> T {
+    |                    - required by this bound in `std::ptr::read`
+    |
     = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
     = note: required because it appears within the type `TypeR`

From c8361027d982ddf07c28a4bba1ff20a8618e1955 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 26 2020 05:03:00 +0000
Subject: [PATCH 689/2232] Remove dependency of ui test on whether rust-src is installed


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f28d955..431fd3b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -31,11 +31,7 @@ fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> T
     for api in apis {
         if let Api::RustType(ety) = api {
             expanded.extend(expand_rust_type(ety));
-            let ident = &ety.ident;
-            let span = ident.span();
-            hidden.extend(quote_spanned! {span=>
-                let _ = ::std::ptr::read::<#ident>;
-            });
+            hidden.extend(expand_rust_type_assert_sized(ety));
         }
     }
 
@@ -426,6 +422,28 @@ fn expand_rust_type(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
+    // Rustc will render as follows if not sized:
+    //
+    //     type TheirType;
+    //     -----^^^^^^^^^-
+    //     |    |
+    //     |    doesn't have a size known at compile-time
+    //     required by this bound in `ffi::_::__AssertSized`
+
+    let ident = &ety.ident;
+    let begin_span = Token![::](ety.type_token.span);
+    let sized = quote_spanned! {ety.semi_token.span=>
+        #begin_span std::marker::Sized
+    };
+    quote_spanned! {ident.span()=>
+        let _ = {
+            fn __AssertSized<T: ?#sized + #sized>() {}
+            __AssertSized::<#ident>
+        };
+    }
+}
+
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
     let ident = &efn.ident;
     let link_name = mangle::extern_fn(namespace, efn);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 88c96e8..cd6f235 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -46,6 +46,7 @@ pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
     pub ident: Ident,
+    pub semi_token: Token![;],
 }
 
 pub struct Struct {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a1d31cf..e195081 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -242,6 +242,7 @@ fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang
     let doc = attrs::parse_doc(cx, &foreign_type.attrs);
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
+    let semi_token = foreign_type.semi_token;
     let api_type = match lang {
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
@@ -250,6 +251,7 @@ fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang
         doc,
         type_token,
         ident,
+        semi_token,
     }))
 }
 
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 698fda7..366a8f4 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -1,13 +1,11 @@
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-   --> $DIR/opaque_not_sized.rs:4:14
-    |
-4   |         type TypeR;
-    |              ^^^^^ doesn't have a size known at compile-time
-    |
-   ::: $RUST/core/src/ptr/mod.rs
-    |
-    | pub unsafe fn read<T>(src: *const T) -> T {
-    |                    - required by this bound in `std::ptr::read`
-    |
-    = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
-    = note: required because it appears within the type `TypeR`
+ --> $DIR/opaque_not_sized.rs:4:14
+  |
+4 |         type TypeR;
+  |         -----^^^^^-
+  |         |    |
+  |         |    doesn't have a size known at compile-time
+  |         required by this bound in `ffi::_::__AssertSized`
+  |
+  = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
+  = note: required because it appears within the type `TypeR`

From 041c9040ba4f678e87622ea59515e16f35eeb1e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 26 2020 05:16:15 +0000
Subject: [PATCH 690/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 78fb2a9..585dafd 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -14,13 +14,13 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.58/src/**"]),
+    srcs = glob(["vendor/cc-1.0.59/src/**"]),
     visibility = ["PUBLIC"],
 )
 
 rust_library(
     name = "clap",
-    srcs = glob(["vendor/clap-2.33.1/src/**"]),
+    srcs = glob(["vendor/clap-2.33.3/src/**"]),
     edition = "2015",
     visibility = ["PUBLIC"],
     deps = [
@@ -77,7 +77,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.36/src/**"]),
+    srcs = glob(["vendor/syn-1.0.39/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 3e0e30b..65edf92 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -19,13 +19,13 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.58/src/**"]),
+    srcs = glob(["vendor/cc-1.0.59/src/**"]),
     visibility = ["//visibility:public"],
 )
 
 rust_library(
     name = "clap",
-    srcs = glob(["vendor/clap-2.33.1/src/**"]),
+    srcs = glob(["vendor/clap-2.33.3/src/**"]),
     edition = "2015",
     visibility = ["//visibility:public"],
     deps = [
@@ -82,7 +82,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.36/src/**"]),
+    srcs = glob(["vendor/syn-1.0.39/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 763a429..10c577d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -34,15 +34,15 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.58"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
+checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
 
 [[package]]
 name = "clap"
-version = "2.33.1"
+version = "2.33.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
+checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
 dependencies = [
  "ansi_term",
  "atty",
@@ -161,9 +161,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.74"
+version = "0.2.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
+checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
 
 [[package]]
 name = "link-cplusplus"
@@ -211,18 +211,18 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
 
 [[package]]
 name = "serde"
-version = "1.0.114"
+version = "1.0.115"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
+checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.114"
+version = "1.0.115"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
+checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -248,9 +248,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.36"
+version = "1.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
+checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -286,9 +286,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.32"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fe571fc1c805a7dc57340d2be54d72a96010a46a05c57018863f3b1cb93d28"
+checksum = "48105a4deaf74163c017939b45ef7322fba46e8b17281528039b0beb04235e92"
 dependencies = [
  "dissimilar",
  "glob",

From fb8ddd8eb398f41b09f5befd46250dc9e4c00455 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 04:49:23 +0000
Subject: [PATCH 691/2232] Merge pull request #257 from rinon/rust_vec_accessors


Add rust::Vec accessors
---

diff --git a/include/cxx.h b/include/cxx.h
index c3231fd..786dbb3 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -5,6 +5,7 @@
 #include <exception>
 #include <iosfwd>
 #include <new>
+#include <stdexcept>
 #include <string>
 #include <type_traits>
 #include <utility>
@@ -13,6 +14,26 @@
 #include <BaseTsd.h>
 #endif
 
+#ifndef __has_feature
+#define __has_feature(__x) 0
+#endif
+
+#if !__has_feature(cxx_exceptions)
+#  define _CXXBRIDGE03_NO_EXCEPTIONS
+#endif
+#if !__EXCEPTIONS
+#  define _CXXBRIDGE03_NO_EXCEPTIONS
+#endif
+
+[[noreturn]] inline static void throw_out_of_range(const char *msg) {
+#ifndef _CXXBRIDGE03_NO_EXCEPTIONS
+  throw std::out_of_range(msg);
+#else
+  ((void)msg);
+  std::abort();
+#endif
+}
+
 namespace rust {
 inline namespace cxxbridge03 {
 
@@ -175,6 +196,12 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
 
+  const T &operator[](size_t n) const noexcept;
+  const T &at(size_t n) const;
+
+  const T &front() const;
+  const T &back() const;
+
   class const_iterator {
   public:
     using difference_type = ptrdiff_t;
@@ -464,6 +491,29 @@ bool Vec<T>::empty() const noexcept {
 }
 
 template <typename T>
+const T &Vec<T>::operator[](size_t n) const noexcept {
+  auto data = reinterpret_cast<const char *>(this->data());
+  return *reinterpret_cast<const T *>(data + n * this->stride());
+}
+
+template <typename T>
+const T &Vec<T>::at(size_t n) const {
+  if (n >= this->size())
+    throw_out_of_range("Vec");
+  return (*this)[n];
+}
+
+template <typename T>
+const T &Vec<T>::front() const {
+  return (*this)[0];
+}
+
+template <typename T>
+const T &Vec<T>::back() const {
+  return (*this)[this->size()-1];
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 84a746b..e491343 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -11,6 +11,7 @@ use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
+    #[derive(Clone)]
     struct Shared {
         z: usize,
     }
@@ -61,8 +62,11 @@ pub mod ffi {
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
         fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_rust_vec_index(v: Vec<u8>);
+        fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
+        fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         /*
         // https://github.com/dtolnay/cxx/issues/232
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 060b8aa..66200e5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -209,6 +209,8 @@ void c_take_ref_vector(const std::vector<uint8_t> &v) {
 
 void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
 
+void c_take_rust_vec_index(rust::Vec<uint8_t> v) { c_take_ref_rust_vec_index(v); }
+
 void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   uint32_t sum = 0;
   for (auto i : v) {
@@ -231,6 +233,17 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
+  if (v[0].z == 1010 &&
+      v.at(0).z == 1010 &&
+      v.front().z == 1010 &&
+      v[1].z == 1011 &&
+      v.at(1).z == 1011 &&
+      v.back().z == 1011) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
@@ -238,6 +251,19 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   }
 }
 
+void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
+  if (v[0] == 86 &&
+      v.at(0) == 86 &&
+      v.front() == 86 &&
+      v[1] == 75 &&
+      v.at(1) == 75 &&
+      v[3] == 9 &&
+      v.at(3) == 9 &&
+      v.back() == 9) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   // The std::copy() will make sure rust::Vec<>::const_iterator satisfies the
   // requirements for std::iterator_traits.
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7121cb2..7b7d273 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -65,9 +65,12 @@ void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
+void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 /*
 // https://github.com/dtolnay/cxx/issues/232
diff --git a/tests/test.rs b/tests/test.rs
index f2f670c..55c28d2 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -108,15 +108,16 @@ fn test_c_take() {
     check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8()));
     let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
     check!(ffi::c_take_rust_vec(test_vec.clone()));
-    check!(ffi::c_take_rust_vec_shared(vec![
+    check!(ffi::c_take_rust_vec_index(test_vec.clone()));
+    let shared_test_vec = vec![
         ffi::Shared { z: 1010 },
         ffi::Shared { z: 1011 }
-    ]));
-    check!(ffi::c_take_rust_vec_shared_forward_iterator(vec![
-        ffi::Shared { z: 1010 },
-        ffi::Shared { z: 1011 }
-    ]));
+    ];
+    check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_forward_iterator(shared_test_vec));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
+    check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
     check!(ffi::c_take_enum(ffi::Enum::AVal));
 }

From 521d99d0930abd3171ff4296a548e8a9143723ea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 04:50:11 +0000
Subject: [PATCH 692/2232] Unify the way that String construction and Vec indexing throw


---

diff --git a/include/cxx.h b/include/cxx.h
index 786dbb3..d3f6238 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -14,26 +14,6 @@
 #include <BaseTsd.h>
 #endif
 
-#ifndef __has_feature
-#define __has_feature(__x) 0
-#endif
-
-#if !__has_feature(cxx_exceptions)
-#  define _CXXBRIDGE03_NO_EXCEPTIONS
-#endif
-#if !__EXCEPTIONS
-#  define _CXXBRIDGE03_NO_EXCEPTIONS
-#endif
-
-[[noreturn]] inline static void throw_out_of_range(const char *msg) {
-#ifndef _CXXBRIDGE03_NO_EXCEPTIONS
-  throw std::out_of_range(msg);
-#else
-  ((void)msg);
-  std::abort();
-#endif
-}
-
 namespace rust {
 inline namespace cxxbridge03 {
 
@@ -303,6 +283,9 @@ using try_fn = TryFn<Signature>;
 ////////////////////////////////////////////////////////////////////////////////
 /// end public API, begin implementation details
 
+template <typename Exception>
+void panic [[noreturn]] (const char *msg);
+
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -499,7 +482,7 @@ const T &Vec<T>::operator[](size_t n) const noexcept {
 template <typename T>
 const T &Vec<T>::at(size_t n) const {
   if (n >= this->size())
-    throw_out_of_range("Vec");
+    panic<std::out_of_range>("Vec");
   return (*this)[n];
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index da05ee2..0fa55b2 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -6,16 +6,6 @@
 #include <stdexcept>
 #include <vector>
 
-template <typename Exception>
-static void panic [[noreturn]] (const char *msg) {
-#if defined(RUST_CXX_NO_EXCEPTIONS)
-  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
-  std::terminate();
-#else
-  throw Exception(msg);
-#endif
-}
-
 extern "C" {
 const char *cxxbridge03$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -42,6 +32,18 @@ bool cxxbridge03$str$valid(const char *ptr, size_t len) noexcept;
 namespace rust {
 inline namespace cxxbridge03 {
 
+template <typename Exception>
+void panic [[noreturn]] (const char *msg) {
+#if defined(RUST_CXX_NO_EXCEPTIONS)
+  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
+  std::terminate();
+#else
+  throw Exception(msg);
+#endif
+}
+
+template void panic<std::out_of_range>(const char *msg);
+
 String::String() noexcept { cxxbridge03$string$new(this); }
 
 String::String(const String &other) noexcept {

From 78c1e6b761bd7b3f43435a2e32f2d08f50f2e2d6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 05:05:49 +0000
Subject: [PATCH 693/2232] Resolve 'Failed to specialize function template' MSVC error


Before:

    src/cxx.cc(295): error C2893: Failed to specialize function template 'void rust::cxxbridge03::panic(const char *)'
    D:\a\cxx\cxx\src\../include/cxx.h(287): note: see declaration of 'rust::cxxbridge03::panic'
    src/cxx.cc(295): note: With the following template arguments:
    src/cxx.cc(295): note: 'Exception=std::out_of_range'

---

diff --git a/src/cxx.cc b/src/cxx.cc
index 0fa55b2..2d2349d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -42,7 +42,7 @@ void panic [[noreturn]] (const char *msg) {
 #endif
 }
 
-template void panic<std::out_of_range>(const char *msg);
+template void panic<std::out_of_range> [[noreturn]] (const char *msg);
 
 String::String() noexcept { cxxbridge03$string$new(this); }
 

From 001e6f0c7ce5e93b01cacf06ec750779b020ac04 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 05:13:22 +0000
Subject: [PATCH 694/2232] Merge pull request #262 from dtolnay/throw


Unify the way that String construction and Vec indexing throw
---

diff --git a/include/cxx.h b/include/cxx.h
index 786dbb3..d3f6238 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -14,26 +14,6 @@
 #include <BaseTsd.h>
 #endif
 
-#ifndef __has_feature
-#define __has_feature(__x) 0
-#endif
-
-#if !__has_feature(cxx_exceptions)
-#  define _CXXBRIDGE03_NO_EXCEPTIONS
-#endif
-#if !__EXCEPTIONS
-#  define _CXXBRIDGE03_NO_EXCEPTIONS
-#endif
-
-[[noreturn]] inline static void throw_out_of_range(const char *msg) {
-#ifndef _CXXBRIDGE03_NO_EXCEPTIONS
-  throw std::out_of_range(msg);
-#else
-  ((void)msg);
-  std::abort();
-#endif
-}
-
 namespace rust {
 inline namespace cxxbridge03 {
 
@@ -303,6 +283,9 @@ using try_fn = TryFn<Signature>;
 ////////////////////////////////////////////////////////////////////////////////
 /// end public API, begin implementation details
 
+template <typename Exception>
+void panic [[noreturn]] (const char *msg);
+
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -499,7 +482,7 @@ const T &Vec<T>::operator[](size_t n) const noexcept {
 template <typename T>
 const T &Vec<T>::at(size_t n) const {
   if (n >= this->size())
-    throw_out_of_range("Vec");
+    panic<std::out_of_range>("Vec");
   return (*this)[n];
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index da05ee2..2d2349d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -6,16 +6,6 @@
 #include <stdexcept>
 #include <vector>
 
-template <typename Exception>
-static void panic [[noreturn]] (const char *msg) {
-#if defined(RUST_CXX_NO_EXCEPTIONS)
-  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
-  std::terminate();
-#else
-  throw Exception(msg);
-#endif
-}
-
 extern "C" {
 const char *cxxbridge03$cxx_string$data(const std::string &s) noexcept {
   return s.data();
@@ -42,6 +32,18 @@ bool cxxbridge03$str$valid(const char *ptr, size_t len) noexcept;
 namespace rust {
 inline namespace cxxbridge03 {
 
+template <typename Exception>
+void panic [[noreturn]] (const char *msg) {
+#if defined(RUST_CXX_NO_EXCEPTIONS)
+  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
+  std::terminate();
+#else
+  throw Exception(msg);
+#endif
+}
+
+template void panic<std::out_of_range> [[noreturn]] (const char *msg);
+
 String::String() noexcept { cxxbridge03$string$new(this); }
 
 String::String(const String &other) noexcept {

From 61adf428be27bc20200c87a977692a39219f1b5f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 05:13:31 +0000
Subject: [PATCH 695/2232] Add test for Vec<T>::at exception message


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 66200e5..4ab407b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -209,7 +209,16 @@ void c_take_ref_vector(const std::vector<uint8_t> &v) {
 
 void c_take_rust_vec(rust::Vec<uint8_t> v) { c_take_ref_rust_vec(v); }
 
-void c_take_rust_vec_index(rust::Vec<uint8_t> v) { c_take_ref_rust_vec_index(v); }
+void c_take_rust_vec_index(rust::Vec<uint8_t> v) {
+  try {
+    v.at(100);
+  } catch (const std::out_of_range &ex) {
+    std::string expected = "Vec";
+    if (ex.what() == expected) {
+      cxx_test_suite_set_correct();
+    }
+  }
+}
 
 void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   uint32_t sum = 0;

From 8e1e6ac25cf899cf7030f11b6096b991ad261381 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 05:13:31 +0000
Subject: [PATCH 696/2232] Extend exception message from Vec<T>::at


---

diff --git a/include/cxx.h b/include/cxx.h
index d3f6238..90c0524 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -481,8 +481,9 @@ const T &Vec<T>::operator[](size_t n) const noexcept {
 
 template <typename T>
 const T &Vec<T>::at(size_t n) const {
-  if (n >= this->size())
-    panic<std::out_of_range>("Vec");
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Vec index out of range");
+  }
   return (*this)[n];
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4ab407b..682b9c9 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -213,7 +213,7 @@ void c_take_rust_vec_index(rust::Vec<uint8_t> v) {
   try {
     v.at(100);
   } catch (const std::out_of_range &ex) {
-    std::string expected = "Vec";
+    std::string expected = "rust::Vec index out of range";
     if (ex.what() == expected) {
       cxx_test_suite_set_correct();
     }

From b10c4bc33a77bf17b94d6f1815383c686cebf9b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 05:13:31 +0000
Subject: [PATCH 697/2232] Format with clang-format 10


---

diff --git a/include/cxx.h b/include/cxx.h
index 90c0524..9a9d5fa 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -494,7 +494,7 @@ const T &Vec<T>::front() const {
 
 template <typename T>
 const T &Vec<T>::back() const {
-  return (*this)[this->size()-1];
+  return (*this)[this->size() - 1];
 }
 
 template <typename T>
@@ -522,14 +522,14 @@ Vec<T>::const_iterator::operator++(int) noexcept {
 }
 
 template <typename T>
-bool Vec<T>::const_iterator::operator==(const const_iterator &other) const
-    noexcept {
+bool Vec<T>::const_iterator::operator==(
+    const const_iterator &other) const noexcept {
   return this->pos == other.pos;
 }
 
 template <typename T>
-bool Vec<T>::const_iterator::operator!=(const const_iterator &other) const
-    noexcept {
+bool Vec<T>::const_iterator::operator!=(
+    const const_iterator &other) const noexcept {
   return this->pos != other.pos;
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 2d2349d..b953904 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -42,7 +42,7 @@ void panic [[noreturn]] (const char *msg) {
 #endif
 }
 
-template void panic<std::out_of_range> [[noreturn]] (const char *msg);
+template void panic<std::out_of_range>[[noreturn]] (const char *msg);
 
 String::String() noexcept { cxxbridge03$string$new(this); }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 682b9c9..4cc771e 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -243,12 +243,8 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
 }
 
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
-  if (v[0].z == 1010 &&
-      v.at(0).z == 1010 &&
-      v.front().z == 1010 &&
-      v[1].z == 1011 &&
-      v.at(1).z == 1011 &&
-      v.back().z == 1011) {
+  if (v[0].z == 1010 && v.at(0).z == 1010 && v.front().z == 1010 &&
+      v[1].z == 1011 && v.at(1).z == 1011 && v.back().z == 1011) {
     cxx_test_suite_set_correct();
   }
 }
@@ -261,14 +257,8 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
 }
 
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
-  if (v[0] == 86 &&
-      v.at(0) == 86 &&
-      v.front() == 86 &&
-      v[1] == 75 &&
-      v.at(1) == 75 &&
-      v[3] == 9 &&
-      v.at(3) == 9 &&
-      v.back() == 9) {
+  if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
+      v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
     cxx_test_suite_set_correct();
   }
 }

From a7ba6a629ced417a20b1ba15d88e37d05409c704 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 07:15:55 +0000
Subject: [PATCH 698/2232] Format with rustfmt 1.4.20


---

diff --git a/tests/test.rs b/tests/test.rs
index 55c28d2..9c71bd5 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -109,13 +109,12 @@ fn test_c_take() {
     let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec();
     check!(ffi::c_take_rust_vec(test_vec.clone()));
     check!(ffi::c_take_rust_vec_index(test_vec.clone()));
-    let shared_test_vec = vec![
-        ffi::Shared { z: 1010 },
-        ffi::Shared { z: 1011 }
-    ];
+    let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }];
     check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
-    check!(ffi::c_take_rust_vec_shared_forward_iterator(shared_test_vec));
+    check!(ffi::c_take_rust_vec_shared_forward_iterator(
+        shared_test_vec,
+    ));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));

From f1c7f3219be65b9afe247401a75ca35ca6dca075 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 07:58:15 +0000
Subject: [PATCH 699/2232] Handle &mut reference in more places


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 431fd3b..ab1206c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -256,10 +256,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    quote!(::cxx::private::RustString::from_ref(#var))
-                }
-                Type::RustVec(_) => quote!(::cxx::private::RustVec::from_ref(#var)),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => quote!(::cxx::private::RustString::from_ref(#var)),
+                    Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => quote!(::cxx::private::RustVec::from_ref(#var)),
+                    Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
+                },
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -331,10 +335,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    Some(quote!(#call.map(|r| r.as_string())))
-                }
-                Type::RustVec(_) => Some(quote!(#call.map(|r| r.as_vec()))),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_string()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_vec()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
@@ -348,8 +356,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::RustVec(_) => Some(quote!(#call.into_vec())),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
-                Type::RustVec(_) => Some(quote!(#call.as_vec())),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(#call.as_string())),
+                    Some(_) => Some(quote!(#call.as_mut_string())),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(#call.as_vec())),
+                    Some(_) => Some(quote!(#call.as_mut_vec())),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
@@ -497,8 +511,14 @@ fn expand_rust_function_shim_impl(
             Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i == RustString => quote!(#ident.as_string()),
-                Type::RustVec(_) => quote!(#ident.as_vec()),
+                Type::Ident(i) if i == RustString => match ty.mutability {
+                    None => quote!(#ident.as_string()),
+                    Some(_) => quote!(#ident.as_mut_string()),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => quote!(#ident.as_vec()),
+                    Some(_) => quote!(#ident.as_mut_vec()),
+                },
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -532,10 +552,14 @@ fn expand_rust_function_shim_impl(
             Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    Some(quote!(::cxx::private::RustString::from_ref(#call)))
-                }
-                Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
@@ -860,14 +884,19 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             let elem = expand_extern_type(&ty.inner);
             quote!(::cxx::private::RustVec<#elem>)
         }
-        Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
-            Type::RustVec(ty) => {
-                let inner = expand_extern_type(&ty.inner);
-                quote!(&::cxx::private::RustVec<#inner>)
+        Type::Ref(ty) => {
+            let mutability = ty.mutability;
+            match &ty.inner {
+                Type::Ident(ident) if ident == RustString => {
+                    quote!(&#mutability ::cxx::private::RustString)
+                }
+                Type::RustVec(ty) => {
+                    let inner = expand_extern_type(&ty.inner);
+                    quote!(&#mutability ::cxx::private::RustVec<#inner>)
+                }
+                _ => quote!(#ty),
             }
-            _ => quote!(#ty),
-        },
+        }
         Type::Str(_) => quote!(::cxx::private::RustStr),
         Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
         _ => quote!(#ty),
diff --git a/src/rust_string.rs b/src/rust_string.rs
index a923ced..f0d1df1 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -14,6 +14,10 @@ impl RustString {
         unsafe { &*(s as *const String as *const RustString) }
     }
 
+    pub fn from_mut(s: &mut String) -> &mut Self {
+        unsafe { &mut *(s as *mut String as *mut RustString) }
+    }
+
     pub fn into_string(self) -> String {
         self.repr
     }
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 4c5035d..9ff4bbf 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -16,6 +16,10 @@ impl<T> RustVec<T> {
         unsafe { &*(v as *const Vec<T> as *const RustVec<T>) }
     }
 
+    pub fn from_mut(v: &mut Vec<T>) -> &mut Self {
+        unsafe { &mut *(v as *mut Vec<T> as *mut RustVec<T>) }
+    }
+
     pub fn into_vec(self) -> Vec<T> {
         self.repr
     }

From 18d93b6d5850c54bd64b08f128018de9d919826a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 08:00:18 +0000
Subject: [PATCH 700/2232] Add &mut tests


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e491343..d69163a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -32,6 +32,7 @@ pub mod ffi {
         fn c_return_box() -> Box<R>;
         fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
+        fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
@@ -41,8 +42,10 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
+        fn c_return_mut_vector(c: &mut C) -> &mut CxxVector<u8>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
+        fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
@@ -113,11 +116,13 @@ pub mod ffi {
         fn r_return_box() -> Box<R>;
         fn r_return_unique_ptr() -> UniquePtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
+        fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
+        fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
         fn r_return_sum(_: usize, _: usize) -> usize;
         fn r_return_enum(n: u32) -> Enum;
@@ -195,6 +200,10 @@ fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
 
+fn r_return_mut(shared: &mut ffi::Shared) -> &mut usize {
+    &mut shared.z
+}
+
 fn r_return_str(shared: &ffi::Shared) -> &str {
     let _ = shared;
     "2020"
@@ -220,6 +229,11 @@ fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     unimplemented!()
 }
 
+fn r_return_mut_rust_vec(shared: &mut ffi::Shared) -> &mut Vec<u8> {
+    let _ = shared;
+    unimplemented!()
+}
+
 fn r_return_identity(n: usize) -> usize {
     n
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4cc771e..b213930 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,6 +35,8 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
+std::vector<uint8_t> &C::get_v() { return this->v; }
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -49,6 +51,8 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
+size_t &c_return_mut(Shared &shared) { return shared.z; }
+
 rust::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
@@ -99,6 +103,8 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
   return c.get_v();
 }
 
+std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); }
+
 rust::Vec<uint8_t> c_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
@@ -108,6 +114,11 @@ const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
+}
+
 size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7b7d273..fe644eb 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,6 +19,7 @@ public:
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
+  std::vector<uint8_t> &get_v();
 
 private:
   size_t n;
@@ -35,6 +36,7 @@ Shared c_return_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
+size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
@@ -44,8 +46,10 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
+std::vector<uint8_t> &c_return_mut_vector(C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
+rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);

From adf67ae1e5612d8068699fc1855c102b2ec34134 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 08:09:17 +0000
Subject: [PATCH 701/2232] Merge pull request #263 from dtolnay/mut


Handle &mut reference in more places
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 431fd3b..ab1206c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -256,10 +256,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    quote!(::cxx::private::RustString::from_ref(#var))
-                }
-                Type::RustVec(_) => quote!(::cxx::private::RustVec::from_ref(#var)),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => quote!(::cxx::private::RustString::from_ref(#var)),
+                    Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => quote!(::cxx::private::RustVec::from_ref(#var)),
+                    Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
+                },
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -331,10 +335,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    Some(quote!(#call.map(|r| r.as_string())))
-                }
-                Type::RustVec(_) => Some(quote!(#call.map(|r| r.as_vec()))),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_string()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_vec()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
@@ -348,8 +356,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             Type::RustVec(_) => Some(quote!(#call.into_vec())),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => Some(quote!(#call.as_string())),
-                Type::RustVec(_) => Some(quote!(#call.as_vec())),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(#call.as_string())),
+                    Some(_) => Some(quote!(#call.as_mut_string())),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(#call.as_vec())),
+                    Some(_) => Some(quote!(#call.as_mut_vec())),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(#call.as_str())),
@@ -497,8 +511,14 @@ fn expand_rust_function_shim_impl(
             Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i == RustString => quote!(#ident.as_string()),
-                Type::RustVec(_) => quote!(#ident.as_vec()),
+                Type::Ident(i) if i == RustString => match ty.mutability {
+                    None => quote!(#ident.as_string()),
+                    Some(_) => quote!(#ident.as_mut_string()),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => quote!(#ident.as_vec()),
+                    Some(_) => quote!(#ident.as_mut_vec()),
+                },
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -532,10 +552,14 @@ fn expand_rust_function_shim_impl(
             Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
-                    Some(quote!(::cxx::private::RustString::from_ref(#call)))
-                }
-                Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
+                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
+                },
+                Type::RustVec(_) => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
+                },
                 _ => None,
             },
             Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
@@ -860,14 +884,19 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
             let elem = expand_extern_type(&ty.inner);
             quote!(::cxx::private::RustVec<#elem>)
         }
-        Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident == RustString => quote!(&::cxx::private::RustString),
-            Type::RustVec(ty) => {
-                let inner = expand_extern_type(&ty.inner);
-                quote!(&::cxx::private::RustVec<#inner>)
+        Type::Ref(ty) => {
+            let mutability = ty.mutability;
+            match &ty.inner {
+                Type::Ident(ident) if ident == RustString => {
+                    quote!(&#mutability ::cxx::private::RustString)
+                }
+                Type::RustVec(ty) => {
+                    let inner = expand_extern_type(&ty.inner);
+                    quote!(&#mutability ::cxx::private::RustVec<#inner>)
+                }
+                _ => quote!(#ty),
             }
-            _ => quote!(#ty),
-        },
+        }
         Type::Str(_) => quote!(::cxx::private::RustStr),
         Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
         _ => quote!(#ty),
diff --git a/src/rust_string.rs b/src/rust_string.rs
index a923ced..f0d1df1 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -14,6 +14,10 @@ impl RustString {
         unsafe { &*(s as *const String as *const RustString) }
     }
 
+    pub fn from_mut(s: &mut String) -> &mut Self {
+        unsafe { &mut *(s as *mut String as *mut RustString) }
+    }
+
     pub fn into_string(self) -> String {
         self.repr
     }
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 4c5035d..9ff4bbf 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -16,6 +16,10 @@ impl<T> RustVec<T> {
         unsafe { &*(v as *const Vec<T> as *const RustVec<T>) }
     }
 
+    pub fn from_mut(v: &mut Vec<T>) -> &mut Self {
+        unsafe { &mut *(v as *mut Vec<T> as *mut RustVec<T>) }
+    }
+
     pub fn into_vec(self) -> Vec<T> {
         self.repr
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e491343..d69163a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -32,6 +32,7 @@ pub mod ffi {
         fn c_return_box() -> Box<R>;
         fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
+        fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
         fn c_return_rust_string() -> String;
@@ -41,8 +42,10 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
+        fn c_return_mut_vector(c: &mut C) -> &mut CxxVector<u8>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
+        fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
@@ -113,11 +116,13 @@ pub mod ffi {
         fn r_return_box() -> Box<R>;
         fn r_return_unique_ptr() -> UniquePtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
+        fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
+        fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
         fn r_return_sum(_: usize, _: usize) -> usize;
         fn r_return_enum(n: u32) -> Enum;
@@ -195,6 +200,10 @@ fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
 
+fn r_return_mut(shared: &mut ffi::Shared) -> &mut usize {
+    &mut shared.z
+}
+
 fn r_return_str(shared: &ffi::Shared) -> &str {
     let _ = shared;
     "2020"
@@ -220,6 +229,11 @@ fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     unimplemented!()
 }
 
+fn r_return_mut_rust_vec(shared: &mut ffi::Shared) -> &mut Vec<u8> {
+    let _ = shared;
+    unimplemented!()
+}
+
 fn r_return_identity(n: usize) -> usize {
     n
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4cc771e..b213930 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,6 +35,8 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
+std::vector<uint8_t> &C::get_v() { return this->v; }
+
 size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
@@ -49,6 +51,8 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
+size_t &c_return_mut(Shared &shared) { return shared.z; }
+
 rust::Str c_return_str(const Shared &shared) {
   (void)shared;
   return "2020";
@@ -99,6 +103,8 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
   return c.get_v();
 }
 
+std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); }
+
 rust::Vec<uint8_t> c_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
@@ -108,6 +114,11 @@ const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
+  (void)c;
+  throw std::runtime_error("unimplemented");
+}
+
 size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7b7d273..fe644eb 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,6 +19,7 @@ public:
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
+  std::vector<uint8_t> &get_v();
 
 private:
   size_t n;
@@ -35,6 +36,7 @@ Shared c_return_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
+size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
@@ -44,8 +46,10 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
+std::vector<uint8_t> &c_return_mut_vector(C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
+rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c);
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);

From f7a592bfcfdf645c36ec9dbe2a6b1e701864a8eb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 27 2020 08:14:08 +0000
Subject: [PATCH 702/2232] Release 0.3.5


---

diff --git a/Cargo.toml b/Cargo.toml
index 234b098..1c59ccb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.4" # remember to update html_root_url
+version = "0.3.5" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -19,14 +19,14 @@ default = [] # c++11
 "c++17" = []
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.4", path = "macro" }
+cxxbridge-macro = { version = "=0.3.5", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.4", path = "gen/build" }
+cxx-build = { version = "=0.3.5", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b43a37e..b242383 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.4"
+version = "0.3.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b9d4b78..c0cfeb4 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.4"
+version = "0.3.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 21c4318..1b85847 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.4"
+version = "0.3.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 91e0098..69e45b3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.4")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.5")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 10c577d..aea33a4 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.4"
+version = "0.3.5"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.4"
+version = "0.3.5"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.4"
+version = "0.3.5"
 dependencies = [
  "anyhow",
  "clap",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.4"
+version = "0.3.5"
 dependencies = [
  "cxx",
  "proc-macro2",

From 57003b0e78e240315fa12742fd42a252d3da7206 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 05:57:13 +0000
Subject: [PATCH 703/2232] Inline writing include guard


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 51c4b02..1196837 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -314,7 +314,16 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
-    write_include_guard_start(out, &strct.ident);
+    writeln!(
+        out,
+        "#ifndef CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, strct.ident,
+    );
+    writeln!(
+        out,
+        "#define CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, strct.ident,
+    );
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -325,7 +334,11 @@ fn write_struct(out: &mut OutFile, strct: &Struct) {
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, &strct.ident);
+    writeln!(
+        out,
+        "#endif // CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, strct.ident,
+    );
 }
 
 fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
@@ -336,31 +349,17 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "using {} = {};", ident, ident);
 }
 
-const INCLUDE_GUARD_PREFIX: &'static str = "CXXBRIDGE03_TYPE_";
-
-fn write_include_guard_start(out: &mut OutFile, ident: &Ident) {
-    writeln!(
-        out,
-        "#ifndef {}{}{}",
-        INCLUDE_GUARD_PREFIX, out.namespace, ident
-    );
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
     writeln!(
         out,
-        "#define {}{}{}",
-        INCLUDE_GUARD_PREFIX, out.namespace, ident
+        "#ifndef CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, ety.ident,
     );
-}
-
-fn write_include_guard_end(out: &mut OutFile, ident: &Ident) {
     writeln!(
         out,
-        "#endif // {}{}{}",
-        INCLUDE_GUARD_PREFIX, out.namespace, ident
+        "#define CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, ety.ident,
     );
-}
-
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    write_include_guard_start(out, &ety.ident);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -375,11 +374,24 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
         writeln!(out, ";");
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, &ety.ident);
+    writeln!(
+        out,
+        "#endif // CXXBRIDGE03_STRUCT_{}{}",
+        out.namespace, ety.ident,
+    );
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    write_include_guard_start(out, &enm.ident);
+    writeln!(
+        out,
+        "#ifndef CXXBRIDGE03_ENUM_{}{}",
+        out.namespace, enm.ident,
+    );
+    writeln!(
+        out,
+        "#define CXXBRIDGE03_ENUM_{}{}",
+        out.namespace, enm.ident,
+    );
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -390,7 +402,11 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
-    write_include_guard_end(out, &enm.ident);
+    writeln!(
+        out,
+        "#endif // CXXBRIDGE03_ENUM_{}{}",
+        out.namespace, enm.ident,
+    );
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {

From a25ea9cc04b7bc8b4d2d5ae894d0eb2d9979660e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 05:59:38 +0000
Subject: [PATCH 704/2232] Write guards in a way that rustfmt formats tighter vertically


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1196837..a9b8dde 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -314,16 +314,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
-    writeln!(
-        out,
-        "#ifndef CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, strct.ident,
-    );
-    writeln!(
-        out,
-        "#define CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, strct.ident,
-    );
+    let guard = format!("CXXBRIDGE03_STRUCT_{}{}", out.namespace, strct.ident);
+    writeln!(out, "#ifndef {}", guard);
+    writeln!(out, "#define {}", guard);
     for line in strct.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -334,11 +327,7 @@ fn write_struct(out: &mut OutFile, strct: &Struct) {
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
-    writeln!(
-        out,
-        "#endif // CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, strct.ident,
-    );
+    writeln!(out, "#endif // {}", guard);
 }
 
 fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
@@ -350,16 +339,9 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    writeln!(
-        out,
-        "#ifndef CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, ety.ident,
-    );
-    writeln!(
-        out,
-        "#define CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, ety.ident,
-    );
+    let guard = format!("CXXBRIDGE03_STRUCT_{}{}", out.namespace, ety.ident);
+    writeln!(out, "#ifndef {}", guard);
+    writeln!(out, "#define {}", guard);
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -374,24 +356,13 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
         writeln!(out, ";");
     }
     writeln!(out, "}};");
-    writeln!(
-        out,
-        "#endif // CXXBRIDGE03_STRUCT_{}{}",
-        out.namespace, ety.ident,
-    );
+    writeln!(out, "#endif // {}", guard);
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    writeln!(
-        out,
-        "#ifndef CXXBRIDGE03_ENUM_{}{}",
-        out.namespace, enm.ident,
-    );
-    writeln!(
-        out,
-        "#define CXXBRIDGE03_ENUM_{}{}",
-        out.namespace, enm.ident,
-    );
+    let guard = format!("CXXBRIDGE03_ENUM_{}{}", out.namespace, enm.ident);
+    writeln!(out, "#ifndef {}", guard);
+    writeln!(out, "#define {}", guard);
     for line in enm.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -402,11 +373,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
     }
     writeln!(out, "}};");
-    writeln!(
-        out,
-        "#endif // CXXBRIDGE03_ENUM_{}{}",
-        out.namespace, enm.ident,
-    );
+    writeln!(out, "#endif // {}", guard);
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {

From 3cb7542aec0ae4522af80c18730309d98d25d5b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 06:41:13 +0000
Subject: [PATCH 705/2232] Fix link where intra-rustdoc link is not kicking in


From looking at the docs.rs pages for 0.3.1 through 0.3.4, it looks like
this link used to render correctly, but doesn't anymore starting with
0.3.5... Unclear whether caused by a rustdoc change or a cxx change.

---

diff --git a/src/lib.rs b/src/lib.rs
index 69e45b3..bbe8788 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -398,6 +398,8 @@ pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
+///
+/// [`ExternType`]: trait.ExternType.html
 pub use cxxbridge_macro::type_id;
 
 // Not public API.

From f2eb3e70572be2f3880a6fd7529a950007ecc7bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 06:51:23 +0000
Subject: [PATCH 706/2232] Add cxx::String and cxx::Vector aliases


---

diff --git a/src/lib.rs b/src/lib.rs
index bbe8788..5210940 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -402,6 +402,20 @@ pub use cxxbridge_macro::bridge;
 /// [`ExternType`]: trait.ExternType.html
 pub use cxxbridge_macro::type_id;
 
+/// Synonym for `CxxString`.
+///
+/// To avoid confusion with Rust's standard library string you probably
+/// shouldn't import this type with `use`. Instead, write `cxx::String`, or
+/// import and use `CxxString`.
+pub type String = CxxString;
+
+/// Synonym for `CxxVector`.
+///
+/// To avoid confusion with Rust's standard library vector you probably
+/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or
+/// import and use `CxxVector`.
+pub type Vector<T> = CxxVector<T>;
+
 // Not public API.
 #[doc(hidden)]
 pub mod private {

From b69cb0a7d99412aac5196674bf5fce03d1a36f0d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 06:57:10 +0000
Subject: [PATCH 707/2232] Merge pull request #265 from dtolnay/alias


Add cxx::String and cxx::Vector aliases
---

diff --git a/src/lib.rs b/src/lib.rs
index bbe8788..5210940 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -402,6 +402,20 @@ pub use cxxbridge_macro::bridge;
 /// [`ExternType`]: trait.ExternType.html
 pub use cxxbridge_macro::type_id;
 
+/// Synonym for `CxxString`.
+///
+/// To avoid confusion with Rust's standard library string you probably
+/// shouldn't import this type with `use`. Instead, write `cxx::String`, or
+/// import and use `CxxString`.
+pub type String = CxxString;
+
+/// Synonym for `CxxVector`.
+///
+/// To avoid confusion with Rust's standard library vector you probably
+/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or
+/// import and use `CxxVector`.
+pub type Vector<T> = CxxVector<T>;
+
 // Not public API.
 #[doc(hidden)]
 pub mod private {

From 33f56ad8d5e536d3a42f3f2afa74d341d7b0255d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 07:25:41 +0000
Subject: [PATCH 708/2232] Implement Vec<String>


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ab1206c..0869c2c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -260,6 +260,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                     None => quote!(::cxx::private::RustString::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
+                    Some(_) => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => quote!(::cxx::private::RustVec::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
@@ -332,13 +336,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
-            Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(#call.map(|r| r.into_vec_string())))
+                } else {
+                    Some(quote!(#call.map(|r| r.into_vec())))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_string()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_vec_string()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_vec()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
@@ -353,13 +367,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
-            Type::RustVec(_) => Some(quote!(#call.into_vec())),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(#call.into_vec_string()))
+                } else {
+                    Some(quote!(#call.into_vec()))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(#call.as_string())),
                     Some(_) => Some(quote!(#call.as_mut_string())),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(#call.as_vec_string())),
+                    Some(_) => Some(quote!(#call.as_mut_vec_string())),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(#call.as_vec())),
                     Some(_) => Some(quote!(#call.as_mut_vec())),
@@ -508,13 +532,23 @@ fn expand_rust_function_shim_impl(
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
-            Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    quote!(::std::mem::take((*#ident).as_mut_vec_string()))
+                } else {
+                    quote!(::std::mem::take((*#ident).as_mut_vec()))
+                }
+            }
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
                     Some(_) => quote!(#ident.as_mut_string()),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => quote!(#ident.as_vec_string()),
+                    Some(_) => quote!(#ident.as_mut_vec_string()),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => quote!(#ident.as_vec()),
                     Some(_) => quote!(#ident.as_mut_vec()),
@@ -549,13 +583,23 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustString::from(#call)))
             }
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
-            Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
+                } else {
+                    Some(quote!(::cxx::private::RustVec::from(#call)))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
                     Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
                     Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
diff --git a/src/cxx.cc b/src/cxx.cc
index b953904..e00fd6a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -280,7 +280,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
 
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
-  MACRO(bool, bool)
+  MACRO(bool, bool)                                                            \
+  MACRO(string, rust::String)
 
 extern "C" {
 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 9ff4bbf..5e7082a 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,3 +1,6 @@
+use crate::rust_string::RustString;
+use std::mem::ManuallyDrop;
+
 #[repr(C)]
 pub struct RustVec<T> {
     repr: Vec<T>,
@@ -40,3 +43,37 @@ impl<T> RustVec<T> {
         self.repr.as_ptr()
     }
 }
+
+impl RustVec<RustString> {
+    pub fn from_vec_string(v: Vec<String>) -> Self {
+        let mut v = ManuallyDrop::new(v);
+        let ptr = v.as_mut_ptr().cast::<RustString>();
+        let len = v.len();
+        let cap = v.capacity();
+        Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) })
+    }
+
+    pub fn from_ref_vec_string(v: &Vec<String>) -> &Self {
+        Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) })
+    }
+
+    pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self {
+        Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) })
+    }
+
+    pub fn into_vec_string(self) -> Vec<String> {
+        let mut v = ManuallyDrop::new(self.repr);
+        let ptr = v.as_mut_ptr().cast::<String>();
+        let len = v.len();
+        let cap = v.capacity();
+        unsafe { Vec::from_raw_parts(ptr, len, cap) }
+    }
+
+    pub fn as_vec_string(&self) -> &Vec<String> {
+        unsafe { &*(&self.repr as *const Vec<RustString> as *const Vec<String>) }
+    }
+
+    pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> {
+        unsafe { &mut *(&mut self.repr as *mut Vec<RustString> as *mut Vec<String>) }
+    }
+}
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 63d4ba7..d8e0f4a 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -3,6 +3,11 @@ use std::ptr;
 use std::slice;
 use std::str;
 
+#[repr(C)]
+pub(crate) struct RustString {
+    repr: String,
+}
+
 #[export_name = "cxxbridge03$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 9ce87ab..5465471 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,8 +1,9 @@
+use super::rust_string::RustString;
 use std::mem;
 use std::ptr;
 
 #[repr(C)]
-pub struct RustVec<T> {
+pub(crate) struct RustVec<T> {
     repr: Vec<T>,
 }
 
@@ -13,38 +14,38 @@ macro_rules! attr {
     };
 }
 
-macro_rules! rust_vec_shims_for_primitive {
-    ($ty:ident) => {
+macro_rules! rust_vec_shims {
+    ($segment:expr, $ty:ty) => {
         const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
         const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec { repr: Vec::new() });
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).repr.len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
@@ -53,6 +54,12 @@ macro_rules! rust_vec_shims_for_primitive {
     };
 }
 
+macro_rules! rust_vec_shims_for_primitive {
+    ($ty:ident) => {
+        rust_vec_shims!(stringify!($ty), $ty);
+    };
+}
+
 rust_vec_shims_for_primitive!(bool);
 rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
@@ -64,3 +71,5 @@ rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
+
+rust_vec_shims!("string", RustString);
diff --git a/syntax/check.rs b/syntax/check.rs
index c54430c..71fab3b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -92,8 +92,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
 
         match Atom::from(ident) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
-            Some(Bool) | Some(RustString) => { /* todo */ }
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(RustString) => return,
+            Some(Bool) => { /* todo */ }
             Some(CxxString) => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d69163a..cb688f3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -46,6 +46,7 @@ pub mod ffi {
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
+        fn c_return_rust_vec_string() -> Vec<String>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
@@ -65,10 +66,12 @@ pub mod ffi {
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
         fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_rust_vec_string(v: Vec<String>);
         fn c_take_rust_vec_index(v: Vec<u8>);
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
+        fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         /*
@@ -87,6 +90,7 @@ pub mod ffi {
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
+        fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
         fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
@@ -121,6 +125,7 @@ pub mod ffi {
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
+        fn r_return_rust_vec_string() -> Vec<String>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
@@ -138,7 +143,9 @@ pub mod ffi {
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_rust_vec(v: Vec<u8>);
+        fn r_take_rust_vec_string(v: Vec<String>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
+        fn r_take_ref_rust_vec_string(v: &Vec<String>);
         fn r_take_enum(e: Enum);
 
         fn r_try_return_void() -> Result<()>;
@@ -224,6 +231,10 @@ fn r_return_rust_vec() -> Vec<u8> {
     Vec::new()
 }
 
+fn r_return_rust_vec_string() -> Vec<String> {
+    Vec::new()
+}
+
 fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     let _ = shared;
     unimplemented!()
@@ -297,10 +308,18 @@ fn r_take_rust_vec(v: Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_rust_vec_string(v: Vec<String>) {
+    let _ = v;
+}
+
 fn r_take_ref_rust_vec(v: &Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_ref_rust_vec_string(v: &Vec<String>) {
+    let _ = v;
+}
+
 fn r_take_enum(e: ffi::Enum) {
     let _ = e;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b213930..b45e8ae 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -119,6 +119,10 @@ rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<rust::String> c_return_rust_vec_string() {
+  throw std::runtime_error("unimplemented");
+}
+
 size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
@@ -241,6 +245,11 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_string(rust::Vec<rust::String> v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   // Exercise requirements of ForwardIterator
   // https://en.cppreference.com/w/cpp/named_req/ForwardIterator
@@ -267,6 +276,11 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   }
 }
 
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
   if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
       v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
@@ -323,6 +337,10 @@ rust::Vec<uint8_t> c_try_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<rust::String> c_try_return_rust_vec_string() {
+  throw std::runtime_error("unimplemented");
+}
+
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
   (void)c;
   throw std::runtime_error("unimplemented");
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fe644eb..0efbd62 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -50,6 +50,7 @@ std::vector<uint8_t> &c_return_mut_vector(C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c);
+rust::Vec<rust::String> c_return_rust_vec_string();
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
@@ -71,9 +72,11 @@ void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
 void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 /*
@@ -92,6 +95,7 @@ rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();
+rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
 } // namespace tests

From 13e4d3988cc681cbf06a582399946b37b9de882b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 07:33:13 +0000
Subject: [PATCH 709/2232] Merge pull request #266 from dtolnay/vec


Implement Vec<String>
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ab1206c..0869c2c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -260,6 +260,10 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                     None => quote!(::cxx::private::RustString::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
+                    Some(_) => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => quote!(::cxx::private::RustVec::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
@@ -332,13 +336,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
-            Type::RustVec(_) => Some(quote!(#call.map(|r| r.into_vec()))),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(#call.map(|r| r.into_vec_string())))
+                } else {
+                    Some(quote!(#call.map(|r| r.into_vec())))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_string()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(#call.map(|r| r.as_vec_string()))),
+                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_vec()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
@@ -353,13 +367,23 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         efn.ret.as_ref().and_then(|ret| match ret {
             Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
-            Type::RustVec(_) => Some(quote!(#call.into_vec())),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(#call.into_vec_string()))
+                } else {
+                    Some(quote!(#call.into_vec()))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(#call.as_string())),
                     Some(_) => Some(quote!(#call.as_mut_string())),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(#call.as_vec_string())),
+                    Some(_) => Some(quote!(#call.as_mut_vec_string())),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(#call.as_vec())),
                     Some(_) => Some(quote!(#call.as_mut_vec())),
@@ -508,13 +532,23 @@ fn expand_rust_function_shim_impl(
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
-            Type::RustVec(_) => quote!(::std::mem::take((*#ident).as_mut_vec())),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    quote!(::std::mem::take((*#ident).as_mut_vec_string()))
+                } else {
+                    quote!(::std::mem::take((*#ident).as_mut_vec()))
+                }
+            }
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
                     Some(_) => quote!(#ident.as_mut_string()),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => quote!(#ident.as_vec_string()),
+                    Some(_) => quote!(#ident.as_mut_vec_string()),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => quote!(#ident.as_vec()),
                     Some(_) => quote!(#ident.as_mut_vec()),
@@ -549,13 +583,23 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustString::from(#call)))
             }
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
-            Type::RustVec(_) => Some(quote!(::cxx::private::RustVec::from(#call))),
+            Type::RustVec(vec) => {
+                if vec.inner == RustString {
+                    Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
+                } else {
+                    Some(quote!(::cxx::private::RustVec::from(#call)))
+                }
+            }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident == RustString => match ty.mutability {
                     None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
                     Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
                 },
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                    None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
+                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
+                },
                 Type::RustVec(_) => match ty.mutability {
                     None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
                     Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
diff --git a/src/cxx.cc b/src/cxx.cc
index b953904..e00fd6a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -280,7 +280,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
 
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
-  MACRO(bool, bool)
+  MACRO(bool, bool)                                                            \
+  MACRO(string, rust::String)
 
 extern "C" {
 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 9ff4bbf..5e7082a 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,3 +1,6 @@
+use crate::rust_string::RustString;
+use std::mem::ManuallyDrop;
+
 #[repr(C)]
 pub struct RustVec<T> {
     repr: Vec<T>,
@@ -40,3 +43,37 @@ impl<T> RustVec<T> {
         self.repr.as_ptr()
     }
 }
+
+impl RustVec<RustString> {
+    pub fn from_vec_string(v: Vec<String>) -> Self {
+        let mut v = ManuallyDrop::new(v);
+        let ptr = v.as_mut_ptr().cast::<RustString>();
+        let len = v.len();
+        let cap = v.capacity();
+        Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) })
+    }
+
+    pub fn from_ref_vec_string(v: &Vec<String>) -> &Self {
+        Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) })
+    }
+
+    pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self {
+        Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) })
+    }
+
+    pub fn into_vec_string(self) -> Vec<String> {
+        let mut v = ManuallyDrop::new(self.repr);
+        let ptr = v.as_mut_ptr().cast::<String>();
+        let len = v.len();
+        let cap = v.capacity();
+        unsafe { Vec::from_raw_parts(ptr, len, cap) }
+    }
+
+    pub fn as_vec_string(&self) -> &Vec<String> {
+        unsafe { &*(&self.repr as *const Vec<RustString> as *const Vec<String>) }
+    }
+
+    pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> {
+        unsafe { &mut *(&mut self.repr as *mut Vec<RustString> as *mut Vec<String>) }
+    }
+}
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 63d4ba7..d8e0f4a 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -3,6 +3,11 @@ use std::ptr;
 use std::slice;
 use std::str;
 
+#[repr(C)]
+pub(crate) struct RustString {
+    repr: String,
+}
+
 #[export_name = "cxxbridge03$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 9ce87ab..5465471 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,8 +1,9 @@
+use super::rust_string::RustString;
 use std::mem;
 use std::ptr;
 
 #[repr(C)]
-pub struct RustVec<T> {
+pub(crate) struct RustVec<T> {
     repr: Vec<T>,
 }
 
@@ -13,38 +14,38 @@ macro_rules! attr {
     };
 }
 
-macro_rules! rust_vec_shims_for_primitive {
-    ($ty:ident) => {
+macro_rules! rust_vec_shims {
+    ($segment:expr, $ty:ty) => {
         const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
         const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$new")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec { repr: Vec::new() });
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$drop")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$len")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).repr.len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$data")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", stringify!($ty), "$stride")]
+                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
@@ -53,6 +54,12 @@ macro_rules! rust_vec_shims_for_primitive {
     };
 }
 
+macro_rules! rust_vec_shims_for_primitive {
+    ($ty:ident) => {
+        rust_vec_shims!(stringify!($ty), $ty);
+    };
+}
+
 rust_vec_shims_for_primitive!(bool);
 rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
@@ -64,3 +71,5 @@ rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
+
+rust_vec_shims!("string", RustString);
diff --git a/syntax/check.rs b/syntax/check.rs
index c54430c..71fab3b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -92,8 +92,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
 
         match Atom::from(ident) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
-            Some(Bool) | Some(RustString) => { /* todo */ }
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(RustString) => return,
+            Some(Bool) => { /* todo */ }
             Some(CxxString) => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d69163a..cb688f3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -46,6 +46,7 @@ pub mod ffi {
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
         fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
+        fn c_return_rust_vec_string() -> Vec<String>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
@@ -65,10 +66,12 @@ pub mod ffi {
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
         fn c_take_rust_vec_shared(v: Vec<Shared>);
+        fn c_take_rust_vec_string(v: Vec<String>);
         fn c_take_rust_vec_index(v: Vec<u8>);
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
+        fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
         /*
@@ -87,6 +90,7 @@ pub mod ffi {
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
+        fn c_try_return_rust_vec_string() -> Result<Vec<String>>;
         fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
@@ -121,6 +125,7 @@ pub mod ffi {
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
+        fn r_return_rust_vec_string() -> Vec<String>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
@@ -138,7 +143,9 @@ pub mod ffi {
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_rust_vec(v: Vec<u8>);
+        fn r_take_rust_vec_string(v: Vec<String>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
+        fn r_take_ref_rust_vec_string(v: &Vec<String>);
         fn r_take_enum(e: Enum);
 
         fn r_try_return_void() -> Result<()>;
@@ -224,6 +231,10 @@ fn r_return_rust_vec() -> Vec<u8> {
     Vec::new()
 }
 
+fn r_return_rust_vec_string() -> Vec<String> {
+    Vec::new()
+}
+
 fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     let _ = shared;
     unimplemented!()
@@ -297,10 +308,18 @@ fn r_take_rust_vec(v: Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_rust_vec_string(v: Vec<String>) {
+    let _ = v;
+}
+
 fn r_take_ref_rust_vec(v: &Vec<u8>) {
     let _ = v;
 }
 
+fn r_take_ref_rust_vec_string(v: &Vec<String>) {
+    let _ = v;
+}
+
 fn r_take_enum(e: ffi::Enum) {
     let _ = e;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b213930..b45e8ae 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -119,6 +119,10 @@ rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<rust::String> c_return_rust_vec_string() {
+  throw std::runtime_error("unimplemented");
+}
+
 size_t c_return_identity(size_t n) { return n; }
 
 size_t c_return_sum(size_t n1, size_t n2) { return n1 + n2; }
@@ -241,6 +245,11 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_string(rust::Vec<rust::String> v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   // Exercise requirements of ForwardIterator
   // https://en.cppreference.com/w/cpp/named_req/ForwardIterator
@@ -267,6 +276,11 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   }
 }
 
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v) {
   if (v[0] == 86 && v.at(0) == 86 && v.front() == 86 && v[1] == 75 &&
       v.at(1) == 75 && v[3] == 9 && v.at(3) == 9 && v.back() == 9) {
@@ -323,6 +337,10 @@ rust::Vec<uint8_t> c_try_return_rust_vec() {
   throw std::runtime_error("unimplemented");
 }
 
+rust::Vec<rust::String> c_try_return_rust_vec_string() {
+  throw std::runtime_error("unimplemented");
+}
+
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
   (void)c;
   throw std::runtime_error("unimplemented");
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fe644eb..0efbd62 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -50,6 +50,7 @@ std::vector<uint8_t> &c_return_mut_vector(C &c);
 rust::Vec<uint8_t> c_return_rust_vec();
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c);
 rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c);
+rust::Vec<rust::String> c_return_rust_vec_string();
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
@@ -71,9 +72,11 @@ void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
 void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
+void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 /*
@@ -92,6 +95,7 @@ rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();
+rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
 } // namespace tests

From 47e239df1107c4cf9be1a7b522ae8820bbc10997 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 07:43:10 +0000
Subject: [PATCH 710/2232] Implement CxxVector<CxxString>


---

diff --git a/src/cxx.cc b/src/cxx.cc
index e00fd6a..2114598 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -276,7 +276,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
 #define FOR_EACH_STD_VECTOR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(usize, size_t)                                                         \
-  MACRO(isize, rust::isize)
+  MACRO(isize, rust::isize)                                                    \
+  MACRO(string, std::string)
 
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index bfb4a4e..10853a6 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
 use std::ffi::c_void;
 use std::fmt::{self, Display};
 use std::marker::PhantomData;
@@ -129,16 +130,16 @@ pub unsafe trait VectorElement: Sized {
     unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
-macro_rules! impl_vector_element_for_primitive {
-    ($ty:ident) => {
+macro_rules! impl_vector_element {
+    ($segment:expr, $name:expr, $ty:ty) => {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
-            const __NAME: &'static dyn Display = &stringify!($ty);
+            const __NAME: &'static dyn Display = &$name;
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$size")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -147,7 +148,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -156,7 +157,7 @@ macro_rules! impl_vector_element_for_primitive {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -167,7 +168,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -178,7 +179,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -187,7 +188,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -196,7 +197,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
@@ -206,6 +207,12 @@ macro_rules! impl_vector_element_for_primitive {
     };
 }
 
+macro_rules! impl_vector_element_for_primitive {
+    ($ty:ident) => {
+        impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
 impl_vector_element_for_primitive!(u8);
 impl_vector_element_for_primitive!(u16);
 impl_vector_element_for_primitive!(u32);
@@ -218,3 +225,5 @@ impl_vector_element_for_primitive!(i64);
 impl_vector_element_for_primitive!(isize);
 impl_vector_element_for_primitive!(f32);
 impl_vector_element_for_primitive!(f64);
+
+impl_vector_element!("string", "CxxString", CxxString);
diff --git a/syntax/check.rs b/syntax/check.rs
index 71fab3b..4fbc6e2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -130,8 +130,8 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
 
         match Atom::from(ident) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
-            Some(CxxString) => { /* todo */ }
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(CxxString) => return,
             Some(Bool) | Some(RustString) => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cb688f3..8aaac75 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -39,6 +39,7 @@ pub mod ffi {
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
         fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
+        fn c_return_unique_ptr_vector_string() -> UniquePtr<CxxVector<CxxString>>;
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
@@ -62,6 +63,7 @@ pub mod ffi {
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
         fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_string(v: UniquePtr<CxxVector<CxxString>>);
         fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b45e8ae..d45d5d5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -88,6 +88,11 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
   return vec;
 }
 
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string() {
+  return std::unique_ptr<std::vector<std::string>>(
+      new std::vector<std::string>());
+}
+
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
   auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
   vec->push_back(Shared{1010});
@@ -210,6 +215,12 @@ void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
   }
 }
 
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   if (v->size() == 2) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0efbd62..f3bc2dd 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -43,6 +43,7 @@ rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
@@ -67,6 +68,8 @@ void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);

From ee07f011a293ba42f876825ced6a379ca89b97bc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 07:48:02 +0000
Subject: [PATCH 711/2232] Merge pull request #267 from dtolnay/vec


Implement CxxVector<CxxString>
---

diff --git a/src/cxx.cc b/src/cxx.cc
index e00fd6a..2114598 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -276,7 +276,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
 #define FOR_EACH_STD_VECTOR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(usize, size_t)                                                         \
-  MACRO(isize, rust::isize)
+  MACRO(isize, rust::isize)                                                    \
+  MACRO(string, std::string)
 
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index bfb4a4e..10853a6 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
 use std::ffi::c_void;
 use std::fmt::{self, Display};
 use std::marker::PhantomData;
@@ -129,16 +130,16 @@ pub unsafe trait VectorElement: Sized {
     unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
-macro_rules! impl_vector_element_for_primitive {
-    ($ty:ident) => {
+macro_rules! impl_vector_element {
+    ($segment:expr, $name:expr, $ty:ty) => {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
-            const __NAME: &'static dyn Display = &stringify!($ty);
+            const __NAME: &'static dyn Display = &$name;
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$size")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -147,7 +148,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -156,7 +157,7 @@ macro_rules! impl_vector_element_for_primitive {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -167,7 +168,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -178,7 +179,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -187,7 +188,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -196,7 +197,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
@@ -206,6 +207,12 @@ macro_rules! impl_vector_element_for_primitive {
     };
 }
 
+macro_rules! impl_vector_element_for_primitive {
+    ($ty:ident) => {
+        impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
 impl_vector_element_for_primitive!(u8);
 impl_vector_element_for_primitive!(u16);
 impl_vector_element_for_primitive!(u32);
@@ -218,3 +225,5 @@ impl_vector_element_for_primitive!(i64);
 impl_vector_element_for_primitive!(isize);
 impl_vector_element_for_primitive!(f32);
 impl_vector_element_for_primitive!(f64);
+
+impl_vector_element!("string", "CxxString", CxxString);
diff --git a/syntax/check.rs b/syntax/check.rs
index 71fab3b..4fbc6e2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -130,8 +130,8 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
 
         match Atom::from(ident) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
-            Some(CxxString) => { /* todo */ }
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(CxxString) => return,
             Some(Bool) | Some(RustString) => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cb688f3..8aaac75 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -39,6 +39,7 @@ pub mod ffi {
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
         fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
+        fn c_return_unique_ptr_vector_string() -> UniquePtr<CxxVector<CxxString>>;
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
@@ -62,6 +63,7 @@ pub mod ffi {
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
         fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_string(v: UniquePtr<CxxVector<CxxString>>);
         fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b45e8ae..d45d5d5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -88,6 +88,11 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
   return vec;
 }
 
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string() {
+  return std::unique_ptr<std::vector<std::string>>(
+      new std::vector<std::string>());
+}
+
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
   auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
   vec->push_back(Shared{1010});
@@ -210,6 +215,12 @@ void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
   }
 }
 
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   if (v->size() == 2) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0efbd62..f3bc2dd 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -43,6 +43,7 @@ rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
@@ -67,6 +68,8 @@ void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);

From 907debe8b471d75afa0aeaab79335470d6759e8e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 28 2020 23:56:19 +0000
Subject: [PATCH 712/2232] Release 0.3.6


---

diff --git a/Cargo.toml b/Cargo.toml
index 1c59ccb..a9db039 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.5" # remember to update html_root_url
+version = "0.3.6" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -19,14 +19,14 @@ default = [] # c++11
 "c++17" = []
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.5", path = "macro" }
+cxxbridge-macro = { version = "=0.3.6", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.5", path = "gen/build" }
+cxx-build = { version = "=0.3.6", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b242383..c59382e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.5"
+version = "0.3.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index c0cfeb4..03fb4cf 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.5"
+version = "0.3.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1b85847..2cc2a72 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.5"
+version = "0.3.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 5210940..ad195cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.5")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.6")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index aea33a4..2a37462 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.5"
+version = "0.3.6"
 dependencies = [
  "cc",
  "cxx-build",
@@ -78,7 +78,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.5"
+version = "0.3.6"
 dependencies = [
  "anyhow",
  "cc",
@@ -98,7 +98,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.5"
+version = "0.3.6"
 dependencies = [
  "anyhow",
  "clap",
@@ -118,7 +118,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.5"
+version = "0.3.6"
 dependencies = [
  "cxx",
  "proc-macro2",

From de1cb777b2e4fb3f7b1255500baf7c09d2ef7a3e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 00:36:33 +0000
Subject: [PATCH 713/2232] Specify consistent c++ standard between cxx and cxx-test-suite


---

diff --git a/Cargo.toml b/Cargo.toml
index a9db039..5f20ad9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,9 +14,10 @@ keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
 [features]
-default = [] # c++11
-"c++14" = []
-"c++17" = []
+default = ["cxxbridge-flags/default"] # c++11
+"c++14" = ["cxxbridge-flags/c++14"]
+"c++17" = ["cxxbridge-flags/c++17"]
+"c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
 cxxbridge-macro = { version = "=0.3.6", path = "macro" }
@@ -24,6 +25,7 @@ link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
+cxxbridge-flags = { version = "=0.3.6", path = "flags", default-features = false }
 
 [dev-dependencies]
 cxx-build = { version = "=0.3.6", path = "gen/build" }
@@ -32,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
+members = ["demo-rs", "flags", "gen/build", "gen/cmd", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/build.rs b/build.rs
index a412dbd..2aad99f 100644
--- a/build.rs
+++ b/build.rs
@@ -3,13 +3,7 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag_if_supported(if cfg!(feature = "c++17") {
-            "-std=c++17"
-        } else if cfg!(feature = "c++14") {
-            "-std=c++14"
-        } else {
-            "-std=c++11"
-        })
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
new file mode 100644
index 0000000..6e5bc5d
--- /dev/null
+++ b/flags/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "cxxbridge-flags"
+version = "0.3.6"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "Compiler configuration of the `cxx` crate (implementation detail)"
+repository = "https://github.com/dtolnay/cxx"
+
+[features]
+default = [] # c++11
+"c++14" = []
+"c++17" = []
+"c++20" = []
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/flags/src/impl.rs b/flags/src/impl.rs
new file mode 100644
index 0000000..4f7b8fb
--- /dev/null
+++ b/flags/src/impl.rs
@@ -0,0 +1,20 @@
+#[allow(unused_assignments, unused_mut, unused_variables)]
+pub const STD: &str = {
+    let mut flags = ["-std=c++11", "/std:c++11"];
+
+    #[cfg(feature = "c++14")]
+    (flags = ["-std=c++14", "/std:c++14"]);
+
+    #[cfg(feature = "c++17")]
+    (flags = ["-std=c++17", "/std:c++17"]);
+
+    #[cfg(feature = "c++20")]
+    (flags = ["-std=c++20", "/std:c++20"]);
+
+    let [mut flag, msvc_flag] = flags;
+
+    #[cfg(target_env = "msvc")]
+    (flag = msvc_flag);
+
+    flag
+};
diff --git a/flags/src/lib.rs b/flags/src/lib.rs
new file mode 100644
index 0000000..55172b2
--- /dev/null
+++ b/flags/src/lib.rs
@@ -0,0 +1,7 @@
+//! This crate is an implementation detail of the `cxx` and `cxx-build` crates,
+//! and does not expose any public API.
+
+mod r#impl;
+
+#[doc(hidden)]
+pub use r#impl::*;
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
index c2d8227..e62d090 100644
--- a/tests/ffi/Cargo.toml
+++ b/tests/ffi/Cargo.toml
@@ -12,3 +12,4 @@ cxx = { path = "../.." }
 
 [build-dependencies]
 cxx-build = { path = "../../gen/build" }
+cxxbridge-flags = { path = "../../flags" }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index f6fa59e..8042129 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,6 +6,6 @@ fn main() {
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxx-test-suite");
 }
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2a37462..65ec211 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -70,6 +70,7 @@ dependencies = [
  "cc",
  "cxx-build",
  "cxx-test-suite",
+ "cxxbridge-flags",
  "cxxbridge-macro",
  "link-cplusplus",
  "rustversion",
@@ -94,6 +95,7 @@ version = "0.0.0"
 dependencies = [
  "cxx",
  "cxx-build",
+ "cxxbridge-flags",
 ]
 
 [[package]]
@@ -117,6 +119,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxxbridge-flags"
+version = "0.3.6"
+
+[[package]]
 name = "cxxbridge-macro"
 version = "0.3.6"
 dependencies = [

From 0f312e7a7b8721d47f2c2791a706df8395535fd5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 00:40:58 +0000
Subject: [PATCH 714/2232] Merge pull request #268 from dtolnay/flags


Specify consistent c++ standard between cxx and cxx-test-suite
---

diff --git a/Cargo.toml b/Cargo.toml
index a9db039..5f20ad9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,9 +14,10 @@ keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
 [features]
-default = [] # c++11
-"c++14" = []
-"c++17" = []
+default = ["cxxbridge-flags/default"] # c++11
+"c++14" = ["cxxbridge-flags/c++14"]
+"c++17" = ["cxxbridge-flags/c++17"]
+"c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
 cxxbridge-macro = { version = "=0.3.6", path = "macro" }
@@ -24,6 +25,7 @@ link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
+cxxbridge-flags = { version = "=0.3.6", path = "flags", default-features = false }
 
 [dev-dependencies]
 cxx-build = { version = "=0.3.6", path = "gen/build" }
@@ -32,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "gen/build", "gen/cmd", "macro", "tests/ffi"]
+members = ["demo-rs", "flags", "gen/build", "gen/cmd", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/build.rs b/build.rs
index a412dbd..2aad99f 100644
--- a/build.rs
+++ b/build.rs
@@ -3,13 +3,7 @@ fn main() {
         .file("src/cxx.cc")
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
-        .flag_if_supported(if cfg!(feature = "c++17") {
-            "-std=c++17"
-        } else if cfg!(feature = "c++14") {
-            "-std=c++14"
-        } else {
-            "-std=c++11"
-        })
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
new file mode 100644
index 0000000..6e5bc5d
--- /dev/null
+++ b/flags/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "cxxbridge-flags"
+version = "0.3.6"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "Compiler configuration of the `cxx` crate (implementation detail)"
+repository = "https://github.com/dtolnay/cxx"
+
+[features]
+default = [] # c++11
+"c++14" = []
+"c++17" = []
+"c++20" = []
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/flags/src/impl.rs b/flags/src/impl.rs
new file mode 100644
index 0000000..4f7b8fb
--- /dev/null
+++ b/flags/src/impl.rs
@@ -0,0 +1,20 @@
+#[allow(unused_assignments, unused_mut, unused_variables)]
+pub const STD: &str = {
+    let mut flags = ["-std=c++11", "/std:c++11"];
+
+    #[cfg(feature = "c++14")]
+    (flags = ["-std=c++14", "/std:c++14"]);
+
+    #[cfg(feature = "c++17")]
+    (flags = ["-std=c++17", "/std:c++17"]);
+
+    #[cfg(feature = "c++20")]
+    (flags = ["-std=c++20", "/std:c++20"]);
+
+    let [mut flag, msvc_flag] = flags;
+
+    #[cfg(target_env = "msvc")]
+    (flag = msvc_flag);
+
+    flag
+};
diff --git a/flags/src/lib.rs b/flags/src/lib.rs
new file mode 100644
index 0000000..55172b2
--- /dev/null
+++ b/flags/src/lib.rs
@@ -0,0 +1,7 @@
+//! This crate is an implementation detail of the `cxx` and `cxx-build` crates,
+//! and does not expose any public API.
+
+mod r#impl;
+
+#[doc(hidden)]
+pub use r#impl::*;
diff --git a/tests/ffi/Cargo.toml b/tests/ffi/Cargo.toml
index c2d8227..e62d090 100644
--- a/tests/ffi/Cargo.toml
+++ b/tests/ffi/Cargo.toml
@@ -12,3 +12,4 @@ cxx = { path = "../.." }
 
 [build-dependencies]
 cxx-build = { path = "../../gen/build" }
+cxxbridge-flags = { path = "../../flags" }
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index f6fa59e..8042129 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,6 +6,6 @@ fn main() {
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
-        .flag_if_supported("-std=c++11")
+        .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxx-test-suite");
 }
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2a37462..65ec211 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -70,6 +70,7 @@ dependencies = [
  "cc",
  "cxx-build",
  "cxx-test-suite",
+ "cxxbridge-flags",
  "cxxbridge-macro",
  "link-cplusplus",
  "rustversion",
@@ -94,6 +95,7 @@ version = "0.0.0"
 dependencies = [
  "cxx",
  "cxx-build",
+ "cxxbridge-flags",
 ]
 
 [[package]]
@@ -117,6 +119,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxxbridge-flags"
+version = "0.3.6"
+
+[[package]]
 name = "cxxbridge-macro"
 version = "0.3.6"
 dependencies = [

From dab7e80a818491b5652052f96cd46c013c7ac28d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 01:54:53 +0000
Subject: [PATCH 715/2232] Preserve utf-8 invariant on generated code


We only write to the output buffer using the `write!` macros, which go
through std::fmt and are guaranteed that the data written is utf-8.

---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index c21ad78..dbb1d73 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -12,7 +12,7 @@ pub(crate) struct OutFile {
 }
 
 pub struct Content {
-    bytes: Vec<u8>,
+    bytes: String,
     section_pending: bool,
     blocks_pending: Vec<&'static str>,
 }
@@ -42,9 +42,9 @@ impl OutFile {
     pub fn end_block(&mut self, block: &'static str) {
         let content = self.content.get_mut();
         if content.blocks_pending.pop().is_none() {
-            content.bytes.extend_from_slice(b"} // ");
-            content.bytes.extend_from_slice(block.as_bytes());
-            content.bytes.push(b'\n');
+            content.bytes.push_str("} // ");
+            content.bytes.push_str(block);
+            content.bytes.push('\n');
             content.section_pending = true;
         }
     }
@@ -58,19 +58,19 @@ impl OutFile {
         let front = &self.front.bytes;
         let content = &self.content.borrow().bytes;
         let len = front.len() + !front.is_empty() as usize + content.len();
-        let mut out = Vec::with_capacity(len);
-        out.extend_from_slice(front);
+        let mut out = String::with_capacity(len);
+        out.push_str(front);
         if !front.is_empty() {
-            out.push(b'\n');
+            out.push('\n');
         }
-        out.extend_from_slice(content);
-        out
+        out.push_str(content);
+        out.into_bytes()
     }
 }
 
 impl Write for Content {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        self.write_bytes(s.as_bytes());
+        self.write(s);
         Ok(())
     }
 }
@@ -82,30 +82,30 @@ impl Content {
 
     fn new() -> Self {
         Content {
-            bytes: Vec::new(),
+            bytes: String::new(),
             section_pending: false,
             blocks_pending: Vec::new(),
         }
     }
 
-    fn write_bytes(&mut self, b: &[u8]) {
+    fn write(&mut self, b: &str) {
         if !b.is_empty() {
             if !self.blocks_pending.is_empty() {
                 if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
+                    self.bytes.push('\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    self.bytes.extend_from_slice(block.as_bytes());
-                    self.bytes.extend_from_slice(b" {\n");
+                    self.bytes.push_str(block);
+                    self.bytes.push_str(" {\n");
                 }
                 self.section_pending = false;
             } else if self.section_pending {
                 if !self.bytes.is_empty() {
-                    self.bytes.push(b'\n');
+                    self.bytes.push('\n');
                 }
                 self.section_pending = false;
             }
-            self.bytes.extend_from_slice(b);
+            self.bytes.push_str(b);
         }
     }
 }

From 020c923e6ba251837e25b70d0e64982a11cfd526 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 18:34:00 +0000
Subject: [PATCH 716/2232] Less brittle matching of cxx::bridge path


---

diff --git a/gen/src/find.rs b/gen/src/find.rs
index 86e1dc7..d897deb 100644
--- a/gen/src/find.rs
+++ b/gen/src/find.rs
@@ -1,6 +1,5 @@
 use crate::gen::{Error, Input, Result};
 use crate::syntax::namespace::Namespace;
-use quote::quote;
 use syn::{Attribute, File, Item};
 
 pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
@@ -14,8 +13,8 @@ fn scan(items: Vec<Item>) -> Result<Option<Input>> {
     for item in items {
         if let Item::Mod(item) = item {
             for attr in &item.attrs {
-                let path = &attr.path;
-                if quote!(#path).to_string() == "cxx :: bridge" {
+                let path = &attr.path.segments;
+                if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
                     let module = match item.content {
                         Some(module) => module.1,
                         None => {

From 5e668bce9b712aa2246a1a8918c2ee4145c2c410 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 18:36:22 +0000
Subject: [PATCH 717/2232] Format ui test files using rustfmt


---

diff --git a/tests/ui/empty_enum.rs b/tests/ui/empty_enum.rs
index a9ad533..987004b 100644
--- a/tests/ui/empty_enum.rs
+++ b/tests/ui/empty_enum.rs
@@ -1,8 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    enum A {
-
-    }
+    enum A {}
 }
 
 fn main() {}
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
index c73578a..7f35019 100644
--- a/tests/ui/empty_enum.stderr
+++ b/tests/ui/empty_enum.stderr
@@ -1,7 +1,5 @@
 error: enums without any variants are not supported
  --> $DIR/empty_enum.rs:3:5
   |
-3 | /     enum A {
-4 | |
-5 | |     }
-  | |_____^
+3 |     enum A {}
+  |     ^^^^^^^^^
diff --git a/tests/ui/multiple_parse_error.rs b/tests/ui/multiple_parse_error.rs
index 061eab6..138d6d6 100644
--- a/tests/ui/multiple_parse_error.rs
+++ b/tests/ui/multiple_parse_error.rs
@@ -2,8 +2,7 @@
 mod ffi {
     struct Monad<T>;
 
-    extern "Haskell" {
-    }
+    extern "Haskell" {}
 }
 
 fn main() {}
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 854aa90..4189507 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -7,5 +7,5 @@ error: struct with generic parameters is not supported yet
 error: unrecognized ABI
  --> $DIR/multiple_parse_error.rs:5:5
   |
-5 |     extern "Haskell" {
+5 |     extern "Haskell" {}
   |     ^^^^^^^^^^^^^^^^

From 05ef6ffa28719132df8967edc80ba45907166318 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 18:55:04 +0000
Subject: [PATCH 718/2232] Data structure to represent possibly unsafe module


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 0869c2c..48ef6a3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,21 +1,20 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
 };
-use proc_macro2::{Ident, Span, TokenStream};
+use proc_macro2::{Ident, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, Error, ItemMod, Result, Token};
+use std::mem;
+use syn::{parse_quote, Result, Token};
 
-pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
+pub fn bridge(namespace: &Namespace, mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
-    let content = ffi.content.take().ok_or(Error::new(
-        Span::call_site(),
-        "#[cxx::bridge] module must have inline contents",
-    ))?;
-    let ref apis = syntax::parse_items(errors, content.1);
+    let content = mem::take(&mut ffi.content);
+    let ref apis = syntax::parse_items(errors, content);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
@@ -24,7 +23,7 @@ pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
     Ok(expand(namespace, ffi, apis, types))
 }
 
-fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> TokenStream {
+fn expand(namespace: &Namespace, ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index bc8d19b..b8a592b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -13,9 +13,10 @@ mod expand;
 mod syntax;
 mod type_id;
 
+use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod, LitStr};
+use syn::{parse_macro_input, LitStr};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -39,7 +40,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
     let namespace = parse_macro_input!(args as Namespace);
-    let ffi = parse_macro_input!(input as ItemMod);
+    let ffi = parse_macro_input!(input as Module);
 
     expand::bridge(&namespace, ffi)
         .unwrap_or_else(|err| err.to_compile_error())
diff --git a/syntax/file.rs b/syntax/file.rs
new file mode 100644
index 0000000..132a986
--- /dev/null
+++ b/syntax/file.rs
@@ -0,0 +1,47 @@
+use proc_macro2::Span;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::{braced, token, Attribute, Ident, Item, Token, Visibility};
+
+pub struct Module {
+    pub attrs: Vec<Attribute>,
+    pub vis: Visibility,
+    // TODO: unsafety
+    pub mod_token: Token![mod],
+    pub ident: Ident,
+    pub brace_token: token::Brace,
+    pub content: Vec<Item>,
+}
+
+impl Parse for Module {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let vis: Visibility = input.parse()?;
+        let mod_token: Token![mod] = input.parse()?;
+        let ident: Ident = input.parse()?;
+
+        if input.peek(Token![;]) {
+            return Err(Error::new(
+                Span::call_site(),
+                "#[cxx::bridge] module must have inline contents",
+            ))?;
+        }
+
+        let content;
+        let brace_token = braced!(content in input);
+        attrs.extend(content.call(Attribute::parse_inner)?);
+
+        let mut items = Vec::new();
+        while !content.is_empty() {
+            items.push(content.parse()?);
+        }
+
+        Ok(Module {
+            attrs,
+            vis,
+            mod_token,
+            ident,
+            brace_token,
+            content: items,
+        })
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index cd6f235..ae37802 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod derive;
 mod discriminant;
 mod doc;
 pub mod error;
+pub mod file;
 pub mod ident;
 mod impls;
 pub mod mangle;

From fcd8f463a0fbba06ee1e3b06d017e5a8b0fcc6a2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 19:13:52 +0000
Subject: [PATCH 719/2232] Data structure for source file


---

diff --git a/gen/src/file.rs b/gen/src/file.rs
new file mode 100644
index 0000000..3b45fe7
--- /dev/null
+++ b/gen/src/file.rs
@@ -0,0 +1,20 @@
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{Attribute, Item};
+
+pub struct File {
+    pub attrs: Vec<Attribute>,
+    pub items: Vec<Item>,
+}
+
+impl Parse for File {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let attrs = input.call(Attribute::parse_inner)?;
+
+        let mut items = Vec::new();
+        while !input.is_empty() {
+            items.push(input.parse()?);
+        }
+
+        Ok(File { attrs, items })
+    }
+}
diff --git a/gen/src/find.rs b/gen/src/find.rs
index d897deb..d4608c8 100644
--- a/gen/src/find.rs
+++ b/gen/src/find.rs
@@ -1,6 +1,6 @@
-use crate::gen::{Error, Input, Result};
+use crate::gen::{Error, File, Input, Result};
 use crate::syntax::namespace::Namespace;
-use syn::{Attribute, File, Item};
+use syn::{Attribute, Item};
 
 pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
     match scan(syntax.items)? {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 710bca2..8df3404 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -2,6 +2,7 @@
 // the cxxbridge CLI command.
 
 mod error;
+mod file;
 mod find;
 pub(super) mod include;
 pub(super) mod out;
@@ -11,6 +12,7 @@ mod write;
 mod tests;
 
 use self::error::{format_err, Error, Result};
+use self::file::File;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
@@ -56,7 +58,7 @@ fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
 fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
-    let syntax = syn::parse_file(&source)?;
+    let syntax: File = syn::parse_str(source)?;
     let bridge = find::find_bridge_mod(syntax)?;
     let ref namespace = bridge.namespace;
     let ref apis = syntax::parse_items(errors, bridge.module);

From 17c3230d08481f23e7031ee8bd2ff59bba117837 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 19:21:16 +0000
Subject: [PATCH 720/2232] Skip past shebang in source file


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 8df3404..0aa149f 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -49,9 +49,14 @@ fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match generate(&source, opt, header) {
+    let mut source = source.as_str();
+    if source.starts_with("#!") && !source.starts_with("#![") {
+        let shebang_end = source.find('\n').unwrap_or(source.len());
+        source = &source[shebang_end..];
+    }
+    match generate(source, opt, header) {
         Ok(out) => out,
-        Err(err) => format_err(path, &source, err),
+        Err(err) => format_err(path, source, err),
     }
 }
 

From 3c64a4e144a4b7f476345e038212747fd6feb5c6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 21:36:42 +0000
Subject: [PATCH 721/2232] Parse full file using the new Module parser


---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 51dbbe7..537351f 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -16,7 +16,6 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 #[derive(Debug)]
 pub(super) enum Error {
     NoBridgeMod,
-    OutOfLineMod,
     Io(io::Error),
     Syn(syn::Error),
 }
@@ -25,7 +24,6 @@ impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
             Error::Io(err) => err.fmt(f),
             Error::Syn(err) => err.fmt(f),
         }
diff --git a/gen/src/file.rs b/gen/src/file.rs
index 3b45fe7..a2f86e6 100644
--- a/gen/src/file.rs
+++ b/gen/src/file.rs
@@ -1,20 +1,71 @@
-use syn::parse::{Parse, ParseStream, Result};
-use syn::{Attribute, Item};
+use crate::syntax::file::Module;
+use crate::syntax::namespace::Namespace;
+use syn::parse::discouraged::Speculative;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::{braced, Attribute, Ident, Item, Token, Visibility};
 
 pub struct File {
-    pub attrs: Vec<Attribute>,
-    pub items: Vec<Item>,
+    pub modules: Vec<Module>,
 }
 
 impl Parse for File {
     fn parse(input: ParseStream) -> Result<Self> {
-        let attrs = input.call(Attribute::parse_inner)?;
+        let mut modules = Vec::new();
+        input.call(Attribute::parse_inner)?;
+        parse(input, &mut modules)?;
+        Ok(File { modules })
+    }
+}
+
+fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
+    while !input.is_empty() {
+        let mut cxx_bridge = false;
+        let mut namespace = Namespace::none();
+        let attrs = input.call(Attribute::parse_outer)?;
+        for attr in &attrs {
+            let path = &attr.path.segments;
+            if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
+                cxx_bridge = true;
+                namespace = parse_args(attr)?;
+                break;
+            }
+        }
 
-        let mut items = Vec::new();
-        while !input.is_empty() {
-            items.push(input.parse()?);
+        let ahead = input.fork();
+        ahead.parse::<Visibility>()?;
+        ahead.parse::<Option<Token![unsafe]>>()?;
+        if !ahead.peek(Token![mod]) {
+            let item: Item = input.parse()?;
+            if cxx_bridge {
+                return Err(Error::new_spanned(item, "expected a module"));
+            }
+            continue;
         }
 
-        Ok(File { attrs, items })
+        if cxx_bridge {
+            let mut module: Module = input.parse()?;
+            module.namespace = namespace;
+            module.attrs = attrs;
+            modules.push(module);
+        } else {
+            input.advance_to(&ahead);
+            input.parse::<Token![mod]>()?;
+            input.parse::<Ident>()?;
+            let semi: Option<Token![;]> = input.parse()?;
+            if semi.is_none() {
+                let content;
+                braced!(content in input);
+                parse(&content, modules)?;
+            }
+        }
+    }
+    Ok(())
+}
+
+fn parse_args(attr: &Attribute) -> Result<Namespace> {
+    if attr.tokens.is_empty() {
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
     }
 }
diff --git a/gen/src/find.rs b/gen/src/find.rs
deleted file mode 100644
index d4608c8..0000000
--- a/gen/src/find.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::gen::{Error, File, Input, Result};
-use crate::syntax::namespace::Namespace;
-use syn::{Attribute, Item};
-
-pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
-    match scan(syntax.items)? {
-        Some(input) => Ok(input),
-        None => Err(Error::NoBridgeMod),
-    }
-}
-
-fn scan(items: Vec<Item>) -> Result<Option<Input>> {
-    for item in items {
-        if let Item::Mod(item) = item {
-            for attr in &item.attrs {
-                let path = &attr.path.segments;
-                if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
-                    let module = match item.content {
-                        Some(module) => module.1,
-                        None => {
-                            return Err(Error::Syn(syn::Error::new_spanned(
-                                item,
-                                Error::OutOfLineMod,
-                            )));
-                        }
-                    };
-                    let namespace = parse_args(attr)?;
-                    return Ok(Some(Input { namespace, module }));
-                }
-            }
-            if let Some(module) = item.content {
-                if let Some(input) = scan(module.1)? {
-                    return Ok(Some(input));
-                }
-            }
-        }
-    }
-    Ok(None)
-}
-
-fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
-    if attr.tokens.is_empty() {
-        Ok(Namespace::none())
-    } else {
-        attr.parse_args()
-    }
-}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 0aa149f..fa9e407 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -3,7 +3,6 @@
 
 mod error;
 mod file;
-mod find;
 pub(super) mod include;
 pub(super) mod out;
 mod write;
@@ -13,17 +12,10 @@ mod tests;
 
 use self::error::{format_err, Error, Result};
 use self::file::File;
-use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use std::fs;
 use std::path::Path;
-use syn::Item;
-
-struct Input {
-    namespace: Namespace,
-    module: Vec<Item>,
-}
 
 #[derive(Default)]
 pub(super) struct Opt {
@@ -64,9 +56,13 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
     let syntax: File = syn::parse_str(source)?;
-    let bridge = find::find_bridge_mod(syntax)?;
+    let bridge = syntax
+        .modules
+        .into_iter()
+        .next()
+        .ok_or(Error::NoBridgeMod)?;
     let ref namespace = bridge.namespace;
-    let ref apis = syntax::parse_items(errors, bridge.module);
+    let ref apis = syntax::parse_items(errors, bridge.content);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 48ef6a3..aecec75 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -11,21 +11,23 @@ use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
 use syn::{parse_quote, Result, Token};
 
-pub fn bridge(namespace: &Namespace, mut ffi: Module) -> Result<TokenStream> {
+pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
     let content = mem::take(&mut ffi.content);
     let ref apis = syntax::parse_items(errors, content);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
+    let namespace = &ffi.namespace;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
 
-    Ok(expand(namespace, ffi, apis, types))
+    Ok(expand(ffi, apis, types))
 }
 
-fn expand(namespace: &Namespace, ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
+fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
+    let namespace = &ffi.namespace;
 
     for api in apis {
         if let Api::RustType(ety) = api {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b8a592b..c2ad38b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -40,9 +40,10 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
     let namespace = parse_macro_input!(args as Namespace);
-    let ffi = parse_macro_input!(input as Module);
+    let mut ffi = parse_macro_input!(input as Module);
+    ffi.namespace = namespace;
 
-    expand::bridge(&namespace, ffi)
+    expand::bridge(ffi)
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
diff --git a/syntax/file.rs b/syntax/file.rs
index 132a986..dc7c295 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -1,8 +1,10 @@
-use proc_macro2::Span;
+use crate::syntax::namespace::Namespace;
+use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
 use syn::{braced, token, Attribute, Ident, Item, Token, Visibility};
 
 pub struct Module {
+    pub namespace: Namespace,
     pub attrs: Vec<Attribute>,
     pub vis: Visibility,
     // TODO: unsafety
@@ -14,14 +16,17 @@ pub struct Module {
 
 impl Parse for Module {
     fn parse(input: ParseStream) -> Result<Self> {
+        let namespace = Namespace::none();
         let mut attrs = input.call(Attribute::parse_outer)?;
         let vis: Visibility = input.parse()?;
         let mod_token: Token![mod] = input.parse()?;
         let ident: Ident = input.parse()?;
 
-        if input.peek(Token![;]) {
-            return Err(Error::new(
-                Span::call_site(),
+        let semi: Option<Token![;]> = input.parse()?;
+        if let Some(semi) = semi {
+            let span = quote!(#vis #mod_token #semi);
+            return Err(Error::new_spanned(
+                span,
                 "#[cxx::bridge] module must have inline contents",
             ))?;
         }
@@ -36,6 +41,7 @@ impl Parse for Module {
         }
 
         Ok(Module {
+            namespace,
             attrs,
             vis,
             mod_token,

From 633f5669fa03e72917720eb44ec89811ea998907 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 21:47:45 +0000
Subject: [PATCH 722/2232] Parse unsafety on module


---

diff --git a/syntax/file.rs b/syntax/file.rs
index dc7c295..2243235 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -7,7 +7,7 @@ pub struct Module {
     pub namespace: Namespace,
     pub attrs: Vec<Attribute>,
     pub vis: Visibility,
-    // TODO: unsafety
+    pub unsafety: Option<Token![unsafe]>,
     pub mod_token: Token![mod],
     pub ident: Ident,
     pub brace_token: token::Brace,
@@ -19,6 +19,7 @@ impl Parse for Module {
         let namespace = Namespace::none();
         let mut attrs = input.call(Attribute::parse_outer)?;
         let vis: Visibility = input.parse()?;
+        let unsafety: Option<Token![unsafe]> = input.parse()?;
         let mod_token: Token![mod] = input.parse()?;
         let ident: Ident = input.parse()?;
 
@@ -44,6 +45,7 @@ impl Parse for Module {
             namespace,
             attrs,
             vis,
+            unsafety,
             mod_token,
             ident,
             brace_token,

From 00a83852cd9362c2e8bb6c4889801e3980d402c6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 22:11:37 +0000
Subject: [PATCH 723/2232] Data structure for parsed contents of bridge module


---

diff --git a/syntax/file.rs b/syntax/file.rs
index 2243235..f227900 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -1,7 +1,10 @@
 use crate::syntax::namespace::Namespace;
 use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
-use syn::{braced, token, Attribute, Ident, Item, Token, Visibility};
+use syn::{
+    braced, token, Attribute, Ident, Item as RustItem, ItemEnum, ItemForeignMod, ItemStruct,
+    ItemUse, Token, Visibility,
+};
 
 pub struct Module {
     pub namespace: Namespace,
@@ -14,6 +17,14 @@ pub struct Module {
     pub content: Vec<Item>,
 }
 
+pub enum Item {
+    Struct(ItemStruct),
+    Enum(ItemEnum),
+    ForeignMod(ItemForeignMod),
+    Use(ItemUse),
+    Other(RustItem),
+}
+
 impl Parse for Module {
     fn parse(input: ParseStream) -> Result<Self> {
         let namespace = Namespace::none();
@@ -53,3 +64,16 @@ impl Parse for Module {
         })
     }
 }
+
+impl Parse for Item {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let item = input.parse()?;
+        match item {
+            RustItem::Struct(item) => Ok(Item::Struct(item)),
+            RustItem::Enum(item) => Ok(Item::Enum(item)),
+            RustItem::ForeignMod(item) => Ok(Item::ForeignMod(item)),
+            RustItem::Use(item) => Ok(Item::Use(item)),
+            other => Ok(Item::Other(other)),
+        }
+    }
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e195081..117d025 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,4 +1,5 @@
 use crate::syntax::discriminant::DiscriminantSet;
+use crate::syntax::file::Item;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
@@ -11,7 +12,7 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
+    GenericArgument, Ident, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
     Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
@@ -33,7 +34,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
             },
             Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis),
             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
-            _ => cx.error(item, "unsupported item"),
+            Item::Other(item) => cx.error(item, "unsupported item"),
         }
     }
     apis

From c598a279025c8a89b029b2899fccfe6f06f3663a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 22:12:46 +0000
Subject: [PATCH 724/2232] Represent the unsafety on foreign module


---

diff --git a/syntax/file.rs b/syntax/file.rs
index f227900..dfe8e0d 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -2,7 +2,7 @@ use crate::syntax::namespace::Namespace;
 use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
 use syn::{
-    braced, token, Attribute, Ident, Item as RustItem, ItemEnum, ItemForeignMod, ItemStruct,
+    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
     ItemUse, Token, Visibility,
 };
 
@@ -25,6 +25,14 @@ pub enum Item {
     Other(RustItem),
 }
 
+pub struct ItemForeignMod {
+    pub attrs: Vec<Attribute>,
+    pub unsafety: Option<Token![unsafe]>,
+    pub abi: Abi,
+    pub brace_token: token::Brace,
+    pub items: Vec<ForeignItem>,
+}
+
 impl Parse for Module {
     fn parse(input: ParseStream) -> Result<Self> {
         let namespace = Namespace::none();
@@ -71,7 +79,13 @@ impl Parse for Item {
         match item {
             RustItem::Struct(item) => Ok(Item::Struct(item)),
             RustItem::Enum(item) => Ok(Item::Enum(item)),
-            RustItem::ForeignMod(item) => Ok(Item::ForeignMod(item)),
+            RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
+                attrs: item.attrs,
+                unsafety: None,
+                abi: item.abi,
+                brace_token: item.brace_token,
+                items: item.items,
+            })),
             RustItem::Use(item) => Ok(Item::Use(item)),
             other => Ok(Item::Other(other)),
         }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 117d025..c23ee8f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,5 +1,5 @@
 use crate::syntax::discriminant::DiscriminantSet;
-use crate::syntax::file::Item;
+use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
@@ -12,8 +12,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
-    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, ItemEnum, ItemStruct, LitStr, Pat, PathArguments, Result, ReturnType,
+    Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {

From 02550c04a0cb3b3def55f2c16fa9f55ccf7bc0f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 22:20:50 +0000
Subject: [PATCH 725/2232] Preserve inner attrs inside bridge module


---

diff --git a/gen/src/file.rs b/gen/src/file.rs
index a2f86e6..c696407 100644
--- a/gen/src/file.rs
+++ b/gen/src/file.rs
@@ -21,7 +21,7 @@ fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
     while !input.is_empty() {
         let mut cxx_bridge = false;
         let mut namespace = Namespace::none();
-        let attrs = input.call(Attribute::parse_outer)?;
+        let mut attrs = input.call(Attribute::parse_outer)?;
         for attr in &attrs {
             let path = &attr.path.segments;
             if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
@@ -45,6 +45,7 @@ fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
         if cxx_bridge {
             let mut module: Module = input.parse()?;
             module.namespace = namespace;
+            attrs.extend(module.attrs);
             module.attrs = attrs;
             modules.push(module);
         } else {

From 0c0cfee26499acee4563eb281809cbc543c2584c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 22:30:53 +0000
Subject: [PATCH 726/2232] Parse unsafety on extern blocks


---

diff --git a/syntax/file.rs b/syntax/file.rs
index dfe8e0d..2141c17 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -3,7 +3,7 @@ use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
 use syn::{
     braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
-    ItemUse, Token, Visibility,
+    ItemUse, LitStr, Token, Visibility,
 };
 
 pub struct Module {
@@ -75,18 +75,31 @@ impl Parse for Module {
 
 impl Parse for Item {
     fn parse(input: ParseStream) -> Result<Self> {
+        let attrs = input.call(Attribute::parse_outer)?;
+
+        let ahead = input.fork();
+        let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
+            && ahead.parse::<Option<Token![extern]>>()?.is_some()
+            && ahead.parse::<Option<LitStr>>().is_ok()
+            && ahead.peek(token::Brace)
+        {
+            Some(input.parse()?)
+        } else {
+            None
+        };
+
         let item = input.parse()?;
         match item {
-            RustItem::Struct(item) => Ok(Item::Struct(item)),
-            RustItem::Enum(item) => Ok(Item::Enum(item)),
+            RustItem::Struct(item) => Ok(Item::Struct(ItemStruct { attrs, ..item })),
+            RustItem::Enum(item) => Ok(Item::Enum(ItemEnum { attrs, ..item })),
             RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
                 attrs: item.attrs,
-                unsafety: None,
+                unsafety,
                 abi: item.abi,
                 brace_token: item.brace_token,
                 items: item.items,
             })),
-            RustItem::Use(item) => Ok(Item::Use(item)),
+            RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
             other => Ok(Item::Other(other)),
         }
     }

From 3c01ac2383524f772f1f03a8b414136a53c147b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 22:50:33 +0000
Subject: [PATCH 727/2232] Merge pull request #270 from dtolnay/parse


Parse unsafe modules and unsafe extern blocks
---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 51dbbe7..537351f 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -16,7 +16,6 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 #[derive(Debug)]
 pub(super) enum Error {
     NoBridgeMod,
-    OutOfLineMod,
     Io(io::Error),
     Syn(syn::Error),
 }
@@ -25,7 +24,6 @@ impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::OutOfLineMod => write!(f, "#[cxx::bridge] module must have inline contents"),
             Error::Io(err) => err.fmt(f),
             Error::Syn(err) => err.fmt(f),
         }
diff --git a/gen/src/file.rs b/gen/src/file.rs
new file mode 100644
index 0000000..c696407
--- /dev/null
+++ b/gen/src/file.rs
@@ -0,0 +1,72 @@
+use crate::syntax::file::Module;
+use crate::syntax::namespace::Namespace;
+use syn::parse::discouraged::Speculative;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::{braced, Attribute, Ident, Item, Token, Visibility};
+
+pub struct File {
+    pub modules: Vec<Module>,
+}
+
+impl Parse for File {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let mut modules = Vec::new();
+        input.call(Attribute::parse_inner)?;
+        parse(input, &mut modules)?;
+        Ok(File { modules })
+    }
+}
+
+fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
+    while !input.is_empty() {
+        let mut cxx_bridge = false;
+        let mut namespace = Namespace::none();
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        for attr in &attrs {
+            let path = &attr.path.segments;
+            if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
+                cxx_bridge = true;
+                namespace = parse_args(attr)?;
+                break;
+            }
+        }
+
+        let ahead = input.fork();
+        ahead.parse::<Visibility>()?;
+        ahead.parse::<Option<Token![unsafe]>>()?;
+        if !ahead.peek(Token![mod]) {
+            let item: Item = input.parse()?;
+            if cxx_bridge {
+                return Err(Error::new_spanned(item, "expected a module"));
+            }
+            continue;
+        }
+
+        if cxx_bridge {
+            let mut module: Module = input.parse()?;
+            module.namespace = namespace;
+            attrs.extend(module.attrs);
+            module.attrs = attrs;
+            modules.push(module);
+        } else {
+            input.advance_to(&ahead);
+            input.parse::<Token![mod]>()?;
+            input.parse::<Ident>()?;
+            let semi: Option<Token![;]> = input.parse()?;
+            if semi.is_none() {
+                let content;
+                braced!(content in input);
+                parse(&content, modules)?;
+            }
+        }
+    }
+    Ok(())
+}
+
+fn parse_args(attr: &Attribute) -> Result<Namespace> {
+    if attr.tokens.is_empty() {
+        Ok(Namespace::none())
+    } else {
+        attr.parse_args()
+    }
+}
diff --git a/gen/src/find.rs b/gen/src/find.rs
deleted file mode 100644
index d897deb..0000000
--- a/gen/src/find.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::gen::{Error, Input, Result};
-use crate::syntax::namespace::Namespace;
-use syn::{Attribute, File, Item};
-
-pub(super) fn find_bridge_mod(syntax: File) -> Result<Input> {
-    match scan(syntax.items)? {
-        Some(input) => Ok(input),
-        None => Err(Error::NoBridgeMod),
-    }
-}
-
-fn scan(items: Vec<Item>) -> Result<Option<Input>> {
-    for item in items {
-        if let Item::Mod(item) = item {
-            for attr in &item.attrs {
-                let path = &attr.path.segments;
-                if path.len() == 2 && path[0].ident == "cxx" && path[1].ident == "bridge" {
-                    let module = match item.content {
-                        Some(module) => module.1,
-                        None => {
-                            return Err(Error::Syn(syn::Error::new_spanned(
-                                item,
-                                Error::OutOfLineMod,
-                            )));
-                        }
-                    };
-                    let namespace = parse_args(attr)?;
-                    return Ok(Some(Input { namespace, module }));
-                }
-            }
-            if let Some(module) = item.content {
-                if let Some(input) = scan(module.1)? {
-                    return Ok(Some(input));
-                }
-            }
-        }
-    }
-    Ok(None)
-}
-
-fn parse_args(attr: &Attribute) -> syn::Result<Namespace> {
-    if attr.tokens.is_empty() {
-        Ok(Namespace::none())
-    } else {
-        attr.parse_args()
-    }
-}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 710bca2..fa9e407 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -2,7 +2,7 @@
 // the cxxbridge CLI command.
 
 mod error;
-mod find;
+mod file;
 pub(super) mod include;
 pub(super) mod out;
 mod write;
@@ -11,17 +11,11 @@ mod write;
 mod tests;
 
 use self::error::{format_err, Error, Result};
-use crate::syntax::namespace::Namespace;
+use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use std::fs;
 use std::path::Path;
-use syn::Item;
-
-struct Input {
-    namespace: Namespace,
-    module: Vec<Item>,
-}
 
 #[derive(Default)]
 pub(super) struct Opt {
@@ -47,19 +41,28 @@ fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match generate(&source, opt, header) {
+    let mut source = source.as_str();
+    if source.starts_with("#!") && !source.starts_with("#![") {
+        let shebang_end = source.find('\n').unwrap_or(source.len());
+        source = &source[shebang_end..];
+    }
+    match generate(source, opt, header) {
         Ok(out) => out,
-        Err(err) => format_err(path, &source, err),
+        Err(err) => format_err(path, source, err),
     }
 }
 
 fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
-    let syntax = syn::parse_file(&source)?;
-    let bridge = find::find_bridge_mod(syntax)?;
+    let syntax: File = syn::parse_str(source)?;
+    let bridge = syntax
+        .modules
+        .into_iter()
+        .next()
+        .ok_or(Error::NoBridgeMod)?;
     let ref namespace = bridge.namespace;
-    let ref apis = syntax::parse_items(errors, bridge.module);
+    let ref apis = syntax::parse_items(errors, bridge.content);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 0869c2c..aecec75 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,32 +1,33 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
 };
-use proc_macro2::{Ident, Span, TokenStream};
+use proc_macro2::{Ident, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use syn::{parse_quote, Error, ItemMod, Result, Token};
+use std::mem;
+use syn::{parse_quote, Result, Token};
 
-pub fn bridge(namespace: &Namespace, mut ffi: ItemMod) -> Result<TokenStream> {
+pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
-    let content = ffi.content.take().ok_or(Error::new(
-        Span::call_site(),
-        "#[cxx::bridge] module must have inline contents",
-    ))?;
-    let ref apis = syntax::parse_items(errors, content.1);
+    let content = mem::take(&mut ffi.content);
+    let ref apis = syntax::parse_items(errors, content);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
+    let namespace = &ffi.namespace;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
 
-    Ok(expand(namespace, ffi, apis, types))
+    Ok(expand(ffi, apis, types))
 }
 
-fn expand(namespace: &Namespace, ffi: ItemMod, apis: &[Api], types: &Types) -> TokenStream {
+fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
+    let namespace = &ffi.namespace;
 
     for api in apis {
         if let Api::RustType(ety) = api {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index bc8d19b..c2ad38b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -13,9 +13,10 @@ mod expand;
 mod syntax;
 mod type_id;
 
+use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, ItemMod, LitStr};
+use syn::{parse_macro_input, LitStr};
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -39,9 +40,10 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
     let namespace = parse_macro_input!(args as Namespace);
-    let ffi = parse_macro_input!(input as ItemMod);
+    let mut ffi = parse_macro_input!(input as Module);
+    ffi.namespace = namespace;
 
-    expand::bridge(&namespace, ffi)
+    expand::bridge(ffi)
         .unwrap_or_else(|err| err.to_compile_error())
         .into()
 }
diff --git a/syntax/file.rs b/syntax/file.rs
new file mode 100644
index 0000000..2141c17
--- /dev/null
+++ b/syntax/file.rs
@@ -0,0 +1,106 @@
+use crate::syntax::namespace::Namespace;
+use quote::quote;
+use syn::parse::{Error, Parse, ParseStream, Result};
+use syn::{
+    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
+    ItemUse, LitStr, Token, Visibility,
+};
+
+pub struct Module {
+    pub namespace: Namespace,
+    pub attrs: Vec<Attribute>,
+    pub vis: Visibility,
+    pub unsafety: Option<Token![unsafe]>,
+    pub mod_token: Token![mod],
+    pub ident: Ident,
+    pub brace_token: token::Brace,
+    pub content: Vec<Item>,
+}
+
+pub enum Item {
+    Struct(ItemStruct),
+    Enum(ItemEnum),
+    ForeignMod(ItemForeignMod),
+    Use(ItemUse),
+    Other(RustItem),
+}
+
+pub struct ItemForeignMod {
+    pub attrs: Vec<Attribute>,
+    pub unsafety: Option<Token![unsafe]>,
+    pub abi: Abi,
+    pub brace_token: token::Brace,
+    pub items: Vec<ForeignItem>,
+}
+
+impl Parse for Module {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let namespace = Namespace::none();
+        let mut attrs = input.call(Attribute::parse_outer)?;
+        let vis: Visibility = input.parse()?;
+        let unsafety: Option<Token![unsafe]> = input.parse()?;
+        let mod_token: Token![mod] = input.parse()?;
+        let ident: Ident = input.parse()?;
+
+        let semi: Option<Token![;]> = input.parse()?;
+        if let Some(semi) = semi {
+            let span = quote!(#vis #mod_token #semi);
+            return Err(Error::new_spanned(
+                span,
+                "#[cxx::bridge] module must have inline contents",
+            ))?;
+        }
+
+        let content;
+        let brace_token = braced!(content in input);
+        attrs.extend(content.call(Attribute::parse_inner)?);
+
+        let mut items = Vec::new();
+        while !content.is_empty() {
+            items.push(content.parse()?);
+        }
+
+        Ok(Module {
+            namespace,
+            attrs,
+            vis,
+            unsafety,
+            mod_token,
+            ident,
+            brace_token,
+            content: items,
+        })
+    }
+}
+
+impl Parse for Item {
+    fn parse(input: ParseStream) -> Result<Self> {
+        let attrs = input.call(Attribute::parse_outer)?;
+
+        let ahead = input.fork();
+        let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
+            && ahead.parse::<Option<Token![extern]>>()?.is_some()
+            && ahead.parse::<Option<LitStr>>().is_ok()
+            && ahead.peek(token::Brace)
+        {
+            Some(input.parse()?)
+        } else {
+            None
+        };
+
+        let item = input.parse()?;
+        match item {
+            RustItem::Struct(item) => Ok(Item::Struct(ItemStruct { attrs, ..item })),
+            RustItem::Enum(item) => Ok(Item::Enum(ItemEnum { attrs, ..item })),
+            RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
+                attrs: item.attrs,
+                unsafety,
+                abi: item.abi,
+                brace_token: item.brace_token,
+                items: item.items,
+            })),
+            RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
+            other => Ok(Item::Other(other)),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index cd6f235..ae37802 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -7,6 +7,7 @@ mod derive;
 mod discriminant;
 mod doc;
 pub mod error;
+pub mod file;
 pub mod ident;
 mod impls;
 pub mod mangle;
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e195081..c23ee8f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,4 +1,5 @@
 use crate::syntax::discriminant::DiscriminantSet;
+use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
@@ -11,8 +12,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, Item, ItemEnum, ItemForeignMod, ItemStruct, LitStr, Pat, PathArguments,
-    Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, ItemEnum, ItemStruct, LitStr, Pat, PathArguments, Result, ReturnType,
+    Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -33,7 +34,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
             },
             Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis),
             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
-            _ => cx.error(item, "unsupported item"),
+            Item::Other(item) => cx.error(item, "unsupported item"),
         }
     }
     apis

From 0b3eef7435233d50b99dbeac1a665116821ec404 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 29 2020 23:15:09 +0000
Subject: [PATCH 728/2232] Clean up some unneeded clones of the type names


---

diff --git a/syntax/types.rs b/syntax/types.rs
index ba9bc78..2f87d96 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -8,11 +8,11 @@ use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
 
 pub struct Types<'a> {
     pub all: Set<'a, Type>,
-    pub structs: Map<Ident, &'a Struct>,
-    pub enums: Map<Ident, &'a Enum>,
+    pub structs: Map<&'a Ident, &'a Struct>,
+    pub enums: Map<&'a Ident, &'a Enum>,
     pub cxx: Set<'a, Ident>,
     pub rust: Set<'a, Ident>,
-    pub aliases: Map<Ident, &'a TypeAlias>,
+    pub aliases: Map<&'a Ident, &'a TypeAlias>,
 }
 
 impl<'a> Types<'a> {
@@ -53,7 +53,7 @@ impl<'a> Types<'a> {
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
                     if type_names.insert(ident) {
-                        structs.insert(ident.clone(), strct);
+                        structs.insert(ident, strct);
                     } else {
                         duplicate_name(cx, strct, ident);
                     }
@@ -68,7 +68,7 @@ impl<'a> Types<'a> {
                     if !type_names.insert(ident) && !cxx.contains(ident) {
                         duplicate_name(cx, enm, ident);
                     }
-                    enums.insert(ident.clone(), enm);
+                    enums.insert(ident, enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
@@ -104,7 +104,7 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, alias, ident);
                     }
                     cxx.insert(ident);
-                    aliases.insert(ident.clone(), alias);
+                    aliases.insert(ident, alias);
                 }
             }
         }

From 554837220f8b38131b51aa7d56374c3235209ca0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 01:27:46 +0000
Subject: [PATCH 729/2232] Add enum classifier for error messages


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 4fbc6e2..22ae58e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -355,6 +355,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Ident(ident) => {
             if cx.types.structs.contains_key(ident) {
                 "struct".to_owned()
+            } else if cx.types.enums.contains_key(ident) {
+                "enum".to_owned()
             } else if cx.types.cxx.contains(ident) {
                 "C++ type".to_owned()
             } else if cx.types.rust.contains(ident) {

From 8984995600655d86d8a0c524689132256ecd3d3f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 01:35:31 +0000
Subject: [PATCH 730/2232] Box, Vec of an extern enum is supposed to work


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 22ae58e..7b84b18 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -71,7 +71,7 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
 
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.cxx.contains(ident) {
+        if cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident) {
             cx.error(ptr, error::BOX_CXX_TYPE.msg);
         }
 
@@ -85,7 +85,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(ident) {
+        if cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident) {
             cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
@@ -320,7 +320,9 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
-    ident == CxxString || cx.types.cxx.contains(ident) || cx.types.rust.contains(ident)
+    ident == CxxString
+        || cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident)
+        || cx.types.rust.contains(ident)
 }
 
 fn span_for_struct_error(strct: &Struct) -> TokenStream {

From c880ae2c34705d84cede18ccf634b9a170cb0938 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 01:46:50 +0000
Subject: [PATCH 731/2232] Parse extern C++ structs


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 7b84b18..5980f75 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -71,7 +71,10 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
 
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident) {
+        if cx.types.cxx.contains(ident)
+            && !cx.types.structs.contains_key(ident)
+            && !cx.types.enums.contains_key(ident)
+        {
             cx.error(ptr, error::BOX_CXX_TYPE.msg);
         }
 
@@ -85,7 +88,10 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident) {
+        if cx.types.cxx.contains(ident)
+            && !cx.types.structs.contains_key(ident)
+            && !cx.types.enums.contains_key(ident)
+        {
             cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
@@ -168,6 +174,11 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
         cx.error(span, "structs without any fields are not supported");
     }
 
+    if cx.types.cxx.contains(&strct.ident) {
+        let span = span_for_struct_error(strct);
+        cx.error(span, "extern C++ structs are not implemented yet");
+    }
+
     for field in &strct.fields {
         if is_unsized(cx, &field.ty) {
             let desc = describe(cx, &field.ty);
@@ -321,7 +332,9 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         _ => return false,
     };
     ident == CxxString
-        || cx.types.cxx.contains(ident) && !cx.types.enums.contains_key(ident)
+        || cx.types.cxx.contains(ident)
+            && !cx.types.structs.contains_key(ident)
+            && !cx.types.enums.contains_key(ident)
         || cx.types.rust.contains(ident)
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 2f87d96..d579c78 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -48,33 +48,54 @@ impl<'a> Types<'a> {
         let mut type_names = UnorderedSet::new();
         let mut function_names = UnorderedSet::new();
         for api in apis {
+            // The same identifier is permitted to be declared as both a shared
+            // enum and extern C++ type, or shared struct and extern C++ type.
+            // That indicates to not emit the C++ enum/struct definition because
+            // it's defined by the included headers already.
+            //
+            // All other cases of duplicate identifiers are reported as an error.
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
                     let ident = &strct.ident;
-                    if type_names.insert(ident) {
-                        structs.insert(ident, strct);
-                    } else {
+                    if !type_names.insert(ident)
+                        && (!cxx.contains(ident)
+                            || structs.contains_key(ident)
+                            || enums.contains_key(ident))
+                    {
+                        // If already declared as a struct or enum, or if
+                        // colliding with something other than an extern C++
+                        // type, then error.
                         duplicate_name(cx, strct, ident);
                     }
+                    structs.insert(ident, strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
                 }
                 Api::Enum(enm) => {
                     let ident = &enm.ident;
-                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
-                    // means not to emit the C++ enum definition.
-                    if !type_names.insert(ident) && !cxx.contains(ident) {
+                    if !type_names.insert(ident)
+                        && (!cxx.contains(ident)
+                            || structs.contains_key(ident)
+                            || enums.contains_key(ident))
+                    {
+                        // If already declared as a struct or enum, or if
+                        // colliding with something other than an extern C++
+                        // type, then error.
                         duplicate_name(cx, enm, ident);
                     }
                     enums.insert(ident, enm);
                 }
                 Api::CxxType(ety) => {
                     let ident = &ety.ident;
-                    // We allow declaring the same type as a shared enum and as a Cxxtype, as this
-                    // means not to emit the C++ enum definition.
-                    if !type_names.insert(ident) && !enums.contains_key(ident) {
+                    if !type_names.insert(ident)
+                        && (cxx.contains(ident)
+                            || !structs.contains_key(ident) && !enums.contains_key(ident))
+                    {
+                        // If already declared as an extern C++ type, or if
+                        // colliding with something which is neither struct nor
+                        // enum, then error.
                         duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);

From 73075fe85fcee399c9a1c7e92834af2f7b89c553 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 01:58:06 +0000
Subject: [PATCH 732/2232] Fix stray question operator


---

diff --git a/syntax/file.rs b/syntax/file.rs
index 2141c17..8b86adc 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -48,7 +48,7 @@ impl Parse for Module {
             return Err(Error::new_spanned(
                 span,
                 "#[cxx::bridge] module must have inline contents",
-            ))?;
+            ));
         }
 
         let content;

From 3a45173325ea341e8ad15c5846d262be96f056cc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 01:58:06 +0000
Subject: [PATCH 733/2232] Reject unsafe on an extern Rust block


    error: extern "Rust" block does not need to be unsafe
       --> lib.rs:116:5
        |
    116 |     unsafe extern "Rust" {
        |     ^^^^^^^^^^^^^^^^^^^^

---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index c23ee8f..32a6ddf 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -171,11 +171,23 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
 }
 
 fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
-    let lang = match parse_lang(foreign_mod.abi) {
+    let lang = match parse_lang(&foreign_mod.abi) {
         Ok(lang) => lang,
         Err(err) => return cx.push(err),
     };
 
+    match lang {
+        Lang::Rust => {
+            if foreign_mod.unsafety.is_some() {
+                let unsafety = foreign_mod.unsafety;
+                let abi = foreign_mod.abi;
+                let span = quote!(#unsafety #abi);
+                cx.error(span, "extern \"Rust\" block does not need to be unsafe");
+            }
+        }
+        Lang::Cxx => {}
+    }
+
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
@@ -222,7 +234,7 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
     out.extend(items);
 }
 
-fn parse_lang(abi: Abi) -> Result<Lang> {
+fn parse_lang(abi: &Abi) -> Result<Lang> {
     let name = match &abi.name {
         Some(name) => name,
         None => {

From 00f236a0e08d28e25084b707c6f31f5b5020b32d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:10:15 +0000
Subject: [PATCH 734/2232] Keep track of whether extern type layout can be trusted


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index ae37802..e2356e1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -48,6 +48,7 @@ pub struct ExternType {
     pub type_token: Token![type],
     pub ident: Ident,
     pub semi_token: Token![;],
+    pub trusted: bool,
 }
 
 pub struct Struct {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 32a6ddf..7520644 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -176,9 +176,10 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
         Err(err) => return cx.push(err),
     };
 
+    let trusted = foreign_mod.unsafety.is_some();
     match lang {
         Lang::Rust => {
-            if foreign_mod.unsafety.is_some() {
+            if trusted {
                 let unsafety = foreign_mod.unsafety;
                 let abi = foreign_mod.abi;
                 let span = quote!(#unsafety #abi);
@@ -191,7 +192,7 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang) {
+            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang, trusted) {
                 Ok(ety) => items.push(ety),
                 Err(err) => cx.push(err),
             },
@@ -251,7 +252,12 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
     }
 }
 
-fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang) -> Result<Api> {
+fn parse_extern_type(
+    cx: &mut Errors,
+    foreign_type: &ForeignItemType,
+    lang: Lang,
+    trusted: bool,
+) -> Result<Api> {
     let doc = attrs::parse_doc(cx, &foreign_type.attrs);
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
@@ -265,6 +271,7 @@ fn parse_extern_type(cx: &mut Errors, foreign_type: &ForeignItemType, lang: Lang
         type_token,
         ident,
         semi_token,
+        trusted,
     }))
 }
 

From 805dca3e10ac26b0ed952e89db908a54a5207f2b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:11:02 +0000
Subject: [PATCH 735/2232] Propagate unsafety from module to extern block


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index fa9e407..68c6f85 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -62,7 +62,8 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
         .next()
         .ok_or(Error::NoBridgeMod)?;
     let ref namespace = bridge.namespace;
-    let ref apis = syntax::parse_items(errors, bridge.content);
+    let trusted = bridge.unsafety.is_some();
+    let ref apis = syntax::parse_items(errors, bridge.content, trusted);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index aecec75..9cfe3b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -14,7 +14,8 @@ use syn::{parse_quote, Result, Token};
 pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
     let content = mem::take(&mut ffi.content);
-    let ref apis = syntax::parse_items(errors, content);
+    let trusted = ffi.unsafety.is_some();
+    let ref apis = syntax::parse_items(errors, content, trusted);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
     let namespace = &ffi.namespace;
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7520644..415b802 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -20,7 +20,7 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
+pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
@@ -32,7 +32,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>) -> Vec<Api> {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
-            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis),
+            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
             Item::Other(item) => cx.error(item, "unsupported item"),
         }
@@ -170,16 +170,20 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     }))
 }
 
-fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec<Api>) {
+fn parse_foreign_mod(
+    cx: &mut Errors,
+    foreign_mod: ItemForeignMod,
+    out: &mut Vec<Api>,
+    trusted: bool,
+) {
     let lang = match parse_lang(&foreign_mod.abi) {
         Ok(lang) => lang,
         Err(err) => return cx.push(err),
     };
 
-    let trusted = foreign_mod.unsafety.is_some();
     match lang {
         Lang::Rust => {
-            if trusted {
+            if foreign_mod.unsafety.is_some() {
                 let unsafety = foreign_mod.unsafety;
                 let abi = foreign_mod.abi;
                 let span = quote!(#unsafety #abi);
@@ -189,6 +193,8 @@ fn parse_foreign_mod(cx: &mut Errors, foreign_mod: ItemForeignMod, out: &mut Vec
         Lang::Cxx => {}
     }
 
+    let trusted = trusted || foreign_mod.unsafety.is_some();
+
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {

From 45f3f89e4318c8193780a0e88be6356f30587b4f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:19:56 +0000
Subject: [PATCH 736/2232] Write OrderedSet using reference syntax


---

diff --git a/syntax/set.rs b/syntax/set.rs
index 688d1c0..de13088 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -2,12 +2,12 @@ use std::collections::HashSet;
 use std::hash::Hash;
 use std::slice;
 
-pub struct OrderedSet<'a, T> {
-    set: HashSet<&'a T>,
-    vec: Vec<&'a T>,
+pub struct OrderedSet<T> {
+    set: HashSet<T>,
+    vec: Vec<T>,
 }
 
-impl<'a, T> OrderedSet<'a, T>
+impl<'a, T> OrderedSet<&'a T>
 where
     T: Hash + Eq,
 {
@@ -31,7 +31,7 @@ where
     }
 }
 
-impl<'s, 'a, T> IntoIterator for &'s OrderedSet<'a, T> {
+impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
     type Item = &'a T;
     type IntoIter = Iter<'s, 'a, T>;
     fn into_iter(self) -> Self::IntoIter {
diff --git a/syntax/types.rs b/syntax/types.rs
index d579c78..ff3d049 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -7,11 +7,11 @@ use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
 
 pub struct Types<'a> {
-    pub all: Set<'a, Type>,
+    pub all: Set<&'a Type>,
     pub structs: Map<&'a Ident, &'a Struct>,
     pub enums: Map<&'a Ident, &'a Enum>,
-    pub cxx: Set<'a, Ident>,
-    pub rust: Set<'a, Ident>,
+    pub cxx: Set<&'a Ident>,
+    pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
 }
 
@@ -24,7 +24,7 @@ impl<'a> Types<'a> {
         let mut rust = Set::new();
         let mut aliases = Map::new();
 
-        fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) {
+        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}

From da219b38e4409bff01e2701423d8dcb3aefcd0a9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:21:49 +0000
Subject: [PATCH 737/2232] Track set of trusted extern types


---

diff --git a/syntax/types.rs b/syntax/types.rs
index ff3d049..533ea48 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -13,6 +13,7 @@ pub struct Types<'a> {
     pub cxx: Set<&'a Ident>,
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
+    pub trusted: Set<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -23,6 +24,7 @@ impl<'a> Types<'a> {
         let mut cxx = Set::new();
         let mut rust = Set::new();
         let mut aliases = Map::new();
+        let mut trusted = Set::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -99,6 +101,9 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);
+                    if ety.trusted {
+                        trusted.insert(ident);
+                    }
                 }
                 Api::RustType(ety) => {
                     let ident = &ety.ident;
@@ -137,6 +142,7 @@ impl<'a> Types<'a> {
             cxx,
             rust,
             aliases,
+            trusted,
         }
     }
 

From c8b5035ae2d28c0198395554c6a0c6019262e2bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:28:25 +0000
Subject: [PATCH 738/2232] Enforce that extern shared structs are declared unsafe


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 5980f75..f823964 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -167,16 +167,22 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
-    check_reserved_name(cx, &strct.ident);
+    let ident = &strct.ident;
+    check_reserved_name(cx, ident);
 
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
     }
 
-    if cx.types.cxx.contains(&strct.ident) {
-        let span = span_for_struct_error(strct);
-        cx.error(span, "extern C++ structs are not implemented yet");
+    if cx.types.cxx.contains(ident) {
+        if let Some(ety) = cx.types.untrusted.get(ident) {
+            let msg = "extern shared struct must be declared in an `unsafe extern` block";
+            cx.error(ety, msg);
+        } else {
+            let span = span_for_struct_error(strct);
+            cx.error(span, "extern C++ structs are not implemented yet");
+        }
     }
 
     for field in &strct.fields {
diff --git a/syntax/types.rs b/syntax/types.rs
index 533ea48..8a86a46 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -13,7 +13,7 @@ pub struct Types<'a> {
     pub cxx: Set<&'a Ident>,
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
-    pub trusted: Set<&'a Ident>,
+    pub untrusted: Map<&'a Ident, &'a ExternType>,
 }
 
 impl<'a> Types<'a> {
@@ -24,7 +24,7 @@ impl<'a> Types<'a> {
         let mut cxx = Set::new();
         let mut rust = Set::new();
         let mut aliases = Map::new();
-        let mut trusted = Set::new();
+        let mut untrusted = Map::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -101,8 +101,8 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, ety, ident);
                     }
                     cxx.insert(ident);
-                    if ety.trusted {
-                        trusted.insert(ident);
+                    if !ety.trusted {
+                        untrusted.insert(ident, ety);
                     }
                 }
                 Api::RustType(ety) => {
@@ -142,7 +142,7 @@ impl<'a> Types<'a> {
             cxx,
             rust,
             aliases,
-            trusted,
+            untrusted,
         }
     }
 

From a593d6e867ee66f28a4704257bc15a782df25979 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 02:48:08 +0000
Subject: [PATCH 739/2232] Implement extern C++ shared structs


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index a9b8dde..32ccbf6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -62,7 +62,9 @@ pub(super) fn gen(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                write_struct(out, strct);
+                if !types.cxx.contains(&strct.ident) {
+                    write_struct(out, strct);
+                }
             }
             Api::Enum(enm) => {
                 out.next_section();
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9cfe3b5..c2d88ce 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -43,7 +43,8 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
-                if !types.enums.contains_key(&ety.ident) {
+                let ident = &ety.ident;
+                if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
                     expanded.extend(expand_cxx_type(namespace, ety));
                 }
             }
diff --git a/syntax/check.rs b/syntax/check.rs
index f823964..147984e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -179,9 +179,6 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
         if let Some(ety) = cx.types.untrusted.get(ident) {
             let msg = "extern shared struct must be declared in an `unsafe extern` block";
             cx.error(ety, msg);
-        } else {
-            let span = span_for_struct_error(strct);
-            cx.error(span, "extern C++ structs are not implemented yet");
         }
     }
 

From e1e12220dacb76fe45e79fa74706a3e09bbbe402 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:04:31 +0000
Subject: [PATCH 740/2232] Revert "Add option to omit type definitions."


This reverts commit 5a6c7b534d33680606570ffe78b025c145fe6655.

We'll instead use an `extern` type to indicate when a type has already
been defined by C++. This matches the approach to extern enums
introduced in cxx 0.3.1.

    mod ffi {
        struct TheStruct {
            ...
        }
        unsafe extern "C" {
            type TheStruct;
        }
    }

---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 1c84a23..f2e5c9b 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -34,8 +34,6 @@ pub struct Opt {
     /// Whether to set __attribute__((visibility("default")))
     /// or similar annotations on function implementations.
     pub cxx_impl_annotations: Option<String>,
-    /// Whether to omit definitions of types.
-    pub omit_type_definitions: bool,
 }
 
 /// Results of code generation.
diff --git a/gen/src/write.rs b/gen/src/write.rs
index b184b52..51c4b02 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -60,7 +60,7 @@ pub(super) fn gen(
 
     for api in apis {
         match api {
-            Api::Struct(strct) if !opt.omit_type_definitions => {
+            Api::Struct(strct) => {
                 out.next_section();
                 write_struct(out, strct);
             }
@@ -68,7 +68,7 @@ pub(super) fn gen(
                 out.next_section();
                 if types.cxx.contains(&enm.ident) {
                     check_enum(out, enm);
-                } else if !opt.omit_type_definitions {
+                } else {
                     write_enum(out, enm);
                 }
             }

From 5fc28551e180471b822f47b295a76fa2d02bf649 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:14:22 +0000
Subject: [PATCH 741/2232] Merge pull request 258 from adetaylor/cxx-embedding-lib


---

diff --git a/BUCK b/BUCK
index c554e1f..a58e0a2 100644
--- a/BUCK
+++ b/BUCK
@@ -68,3 +68,17 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "lib",
+    srcs = glob(["gen/lib/src/**"]),
+    visibility = ["PUBLIC"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/BUILD b/BUILD
index d5255a8..017b7cc 100644
--- a/BUILD
+++ b/BUILD
@@ -67,3 +67,18 @@ rust_library(
         "//third-party:syn",
     ],
 )
+
+rust_library(
+    name = "lib",
+    srcs = glob(["gen/lib/src/**/*.rs"]),
+    data = ["gen/build/src/gen/include/cxx.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//third-party:anyhow",
+        "//third-party:cc",
+        "//third-party:codespan-reporting",
+        "//third-party:proc-macro2",
+        "//third-party:quote",
+        "//third-party:syn",
+    ],
+)
diff --git a/Cargo.toml b/Cargo.toml
index 5f20ad9..eefafff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "flags", "gen/build", "gen/cmd", "macro", "tests/ffi"]
+members = ["demo-rs", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
new file mode 100644
index 0000000..3a5d938
--- /dev/null
+++ b/gen/lib/Cargo.toml
@@ -0,0 +1,21 @@
+[package]
+name = "cxx-gen"
+version = "0.3.4"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "C++ code generator for integrating `cxx` crate into higher level tools."
+repository = "https://github.com/dtolnay/cxx"
+keywords = ["ffi"]
+categories = ["development-tools::ffi"]
+
+[dependencies]
+anyhow = "1.0"
+cc = "1.0.49"
+codespan-reporting = "0.9"
+proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
+quote = { version = "1.0", default-features = false }
+syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/LICENSE-APACHE b/gen/lib/LICENSE-APACHE
new file mode 120000
index 0000000..1cd601d
--- /dev/null
+++ b/gen/lib/LICENSE-APACHE
@@ -0,0 +1 @@
+../../LICENSE-APACHE
\ No newline at end of file
diff --git a/gen/lib/LICENSE-MIT b/gen/lib/LICENSE-MIT
new file mode 120000
index 0000000..b2cfbdc
--- /dev/null
+++ b/gen/lib/LICENSE-MIT
@@ -0,0 +1 @@
+../../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/lib/src/gen b/gen/lib/src/gen
new file mode 120000
index 0000000..929cb3d
--- /dev/null
+++ b/gen/lib/src/gen
@@ -0,0 +1 @@
+../../src
\ No newline at end of file
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
new file mode 100644
index 0000000..cecf654
--- /dev/null
+++ b/gen/lib/src/lib.rs
@@ -0,0 +1,46 @@
+//! The CXX code generator for constructing and compiling C++ code.
+//!
+//! This is intended to be embedded into higher-level code generators.
+
+mod gen;
+mod syntax;
+
+pub use crate::gen::Opt;
+use proc_macro2::TokenStream;
+
+pub use crate::gen::{Error, GeneratedCode, Result};
+
+/// Generate C++ bindings code from a Rust token stream. This should be a Rust
+/// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
+pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
+    gen::do_generate_from_tokens(rust_source, opt)
+}
+
+#[cfg(test)]
+mod test {
+    use quote::quote;
+
+    #[test]
+    fn test_positive() {
+        let rs = quote! {
+            #[cxx::bridge]
+            mod ffi {
+                extern "C" {
+                    fn in_C();
+                }
+                extern "Rust" {
+                    fn in_rs();
+                }
+            }
+        };
+        let code = crate::generate_header_and_cc(rs).unwrap();
+        assert!(code.cxx.len() > 0);
+        assert!(code.header.len() > 0);
+    }
+
+    #[test]
+    fn test_negative() {
+        let rs = quote! {};
+        assert!(crate::generate_header_and_cc(rs).is_err())
+    }
+}
diff --git a/gen/lib/src/syntax b/gen/lib/src/syntax
new file mode 120000
index 0000000..a6fe06c
--- /dev/null
+++ b/gen/lib/src/syntax
@@ -0,0 +1 @@
+../../../syntax
\ No newline at end of file
diff --git a/gen/src/error.rs b/gen/src/error.rs
index 537351f..9a55243 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -11,12 +11,15 @@ use std::ops::Range;
 use std::path::Path;
 use std::process;
 
-pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
+pub type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
-pub(super) enum Error {
+pub enum Error {
+    /// No `#[cxx::bridge]` module could be found.
     NoBridgeMod,
+    /// An IO error occurred when reading Rust code.
     Io(io::Error),
+    /// A syntax error occurred when parsing Rust code.
     Syn(syn::Error),
 }
 
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 68c6f85..a939760 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -10,15 +10,19 @@ mod write;
 #[cfg(test)]
 mod tests;
 
-use self::error::{format_err, Error, Result};
+use self::error::format_err;
+pub use self::error::{Error, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
+use proc_macro2::TokenStream;
+use std::clone::Clone;
 use std::fs;
 use std::path::Path;
 
-#[derive(Default)]
-pub(super) struct Opt {
+/// Options for C++ code generation.
+#[derive(Default, Clone)]
+pub struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,
     /// Whether to set __attribute__((visibility("default")))
@@ -26,6 +30,14 @@ pub(super) struct Opt {
     pub cxx_impl_annotations: Option<String>,
 }
 
+/// Results of code generation.
+pub struct GeneratedCode {
+    /// The bytes of a C++ header file.
+    pub header: Vec<u8>,
+    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
+    pub cxx: Vec<u8>,
+}
+
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)
@@ -36,26 +48,52 @@ pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     generate_from_path(path, opt, header)
 }
 
+pub(super) fn do_generate_from_tokens(
+    tokens: TokenStream,
+    opt: Opt,
+) -> std::result::Result<GeneratedCode, Error> {
+    let syntax = syn::parse2::<File>(tokens)?;
+    match generate(syntax, opt, true, true) {
+        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
+        Err(err) => Err(err),
+        _ => panic!("Unexpected generation"),
+    }
+}
+
 fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    let mut source = source.as_str();
+    match generate_from_string(&source, opt, header) {
+        Ok(out) => out,
+        Err(err) => format_err(path, &source, err),
+    }
+}
+
+fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+    let mut source = source;
     if source.starts_with("#!") && !source.starts_with("#![") {
         let shebang_end = source.find('\n').unwrap_or(source.len());
         source = &source[shebang_end..];
     }
-    match generate(source, opt, header) {
-        Ok(out) => out,
-        Err(err) => format_err(path, source, err),
+    let syntax: File = syn::parse_str(source)?;
+    let results = generate(syntax, opt, header, !header)?;
+    match results {
+        (Some(hdr), None) => Ok(hdr),
+        (None, Some(cxx)) => Ok(cxx),
+        _ => panic!("Unexpected generation"),
     }
 }
 
-fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+fn generate(
+    syntax: File,
+    opt: Opt,
+    gen_header: bool,
+    gen_cxx: bool,
+) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>)> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
-    let syntax: File = syn::parse_str(source)?;
     let bridge = syntax
         .modules
         .into_iter()
@@ -68,6 +106,18 @@ fn generate(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
-    let out = write::gen(namespace, apis, types, opt, header);
-    Ok(out.content())
+    // Some callers may wish to generate both header and C++
+    // from the same token stream to avoid parsing twice. But others
+    // only need to generate one or the other.
+    let hdr = if gen_header {
+        Some(write::gen(namespace, apis, types, opt.clone(), true).content())
+    } else {
+        None
+    };
+    let cxx = if gen_cxx {
+        Some(write::gen(namespace, apis, types, opt, false).content())
+    } else {
+        None
+    };
+    Ok((hdr, cxx))
 }
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 0e7a910..7621643 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -1,4 +1,4 @@
-use crate::gen::{generate, Opt};
+use crate::gen::{generate_from_string, Opt};
 
 const CPP_EXAMPLE: &'static str = r#"
     #[cxx::bridge]
@@ -15,7 +15,7 @@ fn test_cpp() {
         include: Vec::new(),
         cxx_impl_annotations: None,
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
@@ -28,7 +28,7 @@ fn test_annotation() {
         include: Vec::new(),
         cxx_impl_annotations: Some("ANNOTATION".to_string()),
     };
-    let output = generate(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From 366c41a74e24d45d929e04f15d80ab1445ed8f32 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:28:21 +0000
Subject: [PATCH 742/2232] Move tokenstream-only codepath out of common dir


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index cecf654..aa60b05 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -8,12 +8,25 @@ mod syntax;
 pub use crate::gen::Opt;
 use proc_macro2::TokenStream;
 
-pub use crate::gen::{Error, GeneratedCode, Result};
+pub use crate::gen::{Error, Result};
+
+/// Results of code generation.
+pub struct GeneratedCode {
+    /// The bytes of a C++ header file.
+    pub header: Vec<u8>,
+    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
+    pub cxx: Vec<u8>,
+}
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
 pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
-    gen::do_generate_from_tokens(rust_source, opt)
+    let syntax = syn::parse2(rust_source)?;
+    match gen::generate(syntax, opt, true, true) {
+        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
+        Err(err) => Err(err),
+        _ => panic!("Unexpected generation"),
+    }
 }
 
 #[cfg(test)]
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a939760..9c35285 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -15,7 +15,6 @@ pub use self::error::{Error, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
-use proc_macro2::TokenStream;
 use std::clone::Clone;
 use std::fs;
 use std::path::Path;
@@ -30,14 +29,6 @@ pub struct Opt {
     pub cxx_impl_annotations: Option<String>,
 }
 
-/// Results of code generation.
-pub struct GeneratedCode {
-    /// The bytes of a C++ header file.
-    pub header: Vec<u8>,
-    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
-    pub cxx: Vec<u8>,
-}
-
 pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)
@@ -48,18 +39,6 @@ pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
     generate_from_path(path, opt, header)
 }
 
-pub(super) fn do_generate_from_tokens(
-    tokens: TokenStream,
-    opt: Opt,
-) -> std::result::Result<GeneratedCode, Error> {
-    let syntax = syn::parse2::<File>(tokens)?;
-    match generate(syntax, opt, true, true) {
-        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
-        Err(err) => Err(err),
-        _ => panic!("Unexpected generation"),
-    }
-}
-
 fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
@@ -86,7 +65,7 @@ fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>>
     }
 }
 
-fn generate(
+pub(super) fn generate(
     syntax: File,
     opt: Opt,
     gen_header: bool,

From f33c871b6046253c496f32e4689c1bf8048a9d47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:30:53 +0000
Subject: [PATCH 743/2232] Fix compilation of cxx-gen unit test


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index aa60b05..186e6dd 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -31,6 +31,7 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<Gene
 
 #[cfg(test)]
 mod test {
+    use crate::Opt;
     use quote::quote;
 
     #[test]
@@ -46,7 +47,8 @@ mod test {
                 }
             }
         };
-        let code = crate::generate_header_and_cc(rs).unwrap();
+        let opt = Opt::default();
+        let code = crate::generate_header_and_cc(rs, opt).unwrap();
         assert!(code.cxx.len() > 0);
         assert!(code.header.len() > 0);
     }
@@ -54,6 +56,7 @@ mod test {
     #[test]
     fn test_negative() {
         let rs = quote! {};
-        assert!(crate::generate_header_and_cc(rs).is_err())
+        let opt = Opt::default();
+        assert!(crate::generate_header_and_cc(rs, opt).is_err())
     }
 }

From cae428a3b28b7e92ed3ff32455621d92b1bbd528 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:32:43 +0000
Subject: [PATCH 744/2232] Move test of generated_header_and_cc to integration test


This test only involves the public API of the crate.

---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 186e6dd..da767fa 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -28,35 +28,3 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<Gene
         _ => panic!("Unexpected generation"),
     }
 }
-
-#[cfg(test)]
-mod test {
-    use crate::Opt;
-    use quote::quote;
-
-    #[test]
-    fn test_positive() {
-        let rs = quote! {
-            #[cxx::bridge]
-            mod ffi {
-                extern "C" {
-                    fn in_C();
-                }
-                extern "Rust" {
-                    fn in_rs();
-                }
-            }
-        };
-        let opt = Opt::default();
-        let code = crate::generate_header_and_cc(rs, opt).unwrap();
-        assert!(code.cxx.len() > 0);
-        assert!(code.header.len() > 0);
-    }
-
-    #[test]
-    fn test_negative() {
-        let rs = quote! {};
-        let opt = Opt::default();
-        assert!(crate::generate_header_and_cc(rs, opt).is_err())
-    }
-}
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
new file mode 100644
index 0000000..5c53628
--- /dev/null
+++ b/gen/lib/tests/test.rs
@@ -0,0 +1,28 @@
+use cxx_gen::Opt;
+use quote::quote;
+
+#[test]
+fn test_positive() {
+    let rs = quote! {
+        #[cxx::bridge]
+        mod ffi {
+            extern "C" {
+                fn in_C();
+            }
+            extern "Rust" {
+                fn in_rs();
+            }
+        }
+    };
+    let opt = Opt::default();
+    let code = cxx_gen::generate_header_and_cc(rs, opt).unwrap();
+    assert!(code.cxx.len() > 0);
+    assert!(code.header.len() > 0);
+}
+
+#[test]
+fn test_negative() {
+    let rs = quote! {};
+    let opt = Opt::default();
+    assert!(cxx_gen::generate_header_and_cc(rs, opt).is_err())
+}

From f854d7ee467f3b05d463294e3fe05ee2f5e22dae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:36:31 +0000
Subject: [PATCH 745/2232] Ignore cxx-gen not using format_err


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index da767fa..934d929 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -2,6 +2,8 @@
 //!
 //! This is intended to be embedded into higher-level code generators.
 
+#![allow(dead_code)]
+
 mod gen;
 mod syntax;
 

From 174d30672802cef1a7056f4faff1119cc172b006 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:40:30 +0000
Subject: [PATCH 746/2232] Update POC for cxx-gen crate


---

diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 3a5d938..89cf9f4 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "cxx-gen"
 version = "0.3.4"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
+authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into higher level tools."

From c3fe75d72a791df8a17c47822d24f2f7fc37a415 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:40:49 +0000
Subject: [PATCH 747/2232] Uncouple cxx-gen versioning from cxx crate


---

diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 89cf9f4..348b176 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.3.4"
+version = "0.0.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"

From 1fd4813a897cc3124f21744a84d9598eb7b8a3a2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:46:35 +0000
Subject: [PATCH 748/2232] Fix //:lib bazel build


---

diff --git a/BUILD b/BUILD
index 017b7cc..53bccf7 100644
--- a/BUILD
+++ b/BUILD
@@ -71,7 +71,7 @@ rust_library(
 rust_library(
     name = "lib",
     srcs = glob(["gen/lib/src/**/*.rs"]),
-    data = ["gen/build/src/gen/include/cxx.h"],
+    data = ["gen/lib/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:anyhow",

From 135753b46c4b506d5df3f6578881fe2c28e753d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:48:12 +0000
Subject: [PATCH 749/2232] Include cxx-gen in third-party lockfile


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 65ec211..3c5e6ba 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -90,6 +90,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxx-gen"
+version = "0.0.0"
+dependencies = [
+ "anyhow",
+ "cc",
+ "codespan-reporting",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "cxx-test-suite"
 version = "0.0.0"
 dependencies = [

From 6f7f686f15f8629348d4309d758739d539e5b929 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 05:56:49 +0000
Subject: [PATCH 750/2232] Remove Result alias from API of cxx-gen library


This is unnecessary when we don't expect downstream code to be commonly
passing around cxx_gen::Result<T>.

---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 934d929..3b1b3c6 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -7,11 +7,9 @@
 mod gen;
 mod syntax;
 
-pub use crate::gen::Opt;
+pub use crate::gen::{Error, Opt};
 use proc_macro2::TokenStream;
 
-pub use crate::gen::{Error, Result};
-
 /// Results of code generation.
 pub struct GeneratedCode {
     /// The bytes of a C++ header file.
@@ -22,7 +20,7 @@ pub struct GeneratedCode {
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
-pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode> {
+pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode, Error> {
     let syntax = syn::parse2(rust_source)?;
     match gen::generate(syntax, opt, true, true) {
         Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
diff --git a/gen/src/error.rs b/gen/src/error.rs
index 9a55243..70dcb37 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -11,7 +11,7 @@ use std::ops::Range;
 use std::path::Path;
 use std::process;
 
-pub type Result<T, E = Error> = std::result::Result<T, E>;
+pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub enum Error {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 9c35285..320ff66 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -10,8 +10,8 @@ mod write;
 #[cfg(test)]
 mod tests;
 
-use self::error::format_err;
-pub use self::error::{Error, Result};
+pub use self::error::Error;
+use self::error::{format_err, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};

From e9c533e43031cba8f306c7492ad0902207c0f8f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:03:53 +0000
Subject: [PATCH 751/2232] Hide error enum variants from cxx-gen public api


We can expose more detail on the error as the need arises, but start
with an opaque error type for now.

---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 3b1b3c6..ca9fabe 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -7,8 +7,10 @@
 mod gen;
 mod syntax;
 
-pub use crate::gen::{Error, Opt};
+pub use crate::gen::Opt;
 use proc_macro2::TokenStream;
+use std::error::Error as StdError;
+use std::fmt::{self, Debug, Display};
 
 /// Results of code generation.
 pub struct GeneratedCode {
@@ -18,13 +20,34 @@ pub struct GeneratedCode {
     pub cxx: Vec<u8>,
 }
 
+pub struct Error(crate::gen::Error);
+
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
 pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode, Error> {
-    let syntax = syn::parse2(rust_source)?;
-    match gen::generate(syntax, opt, true, true) {
-        Ok((Some(header), Some(cxx))) => Ok(GeneratedCode { header, cxx }),
-        Err(err) => Err(err),
+    let syntax = syn::parse2(rust_source)
+        .map_err(crate::gen::Error::from)
+        .map_err(Error)?;
+    match gen::generate(syntax, opt, true, true).map_err(Error)? {
+        (Some(header), Some(cxx)) => Ok(GeneratedCode { header, cxx }),
         _ => panic!("Unexpected generation"),
     }
 }
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.0, f)
+    }
+}
+
+impl Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Debug::fmt(&self.0, f)
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        self.0.source()
+    }
+}
diff --git a/gen/src/error.rs b/gen/src/error.rs
index 70dcb37..1cedab1 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -14,12 +14,9 @@ use std::process;
 pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
-pub enum Error {
-    /// No `#[cxx::bridge]` module could be found.
+pub(crate) enum Error {
     NoBridgeMod,
-    /// An IO error occurred when reading Rust code.
     Io(io::Error),
-    /// A syntax error occurred when parsing Rust code.
     Syn(syn::Error),
 }
 
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 320ff66..a5a3780 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -10,7 +10,7 @@ mod write;
 #[cfg(test)]
 mod tests;
 
-pub use self::error::Error;
+pub(super) use self::error::Error;
 use self::error::{format_err, Result};
 use self::file::File;
 use crate::syntax::report::Errors;

From ec0881544d2c94eaa2177f9002ec97f1e5e7afba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:29:26 +0000
Subject: [PATCH 752/2232] Make code generator options non-exhaustive


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a5a3780..a5dcdd0 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -20,7 +20,21 @@ use std::fs;
 use std::path::Path;
 
 /// Options for C++ code generation.
+///
+/// We expect options to be added over time, so this is a non-exhaustive struct.
+/// To instantiate one you need to crate a default value and mutate those fields
+/// that you want to modify.
+///
+/// ```
+/// # use cxx_gen::Opt;
+/// #
+/// let impl_annotations = r#"__attribute__((visibility("default")))"#.to_owned();
+///
+/// let mut opt = Opt::default();
+/// opt.cxx_impl_annotations = Some(impl_annotations);
+/// ```
 #[derive(Default, Clone)]
+#[non_exhaustive]
 pub struct Opt {
     /// Any additional headers to #include
     pub include: Vec<String>,

From df2f78d8bacd9941e551299f7b0b3b361d4ddfd9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:31:53 +0000
Subject: [PATCH 753/2232] Expand on field documentation of Opt struct


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a5dcdd0..5bc51e1 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -36,10 +36,15 @@ use std::path::Path;
 #[derive(Default, Clone)]
 #[non_exhaustive]
 pub struct Opt {
-    /// Any additional headers to #include
+    /// Any additional headers to #include. The cxxbridge tool does not parse or
+    /// even require the given paths to exist; they simply go into the generated
+    /// C++ code as #include lines.
     pub include: Vec<String>,
-    /// Whether to set __attribute__((visibility("default")))
-    /// or similar annotations on function implementations.
+    /// Optional annotation for implementations of C++ function wrappers that
+    /// may be exposed to Rust. You may for example need to provide
+    /// `__declspec(dllexport)` or `__attribute__((visibility("default")))` if
+    /// Rust code from one shared object or executable depends on these C++
+    /// functions in another.
     pub cxx_impl_annotations: Option<String>,
 }
 

From 2719a65d2b33d3703a65356127613b85d521257d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:41:06 +0000
Subject: [PATCH 754/2232] Remove import which is already provided by prelude


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 5bc51e1..6573949 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -15,7 +15,6 @@ use self::error::{format_err, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
-use std::clone::Clone;
 use std::fs;
 use std::path::Path;
 

From a5cca315b3571a47b0192e7c3e000020dd1cb680 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:42:34 +0000
Subject: [PATCH 755/2232] Take codegen options by reference


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 14683b6..a4fcc1d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -102,13 +102,14 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 fn try_generate_bridge(build: &mut cc::Build, rust_source_file: &Path) -> Result<()> {
-    let header = gen::do_generate_header(rust_source_file, Opt::default());
+    let opt = Opt::default();
+    let header = gen::do_generate_header(rust_source_file, &opt);
     let header_path = paths::out_with_extension(rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
     fs::write(&header_path, header)?;
     paths::symlink_header(&header_path, rust_source_file);
 
-    let bridge = gen::do_generate_bridge(rust_source_file, Opt::default());
+    let bridge = gen::do_generate_bridge(rust_source_file, &opt);
     let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
     fs::write(&bridge_path, bridge)?;
     build.file(&bridge_path);
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 0160913..38aab49 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -35,8 +35,8 @@ fn main() {
     };
 
     match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::do_generate_header(&input, gen)),
-        (Some(input), false) => write(gen::do_generate_bridge(&input, gen)),
+        (Some(input), true) => write(gen::do_generate_header(&input, &gen)),
+        (Some(input), false) => write(gen::do_generate_bridge(&input, &gen)),
         (None, true) => write(include::HEADER),
         (None, false) => unreachable!(), // enforced by required_unless
     }
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index ca9fabe..d2ac1ca 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -24,7 +24,7 @@ pub struct Error(crate::gen::Error);
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
-pub fn generate_header_and_cc(rust_source: TokenStream, opt: Opt) -> Result<GeneratedCode, Error> {
+pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<GeneratedCode, Error> {
     let syntax = syn::parse2(rust_source)
         .map_err(crate::gen::Error::from)
         .map_err(Error)?;
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 6573949..0743939 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -32,7 +32,7 @@ use std::path::Path;
 /// let mut opt = Opt::default();
 /// opt.cxx_impl_annotations = Some(impl_annotations);
 /// ```
-#[derive(Default, Clone)]
+#[derive(Default)]
 #[non_exhaustive]
 pub struct Opt {
     /// Any additional headers to #include. The cxxbridge tool does not parse or
@@ -47,17 +47,17 @@ pub struct Opt {
     pub cxx_impl_annotations: Option<String>,
 }
 
-pub(super) fn do_generate_bridge(path: &Path, opt: Opt) -> Vec<u8> {
+pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)
 }
 
-pub(super) fn do_generate_header(path: &Path, opt: Opt) -> Vec<u8> {
+pub(super) fn do_generate_header(path: &Path, opt: &Opt) -> Vec<u8> {
     let header = true;
     generate_from_path(path, opt, header)
 }
 
-fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
+fn generate_from_path(path: &Path, opt: &Opt, header: bool) -> Vec<u8> {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
@@ -68,7 +68,7 @@ fn generate_from_path(path: &Path, opt: Opt, header: bool) -> Vec<u8> {
     }
 }
 
-fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>> {
+fn generate_from_string(source: &str, opt: &Opt, header: bool) -> Result<Vec<u8>> {
     let mut source = source;
     if source.starts_with("#!") && !source.starts_with("#![") {
         let shebang_end = source.find('\n').unwrap_or(source.len());
@@ -85,7 +85,7 @@ fn generate_from_string(source: &str, opt: Opt, header: bool) -> Result<Vec<u8>>
 
 pub(super) fn generate(
     syntax: File,
-    opt: Opt,
+    opt: &Opt,
     gen_header: bool,
     gen_cxx: bool,
 ) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>)> {
@@ -107,7 +107,7 @@ pub(super) fn generate(
     // from the same token stream to avoid parsing twice. But others
     // only need to generate one or the other.
     let hdr = if gen_header {
-        Some(write::gen(namespace, apis, types, opt.clone(), true).content())
+        Some(write::gen(namespace, apis, types, opt, true).content())
     } else {
         None
     };
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 32ccbf6..ccb9f61 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -11,7 +11,7 @@ pub(super) fn gen(
     namespace: &Namespace,
     apis: &[Api],
     types: &Types,
-    opt: Opt,
+    opt: &Opt,
     header: bool,
 ) -> OutFile {
     let mut out_file = OutFile::new(namespace.clone(), header);
@@ -21,7 +21,7 @@ pub(super) fn gen(
         writeln!(out.front, "#pragma once");
     }
 
-    out.include.extend(opt.include);
+    out.include.extend(opt.include.clone());
     for api in apis {
         if let Api::Include(include) = api {
             out.include.insert(include);

From 30d2419e9b184411fbf88e84fef3370f0f9c4103 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 06:50:14 +0000
Subject: [PATCH 756/2232] Get gen dir tests passing


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index c59382e..5a573f0 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -17,5 +17,8 @@ proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
+[dev-dependencies]
+cxx-gen = { version = "=0.0.0", path = "../lib" }
+
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index 5c53628..e69c6fb 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -15,7 +15,7 @@ fn test_positive() {
         }
     };
     let opt = Opt::default();
-    let code = cxx_gen::generate_header_and_cc(rs, opt).unwrap();
+    let code = cxx_gen::generate_header_and_cc(rs, &opt).unwrap();
     assert!(code.cxx.len() > 0);
     assert!(code.header.len() > 0);
 }
@@ -24,5 +24,5 @@ fn test_positive() {
 fn test_negative() {
     let rs = quote! {};
     let opt = Opt::default();
-    assert!(cxx_gen::generate_header_and_cc(rs, opt).is_err())
+    assert!(cxx_gen::generate_header_and_cc(rs, &opt).is_err())
 }
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 7621643..7ef731c 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -1,13 +1,13 @@
 use crate::gen::{generate_from_string, Opt};
 
-const CPP_EXAMPLE: &'static str = r#"
+const CPP_EXAMPLE: &str = r#"
     #[cxx::bridge]
     mod ffi {
         extern "C" {
             pub fn do_cpp_thing(foo: &str);
         }
     }
-    "#;
+"#;
 
 #[test]
 fn test_cpp() {
@@ -15,7 +15,7 @@ fn test_cpp() {
         include: Vec::new(),
         cxx_impl_annotations: None,
     };
-    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
@@ -28,7 +28,7 @@ fn test_annotation() {
         include: Vec::new(),
         cxx_impl_annotations: Some("ANNOTATION".to_string()),
     };
-    let output = generate_from_string(CPP_EXAMPLE, opts, false).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
     let output = std::str::from_utf8(&output).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From 0a46aa04e782bdc320c1a0ac3e8c20135767cbfb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:05:55 +0000
Subject: [PATCH 757/2232] Update third-party lockfile with new dev dependency


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3c5e6ba..a01ac13 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -84,6 +84,7 @@ dependencies = [
  "anyhow",
  "cc",
  "codespan-reporting",
+ "cxx-gen",
  "proc-macro2",
  "quote",
  "syn",

From b555c741af0c3895d02d1621d6c4918a78773247 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:05:55 +0000
Subject: [PATCH 758/2232] Run tests of all workspace crates in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f0ca230..a77af49 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,7 +35,7 @@ jobs:
         with:
           toolchain: ${{matrix.rust}}
       - run: cargo run --manifest-path demo-rs/Cargo.toml
-      - run: cargo test
+      - run: cargo test --all
 
   msrv:
     name: Rust 1.42.0

From 19cb7855b265bd2d9b6ae07a0ca4884c64c27073 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:05:55 +0000
Subject: [PATCH 759/2232] Use GeneratedCode consistently as return type for pair of files


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index d2ac1ca..d707529 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -7,19 +7,11 @@
 mod gen;
 mod syntax;
 
-pub use crate::gen::Opt;
+pub use crate::gen::{GeneratedCode, Opt};
 use proc_macro2::TokenStream;
 use std::error::Error as StdError;
 use std::fmt::{self, Debug, Display};
 
-/// Results of code generation.
-pub struct GeneratedCode {
-    /// The bytes of a C++ header file.
-    pub header: Vec<u8>,
-    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
-    pub cxx: Vec<u8>,
-}
-
 pub struct Error(crate::gen::Error);
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
@@ -28,10 +20,7 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
     let syntax = syn::parse2(rust_source)
         .map_err(crate::gen::Error::from)
         .map_err(Error)?;
-    match gen::generate(syntax, opt, true, true).map_err(Error)? {
-        (Some(header), Some(cxx)) => Ok(GeneratedCode { header, cxx }),
-        _ => panic!("Unexpected generation"),
-    }
+    gen::generate(syntax, opt, true, true).map_err(Error)
 }
 
 impl Display for Error {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 0743939..ff0f736 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -47,6 +47,14 @@ pub struct Opt {
     pub cxx_impl_annotations: Option<String>,
 }
 
+/// Results of code generation.
+pub struct GeneratedCode {
+    /// The bytes of a C++ header file.
+    pub header: Vec<u8>,
+    /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
+    pub cxx: Vec<u8>,
+}
+
 pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)
@@ -75,12 +83,8 @@ fn generate_from_string(source: &str, opt: &Opt, header: bool) -> Result<Vec<u8>
         source = &source[shebang_end..];
     }
     let syntax: File = syn::parse_str(source)?;
-    let results = generate(syntax, opt, header, !header)?;
-    match results {
-        (Some(hdr), None) => Ok(hdr),
-        (None, Some(cxx)) => Ok(cxx),
-        _ => panic!("Unexpected generation"),
-    }
+    let generated = generate(syntax, opt, header, !header)?;
+    Ok(if header { generated.header } else { generated.cxx })
 }
 
 pub(super) fn generate(
@@ -88,7 +92,7 @@ pub(super) fn generate(
     opt: &Opt,
     gen_header: bool,
     gen_cxx: bool,
-) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>)> {
+) -> Result<GeneratedCode> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
     let bridge = syntax
@@ -106,15 +110,16 @@ pub(super) fn generate(
     // Some callers may wish to generate both header and C++
     // from the same token stream to avoid parsing twice. But others
     // only need to generate one or the other.
-    let hdr = if gen_header {
-        Some(write::gen(namespace, apis, types, opt, true).content())
-    } else {
-        None
-    };
-    let cxx = if gen_cxx {
-        Some(write::gen(namespace, apis, types, opt, false).content())
-    } else {
-        None
-    };
-    Ok((hdr, cxx))
+    Ok(GeneratedCode {
+        header: if gen_header {
+            write::gen(namespace, apis, types, opt, true).content()
+        } else {
+            Vec::new()
+        },
+        cxx: if gen_cxx {
+            write::gen(namespace, apis, types, opt, false).content()
+        } else {
+            Vec::new()
+        },
+    })
 }

From d3659d8adad267d45b5e5e365d8723b91f635f04 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:12:25 +0000
Subject: [PATCH 760/2232] Use 'implementation' instead of 'cxx' to refer to source files


---

diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index e69c6fb..be2e60f 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -16,8 +16,8 @@ fn test_positive() {
     };
     let opt = Opt::default();
     let code = cxx_gen::generate_header_and_cc(rs, &opt).unwrap();
-    assert!(code.cxx.len() > 0);
     assert!(code.header.len() > 0);
+    assert!(code.implementation.len() > 0);
 }
 
 #[test]
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index ff0f736..6a1354c 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -52,7 +52,7 @@ pub struct GeneratedCode {
     /// The bytes of a C++ header file.
     pub header: Vec<u8>,
     /// The bytes of a C++ implementation file (e.g. .cc, cpp etc.)
-    pub cxx: Vec<u8>,
+    pub implementation: Vec<u8>,
 }
 
 pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
@@ -84,14 +84,18 @@ fn generate_from_string(source: &str, opt: &Opt, header: bool) -> Result<Vec<u8>
     }
     let syntax: File = syn::parse_str(source)?;
     let generated = generate(syntax, opt, header, !header)?;
-    Ok(if header { generated.header } else { generated.cxx })
+    Ok(if header {
+        generated.header
+    } else {
+        generated.implementation
+    })
 }
 
 pub(super) fn generate(
     syntax: File,
     opt: &Opt,
     gen_header: bool,
-    gen_cxx: bool,
+    gen_implementation: bool,
 ) -> Result<GeneratedCode> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
@@ -116,7 +120,7 @@ pub(super) fn generate(
         } else {
             Vec::new()
         },
-        cxx: if gen_cxx {
+        implementation: if gen_implementation {
             write::gen(namespace, apis, types, opt, false).content()
         } else {
             Vec::new()

From 545d2625afda4647220581cb8a076710c43c28d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:35:03 +0000
Subject: [PATCH 761/2232] Avoid compiling the ffi crate a second time in --test mode


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a77af49..16a2f99 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,7 +35,7 @@ jobs:
         with:
           toolchain: ${{matrix.rust}}
       - run: cargo run --manifest-path demo-rs/Cargo.toml
-      - run: cargo test --all
+      - run: cargo test --all --exclude cxx-test-suite
 
   msrv:
     name: Rust 1.42.0

From 125c91dc096e008b884ff76afb72c088577db9e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:38:15 +0000
Subject: [PATCH 762/2232] Switch from deprecated --all to --workspace


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 16a2f99..55431b6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,7 +35,7 @@ jobs:
         with:
           toolchain: ${{matrix.rust}}
       - run: cargo run --manifest-path demo-rs/Cargo.toml
-      - run: cargo test --all --exclude cxx-test-suite
+      - run: cargo test --workspace --exclude cxx-test-suite
 
   msrv:
     name: Rust 1.42.0

From 318c3530b49595661b7cc3f1f1973ccc746d99b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:50:05 +0000
Subject: [PATCH 763/2232] Handwrite Opt::default to prepare for default-true fields


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 6a1354c..d21db06 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -32,7 +32,6 @@ use std::path::Path;
 /// let mut opt = Opt::default();
 /// opt.cxx_impl_annotations = Some(impl_annotations);
 /// ```
-#[derive(Default)]
 #[non_exhaustive]
 pub struct Opt {
     /// Any additional headers to #include. The cxxbridge tool does not parse or
@@ -55,6 +54,15 @@ pub struct GeneratedCode {
     pub implementation: Vec<u8>,
 }
 
+impl Default for Opt {
+    fn default() -> Self {
+        Opt {
+            include: Vec::new(),
+            cxx_impl_annotations: None,
+        }
+    }
+}
+
 pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
     let header = false;
     generate_from_path(path, opt, header)

From 8238d4a316496f1cf845a04a67d9819380cc81f9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 07:59:29 +0000
Subject: [PATCH 764/2232] Use Opt to control which outputs get generated


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index a4fcc1d..aabac22 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -103,16 +103,16 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 
 fn try_generate_bridge(build: &mut cc::Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
-    let header = gen::do_generate_header(rust_source_file, &opt);
+    let generated = gen::generate_from_path(rust_source_file, &opt);
+
     let header_path = paths::out_with_extension(rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
-    fs::write(&header_path, header)?;
+    fs::write(&header_path, generated.header)?;
     paths::symlink_header(&header_path, rust_source_file);
 
-    let bridge = gen::do_generate_bridge(rust_source_file, &opt);
-    let bridge_path = paths::out_with_extension(rust_source_file, ".cc")?;
-    fs::write(&bridge_path, bridge)?;
-    build.file(&bridge_path);
+    let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
+    fs::write(&implementation_path, generated.implementation)?;
+    build.file(&implementation_path);
 
     let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
     let _ = fs::create_dir_all(cxx_h.parent().unwrap());
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 38aab49..c5cc396 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -32,11 +32,13 @@ fn main() {
     let gen = gen::Opt {
         include: opt.include,
         cxx_impl_annotations: opt.cxx_impl_annotations,
+        gen_header: opt.header,
+        gen_implementation: !opt.header,
     };
 
     match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::do_generate_header(&input, &gen)),
-        (Some(input), false) => write(gen::do_generate_bridge(&input, &gen)),
+        (Some(input), true) => write(gen::generate_from_path(&input, &gen).header),
+        (Some(input), false) => write(gen::generate_from_path(&input, &gen).implementation),
         (None, true) => write(include::HEADER),
         (None, false) => unreachable!(), // enforced by required_unless
     }
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index d707529..7054691 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -20,7 +20,7 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
     let syntax = syn::parse2(rust_source)
         .map_err(crate::gen::Error::from)
         .map_err(Error)?;
-    gen::generate(syntax, opt, true, true).map_err(Error)
+    gen::generate(syntax, opt).map_err(Error)
 }
 
 impl Display for Error {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index d21db06..a832280 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -44,6 +44,9 @@ pub struct Opt {
     /// Rust code from one shared object or executable depends on these C++
     /// functions in another.
     pub cxx_impl_annotations: Option<String>,
+
+    pub(super) gen_header: bool,
+    pub(super) gen_implementation: bool,
 }
 
 /// Results of code generation.
@@ -59,52 +62,34 @@ impl Default for Opt {
         Opt {
             include: Vec::new(),
             cxx_impl_annotations: None,
+            gen_header: true,
+            gen_implementation: true,
         }
     }
 }
 
-pub(super) fn do_generate_bridge(path: &Path, opt: &Opt) -> Vec<u8> {
-    let header = false;
-    generate_from_path(path, opt, header)
-}
-
-pub(super) fn do_generate_header(path: &Path, opt: &Opt) -> Vec<u8> {
-    let header = true;
-    generate_from_path(path, opt, header)
-}
-
-fn generate_from_path(path: &Path, opt: &Opt, header: bool) -> Vec<u8> {
+pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
         Err(err) => format_err(path, "", Error::Io(err)),
     };
-    match generate_from_string(&source, opt, header) {
+    match generate_from_string(&source, opt) {
         Ok(out) => out,
         Err(err) => format_err(path, &source, err),
     }
 }
 
-fn generate_from_string(source: &str, opt: &Opt, header: bool) -> Result<Vec<u8>> {
+fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
     let mut source = source;
     if source.starts_with("#!") && !source.starts_with("#![") {
         let shebang_end = source.find('\n').unwrap_or(source.len());
         source = &source[shebang_end..];
     }
     let syntax: File = syn::parse_str(source)?;
-    let generated = generate(syntax, opt, header, !header)?;
-    Ok(if header {
-        generated.header
-    } else {
-        generated.implementation
-    })
+    generate(syntax, opt)
 }
 
-pub(super) fn generate(
-    syntax: File,
-    opt: &Opt,
-    gen_header: bool,
-    gen_implementation: bool,
-) -> Result<GeneratedCode> {
+pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
     let bridge = syntax
@@ -123,12 +108,12 @@ pub(super) fn generate(
     // from the same token stream to avoid parsing twice. But others
     // only need to generate one or the other.
     Ok(GeneratedCode {
-        header: if gen_header {
+        header: if opt.gen_header {
             write::gen(namespace, apis, types, opt, true).content()
         } else {
             Vec::new()
         },
-        implementation: if gen_implementation {
+        implementation: if opt.gen_implementation {
             write::gen(namespace, apis, types, opt, false).content()
         } else {
             Vec::new()
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 7ef731c..76ff987 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -14,9 +14,11 @@ fn test_cpp() {
     let opts = Opt {
         include: Vec::new(),
         cxx_impl_annotations: None,
+        gen_header: false,
+        gen_implementation: true,
     };
-    let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
-    let output = std::str::from_utf8(&output).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
+    let output = std::str::from_utf8(&output.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
     assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
@@ -27,8 +29,10 @@ fn test_annotation() {
     let opts = Opt {
         include: Vec::new(),
         cxx_impl_annotations: Some("ANNOTATION".to_string()),
+        gen_header: false,
+        gen_implementation: true,
     };
-    let output = generate_from_string(CPP_EXAMPLE, &opts, false).unwrap();
-    let output = std::str::from_utf8(&output).unwrap();
+    let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
+    let output = std::str::from_utf8(&output.implementation).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From c8256aff88af893ecfdf3f224da47e3d1a2aaa76 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 08:32:41 +0000
Subject: [PATCH 765/2232] Link to some context about autocxx


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 7054691..81962e1 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -1,6 +1,11 @@
 //! The CXX code generator for constructing and compiling C++ code.
 //!
-//! This is intended to be embedded into higher-level code generators.
+//! This is intended as a mechanism for embedding the `cxx` crate into
+//! higher-level code generators. See [dtolnay/cxx#235] and
+//! [https://github.com/google/autocxx].
+//!
+//! [dtolnay/cxx#235]: https://github.com/dtolnay/cxx/issues/235
+//! [https://github.com/google/autocxx]: https://github.com/google/autocxx
 
 #![allow(dead_code)]
 

From bf86c33570daf775b30fa9e113d8c068f1e94597 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 08:33:37 +0000
Subject: [PATCH 766/2232] Publish cxx-gen 0.0.1


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 5a573f0..6bbc9e4 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -18,7 +18,7 @@ quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
-cxx-gen = { version = "=0.0.0", path = "../lib" }
+cxx-gen = { version = "=0.0.1", path = "../lib" }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 348b176..eb17487 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.0.0"
+version = "0.0.1"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a01ac13..e9fb1ff 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -92,7 +92,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.0.0"
+version = "0.0.1"
 dependencies = [
  "anyhow",
  "cc",

From 9075cdcd38bf0c02a4c68ff9bcf2c235fd190968 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 19:10:38 +0000
Subject: [PATCH 767/2232] Release 0.3.7


---

diff --git a/Cargo.toml b/Cargo.toml
index eefafff..c21f683 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.6" # remember to update html_root_url
+version = "0.3.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.6", path = "macro" }
+cxxbridge-macro = { version = "=0.3.7", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.3.6", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.3.7", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.6", path = "gen/build" }
+cxx-build = { version = "=0.3.7", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 6e5bc5d..7d7453b 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.3.6"
+version = "0.3.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 6bbc9e4..3faed78 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.6"
+version = "0.3.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 03fb4cf..fd4d31a 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.6"
+version = "0.3.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 2cc2a72..6ca6182 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.6"
+version = "0.3.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index ad195cc..dc26f67 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.7")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index e9fb1ff..ae67969 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.6"
+version = "0.3.7"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.6"
+version = "0.3.7"
 dependencies = [
  "anyhow",
  "cc",
@@ -113,7 +113,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.6"
+version = "0.3.7"
 dependencies = [
  "anyhow",
  "clap",
@@ -133,11 +133,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.3.6"
+version = "0.3.7"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.6"
+version = "0.3.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From f5c72266f7eedfaba8f0dc11cb91a6fba90fdfb1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 20:05:10 +0000
Subject: [PATCH 768/2232] Make a module for the cxx-gen error type


---

diff --git a/gen/lib/src/error.rs b/gen/lib/src/error.rs
new file mode 100644
index 0000000..3cf1e62
--- /dev/null
+++ b/gen/lib/src/error.rs
@@ -0,0 +1,25 @@
+// We can expose more detail on the error as the need arises, but start with an
+// opaque error type for now.
+
+use std::error::Error as StdError;
+use std::fmt::{self, Debug, Display};
+
+pub struct Error(pub(crate) crate::gen::Error);
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Display::fmt(&self.0, f)
+    }
+}
+
+impl Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        Debug::fmt(&self.0, f)
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        self.0.source()
+    }
+}
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 81962e1..bdeedfc 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -9,15 +9,13 @@
 
 #![allow(dead_code)]
 
+mod error;
 mod gen;
 mod syntax;
 
+pub use crate::error::Error;
 pub use crate::gen::{GeneratedCode, Opt};
 use proc_macro2::TokenStream;
-use std::error::Error as StdError;
-use std::fmt::{self, Debug, Display};
-
-pub struct Error(crate::gen::Error);
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
@@ -27,21 +25,3 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
         .map_err(Error)?;
     gen::generate(syntax, opt).map_err(Error)
 }
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(&self.0, f)
-    }
-}
-
-impl Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Debug::fmt(&self.0, f)
-    }
-}
-
-impl StdError for Error {
-    fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        self.0.source()
-    }
-}

From 507bdc1905e3739c0595e5adaa7f794339735053 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 20:07:12 +0000
Subject: [PATCH 769/2232] Store cxx-gen error as braced struct


This appears more sympathetically in rustdoc as:

    pub struct Error { /* fields omitted */ }

rather than:

    pub struct Error(_);

---

diff --git a/gen/lib/src/error.rs b/gen/lib/src/error.rs
index 3cf1e62..26249be 100644
--- a/gen/lib/src/error.rs
+++ b/gen/lib/src/error.rs
@@ -4,22 +4,30 @@
 use std::error::Error as StdError;
 use std::fmt::{self, Debug, Display};
 
-pub struct Error(pub(crate) crate::gen::Error);
+pub struct Error {
+    pub(crate) err: crate::gen::Error,
+}
+
+impl From<crate::gen::Error> for Error {
+    fn from(err: crate::gen::Error) -> Self {
+        Error { err }
+    }
+}
 
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(&self.0, f)
+        Display::fmt(&self.err, f)
     }
 }
 
 impl Debug for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Debug::fmt(&self.0, f)
+        Debug::fmt(&self.err, f)
     }
 }
 
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        self.0.source()
+        self.err.source()
     }
 }
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index bdeedfc..6456200 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -22,6 +22,6 @@ use proc_macro2::TokenStream;
 pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<GeneratedCode, Error> {
     let syntax = syn::parse2(rust_source)
         .map_err(crate::gen::Error::from)
-        .map_err(Error)?;
-    gen::generate(syntax, opt).map_err(Error)
+        .map_err(Error::from)?;
+    gen::generate(syntax, opt).map_err(Error::from)
 }

From 39efd73252e3cf30e3205cef1d2d27a7aec7b988 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 20:24:03 +0000
Subject: [PATCH 770/2232] Add test of cxxbridge cli help text


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 37934e5..1092dcd 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -1,3 +1,7 @@
+#[cfg(test)]
+#[path = "test.rs"]
+mod test;
+
 use super::Opt;
 use clap::AppSettings;
 use std::ffi::{OsStr, OsString};
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
new file mode 100644
index 0000000..a9f1955
--- /dev/null
+++ b/gen/cmd/src/test.rs
@@ -0,0 +1,45 @@
+const EXPECTED: &str = "\
+cxxbridge 0.3.7
+David Tolnay <dtolnay@gmail.com>
+https://github.com/dtolnay/cxx
+
+USAGE:
+    cxxbridge <input>.rs              Emit .cc file for bridge to stdout
+    cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
+    cxxbridge --header                Emit rust/cxx.h header to stdout
+
+ARGS:
+    <input>
+            Input Rust source file containing #[cxx::bridge].
+
+OPTIONS:
+        --cxx-impl-annotations <annotation>
+            Optional annotation for implementations of C++ function wrappers
+            that may be exposed to Rust. You may for example need to provide
+            __declspec(dllexport) or __attribute__((visibility(\"default\")))
+            if Rust code from one shared object or executable depends on
+            these C++ functions in another.
+                
+    -h, --help
+            Print help information.
+
+        --header
+            Emit header with declarations only.
+
+    -i, --include <include>...
+            Any additional headers to #include. The cxxbridge tool does not
+            parse or even require the given paths to exist; they simply go
+            into the generated C++ code as #include lines.
+                
+    -V, --version
+            Print version information.
+";
+
+#[test]
+fn test_help() {
+    let mut app = super::app();
+    let mut out = Vec::new();
+    app.write_long_help(&mut out).unwrap();
+    let help = String::from_utf8(out).unwrap();
+    assert_eq!(help, EXPECTED);
+}

From 1bf1aecda2dc024bb2892a3550862da13e391a8f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 20:24:04 +0000
Subject: [PATCH 771/2232] Work around to avoid trailing whitespace in test file


---

diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index a9f1955..cecb292 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -19,7 +19,7 @@ OPTIONS:
             __declspec(dllexport) or __attribute__((visibility(\"default\")))
             if Rust code from one shared object or executable depends on
             these C++ functions in another.
-                
+               \x20
     -h, --help
             Print help information.
 
@@ -30,7 +30,7 @@ OPTIONS:
             Any additional headers to #include. The cxxbridge tool does not
             parse or even require the given paths to exist; they simply go
             into the generated C++ code as #include lines.
-                
+               \x20
     -V, --version
             Print version information.
 ";

From 509ea2e064c0ce56edd943d3d88fb7111fb77013 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 21:25:56 +0000
Subject: [PATCH 772/2232] Hide BUCK files present in target/package/ from `buck build ...`


---

diff --git a/.buckconfig b/.buckconfig
index 33c15ec..fc837a1 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -3,6 +3,7 @@
   # publish` and `cargo vendor` so this allow_symlinks setting should not be
   # required downstream.
   allow_symlinks = allow
+  ignore = target
 
 [cxx]
   cxxflags = -std=c++11

From b1ea3107e4c2e94fd39486576f5b4ad02b064df2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 30 2020 21:28:42 +0000
Subject: [PATCH 773/2232] Add note about buck project.ignore setting


---

diff --git a/.buckconfig b/.buckconfig
index fc837a1..6a4626f 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -3,6 +3,10 @@
   # publish` and `cargo vendor` so this allow_symlinks setting should not be
   # required downstream.
   allow_symlinks = allow
+
+  # Hide BUCK files under target/package/ from `buck build ...`. Otherwise:
+  #   $ buck build ...
+  #   //target/package/cxx-0.3.0/tests:ffi references non-existing file or directory 'target/package/cxx-0.3.0/tests/ffi/lib.rs'
   ignore = target
 
 [cxx]

From b87d70f08c45306c5d2f28f11731a924e007c47f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 03:02:13 +0000
Subject: [PATCH 774/2232] Fix duplication of error messages


Before:

    ```
    cxxbridge: No such file or directory (os error 2)

    Caused by:
        No such file or directory (os error 2)
    ```

---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 740ab94..c8eafa5 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -24,7 +24,7 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => Some(err),
+            Error::Io(err) => err.source(),
             _ => None,
         }
     }
diff --git a/gen/src/error.rs b/gen/src/error.rs
index 1cedab1..d8badac 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -33,8 +33,8 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => Some(err),
-            Error::Syn(err) => Some(err),
+            Error::Io(err) => err.source(),
+            Error::Syn(err) => err.source(),
             _ => None,
         }
     }

From bb3ba50a8c3427cb2e5a4778b85f239230135119 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 03:22:41 +0000
Subject: [PATCH 775/2232] Replace anyhow dependency with a handwritten reporter


---

diff --git a/BUCK b/BUCK
index a58e0a2..2c60139 100644
--- a/BUCK
+++ b/BUCK
@@ -16,7 +16,6 @@ rust_binary(
     crate = "cxxbridge",
     visibility = ["PUBLIC"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
@@ -60,7 +59,6 @@ rust_library(
     srcs = glob(["gen/build/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
@@ -74,7 +72,6 @@ rust_library(
     srcs = glob(["gen/lib/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
diff --git a/BUILD b/BUILD
index 53bccf7..0248173 100644
--- a/BUILD
+++ b/BUILD
@@ -19,7 +19,6 @@ rust_binary(
     data = ["gen/cmd/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:clap",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
@@ -59,7 +58,6 @@ rust_library(
     data = ["gen/build/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
@@ -74,7 +72,6 @@ rust_library(
     data = ["gen/lib/src/gen/include/cxx.h"],
     visibility = ["//visibility:public"],
     deps = [
-        "//third-party:anyhow",
         "//third-party:cc",
         "//third-party:codespan-reporting",
         "//third-party:proc-macro2",
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3faed78..9858005 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -10,7 +10,6 @@ keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
 [dependencies]
-anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index aabac22..840424e 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -58,8 +58,8 @@ mod paths;
 mod syntax;
 
 use crate::error::Result;
+use crate::gen::error::report;
 use crate::gen::Opt;
-use anyhow::anyhow;
 use std::fs;
 use std::io::{self, Write};
 use std::iter;
@@ -93,7 +93,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 
     for path in rust_source_files {
         if let Err(err) = try_generate_bridge(&mut build, path.as_ref()) {
-            let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {:?}\n\n", anyhow!(err));
+            let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
             process::exit(1);
         }
     }
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index fd4d31a..cd74cee 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -14,7 +14,6 @@ name = "cxxbridge"
 path = "src/main.rs"
 
 [dependencies]
-anyhow = "1.0"
 clap = "2.33"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index eb17487..48a4b72 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -10,7 +10,6 @@ keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
 [dependencies]
-anyhow = "1.0"
 cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
diff --git a/gen/src/error.rs b/gen/src/error.rs
index d8badac..a7ce6e1 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -1,5 +1,4 @@
 use crate::syntax;
-use anyhow::anyhow;
 use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
@@ -63,11 +62,34 @@ pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
                 display_syn_error(stderr, path, source, error);
             }
         }
-        _ => eprintln!("cxxbridge: {:?}", anyhow!(error)),
+        _ => {
+            let _ = writeln!(io::stderr(), "cxxbridge: {}", report(error));
+        }
     }
     process::exit(1);
 }
 
+pub(crate) fn report(error: impl StdError) -> impl Display {
+    struct Report<E>(E);
+
+    impl<E: StdError> Display for Report<E> {
+        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+            Display::fmt(&self.0, formatter)?;
+            let mut error: &dyn StdError = &self.0;
+
+            while let Some(cause) = error.source() {
+                formatter.write_str("\n\nCaused by:\n    ")?;
+                Display::fmt(cause, formatter)?;
+                error = cause;
+            }
+
+            Ok(())
+        }
+    }
+
+    Report(error)
+}
+
 fn sort_syn_errors(error: syn::Error) -> Vec<syn::Error> {
     let mut errors: Vec<_> = error.into_iter().collect();
     errors.sort_by_key(|e| {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a832280..873ce1d 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,7 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
-mod error;
+pub(super) mod error;
 mod file;
 pub(super) mod include;
 pub(super) mod out;
diff --git a/third-party/BUCK b/third-party/BUCK
index 585dafd..95c879a 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -1,13 +1,6 @@
 # To be generated by Facebook's `reindeer` tool once that is open source.
 
 rust_library(
-    name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.32/src/**"]),
-    visibility = ["PUBLIC"],
-    features = ["std"],
-)
-
-rust_library(
     name = "bitflags",
     srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
 )
diff --git a/third-party/BUILD b/third-party/BUILD
index 65edf92..081737e 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -6,13 +6,6 @@ load(
 load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
-    name = "anyhow",
-    srcs = glob(["vendor/anyhow-1.0.32/src/**"]),
-    crate_features = ["std"],
-    visibility = ["//visibility:public"],
-)
-
-rust_library(
     name = "bitflags",
     srcs = glob(["vendor/bitflags-1.2.1/src/**"]),
 )
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ae67969..6e7a504 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -10,12 +10,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "anyhow"
-version = "1.0.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
-
-[[package]]
 name = "atty"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -81,7 +75,6 @@ dependencies = [
 name = "cxx-build"
 version = "0.3.7"
 dependencies = [
- "anyhow",
  "cc",
  "codespan-reporting",
  "cxx-gen",
@@ -94,7 +87,6 @@ dependencies = [
 name = "cxx-gen"
 version = "0.0.1"
 dependencies = [
- "anyhow",
  "cc",
  "codespan-reporting",
  "proc-macro2",
@@ -115,7 +107,6 @@ dependencies = [
 name = "cxxbridge-cmd"
 version = "0.3.7"
 dependencies = [
- "anyhow",
  "clap",
  "codespan-reporting",
  "proc-macro2",

From 0d85ccdf9418904364f7fd97af20002080a59a96 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 03:50:37 +0000
Subject: [PATCH 776/2232] Add context to i/o errors


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index c8eafa5..e1bfff2 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,6 +1,6 @@
+use crate::gen::fs;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
@@ -8,7 +8,7 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 pub(super) enum Error {
     MissingOutDir,
     TargetDir,
-    Io(io::Error),
+    Fs(fs::Error),
 }
 
 impl Display for Error {
@@ -16,7 +16,7 @@ impl Display for Error {
         match self {
             Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
             Error::TargetDir => write!(f, "failed to locate target dir"),
-            Error::Io(err) => err.fmt(f),
+            Error::Fs(err) => err.fmt(f),
         }
     }
 }
@@ -24,14 +24,14 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => err.source(),
+            Error::Fs(err) => err.source(),
             _ => None,
         }
     }
 }
 
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
+impl From<fs::Error> for Error {
+    fn from(err: fs::Error) -> Self {
+        Error::Fs(err)
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 840424e..8f48f20 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,8 +59,7 @@ mod syntax;
 
 use crate::error::Result;
 use crate::gen::error::report;
-use crate::gen::Opt;
-use std::fs;
+use crate::gen::{fs, Opt};
 use std::io::{self, Write};
 use std::iter;
 use std::path::Path;
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index ca183d9..7c572ec 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,6 +1,6 @@
 use crate::error::{Error, Result};
+use crate::gen::fs;
 use std::env;
-use std::fs;
 use std::path::{Path, PathBuf};
 
 fn out_dir() -> Result<PathBuf> {
@@ -94,23 +94,21 @@ fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
     // unable to handle in includes. Use a poor approximation instead.
     // https://github.com/rust-lang/rust/issues/42869
     // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(env::current_dir()?.join(path))
+    Ok(fs::current_dir()?.join(path))
 }
 
 #[cfg(unix)]
-use std::os::unix::fs::symlink as symlink_or_copy;
+use self::fs::symlink as symlink_or_copy;
 
 #[cfg(windows)]
 fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
-    use std::os::windows::fs::symlink_file;
-
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
-    if symlink_file(src, dst).is_err() {
+    if fs::symlink_file(src, dst).is_err() {
         fs::copy(src, dst)?;
     }
     Ok(())
 }
 
 #[cfg(not(any(unix, windows)))]
-use std::fs::copy as symlink_or_copy;
+use self::fs::copy as symlink_or_copy;
diff --git a/gen/src/error.rs b/gen/src/error.rs
index a7ce6e1..f140577 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -1,3 +1,4 @@
+use crate::gen::fs;
 use crate::syntax;
 use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
@@ -15,7 +16,7 @@ pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 #[derive(Debug)]
 pub(crate) enum Error {
     NoBridgeMod,
-    Io(io::Error),
+    Fs(fs::Error),
     Syn(syn::Error),
 }
 
@@ -23,7 +24,7 @@ impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::Io(err) => err.fmt(f),
+            Error::Fs(err) => err.fmt(f),
             Error::Syn(err) => err.fmt(f),
         }
     }
@@ -32,16 +33,16 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => err.source(),
+            Error::Fs(err) => err.source(),
             Error::Syn(err) => err.source(),
             _ => None,
         }
     }
 }
 
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
+impl From<fs::Error> for Error {
+    fn from(err: fs::Error) -> Self {
+        Error::Fs(err)
     }
 }
 
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
new file mode 100644
index 0000000..6ad92f8
--- /dev/null
+++ b/gen/src/fs.rs
@@ -0,0 +1,121 @@
+#![allow(dead_code)]
+
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+use std::path::{Path, PathBuf};
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug)]
+pub(crate) struct Error {
+    source: io::Error,
+    message: String,
+}
+
+impl Display for Error {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.message)
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        Some(&self.source)
+    }
+}
+
+macro_rules! err {
+    ($io_error:expr, $fmt:expr $(, $path:expr)* $(,)?) => {
+        Err(Error {
+            source: $io_error,
+            message: format!($fmt $(, $path.display())*),
+        })
+    }
+}
+
+pub(crate) fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    let path = path.as_ref();
+    match std::fs::canonicalize(path) {
+        Ok(string) => Ok(string),
+        Err(e) => err!(e, "Unable to canonicalize path: `{}`", path),
+    }
+}
+
+pub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64> {
+    let from = from.as_ref();
+    let to = to.as_ref();
+    match std::fs::copy(from, to) {
+        Ok(n) => Ok(n),
+        Err(e) => err!(e, "Failed to copy `{}` -> `{}`", from, to),
+    }
+}
+
+pub(crate) fn create_dir_all(path: impl AsRef<Path>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::create_dir_all(path) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to create directory `{}`", path),
+    }
+}
+
+pub(crate) fn current_dir() -> Result<PathBuf> {
+    match std::env::current_dir() {
+        Ok(dir) => Ok(dir),
+        Err(e) => err!(e, "Failed to determine current directory"),
+    }
+}
+
+pub(crate) fn read_to_string(path: impl AsRef<Path>) -> Result<String> {
+    let path = path.as_ref();
+    match std::fs::read_to_string(path) {
+        Ok(string) => Ok(string),
+        Err(e) => err!(e, "Failed to read file `{}`", path),
+    }
+}
+
+pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::remove_file(path) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to remove file `{}`", path),
+    }
+}
+
+#[cfg(unix)]
+pub(crate) fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+    match std::os::unix::fs::symlink(src, dst) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(
+            e,
+            "Failed to create symlink `{}` pointing to `{}`",
+            dst,
+            src,
+        ),
+    }
+}
+
+#[cfg(windows)]
+pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+    match std::os::windows::fs::symlink_file(src, dst) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(
+            e,
+            "Failed to create symlink `{}` pointing to `{}`",
+            dst,
+            src,
+        ),
+    }
+}
+
+pub(crate) fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::write(path, contents) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to write file `{}`", path),
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 873ce1d..c52d273 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -3,6 +3,7 @@
 
 pub(super) mod error;
 mod file;
+pub(super) mod fs;
 pub(super) mod include;
 pub(super) mod out;
 mod write;
@@ -15,7 +16,6 @@ use self::error::{format_err, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
-use std::fs;
 use std::path::Path;
 
 /// Options for C++ code generation.
@@ -71,7 +71,7 @@ impl Default for Opt {
 pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
-        Err(err) => format_err(path, "", Error::Io(err)),
+        Err(err) => format_err(path, "", Error::Fs(err)),
     };
     match generate_from_string(&source, opt) {
         Ok(out) => out,

From d150c13e8af3d848e796063c6197b53b319b3161 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 03:57:21 +0000
Subject: [PATCH 777/2232] Merge pull request #272 from dtolnay/context


Add context to i/o errors
---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index c8eafa5..e1bfff2 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,6 +1,6 @@
+use crate::gen::fs;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
@@ -8,7 +8,7 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 pub(super) enum Error {
     MissingOutDir,
     TargetDir,
-    Io(io::Error),
+    Fs(fs::Error),
 }
 
 impl Display for Error {
@@ -16,7 +16,7 @@ impl Display for Error {
         match self {
             Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
             Error::TargetDir => write!(f, "failed to locate target dir"),
-            Error::Io(err) => err.fmt(f),
+            Error::Fs(err) => err.fmt(f),
         }
     }
 }
@@ -24,14 +24,14 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => err.source(),
+            Error::Fs(err) => err.source(),
             _ => None,
         }
     }
 }
 
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
+impl From<fs::Error> for Error {
+    fn from(err: fs::Error) -> Self {
+        Error::Fs(err)
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 840424e..8f48f20 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,8 +59,7 @@ mod syntax;
 
 use crate::error::Result;
 use crate::gen::error::report;
-use crate::gen::Opt;
-use std::fs;
+use crate::gen::{fs, Opt};
 use std::io::{self, Write};
 use std::iter;
 use std::path::Path;
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index ca183d9..7c572ec 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,6 +1,6 @@
 use crate::error::{Error, Result};
+use crate::gen::fs;
 use std::env;
-use std::fs;
 use std::path::{Path, PathBuf};
 
 fn out_dir() -> Result<PathBuf> {
@@ -94,23 +94,21 @@ fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
     // unable to handle in includes. Use a poor approximation instead.
     // https://github.com/rust-lang/rust/issues/42869
     // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(env::current_dir()?.join(path))
+    Ok(fs::current_dir()?.join(path))
 }
 
 #[cfg(unix)]
-use std::os::unix::fs::symlink as symlink_or_copy;
+use self::fs::symlink as symlink_or_copy;
 
 #[cfg(windows)]
 fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
-    use std::os::windows::fs::symlink_file;
-
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
-    if symlink_file(src, dst).is_err() {
+    if fs::symlink_file(src, dst).is_err() {
         fs::copy(src, dst)?;
     }
     Ok(())
 }
 
 #[cfg(not(any(unix, windows)))]
-use std::fs::copy as symlink_or_copy;
+use self::fs::copy as symlink_or_copy;
diff --git a/gen/src/error.rs b/gen/src/error.rs
index a7ce6e1..f140577 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -1,3 +1,4 @@
+use crate::gen::fs;
 use crate::syntax;
 use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
@@ -15,7 +16,7 @@ pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 #[derive(Debug)]
 pub(crate) enum Error {
     NoBridgeMod,
-    Io(io::Error),
+    Fs(fs::Error),
     Syn(syn::Error),
 }
 
@@ -23,7 +24,7 @@ impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
-            Error::Io(err) => err.fmt(f),
+            Error::Fs(err) => err.fmt(f),
             Error::Syn(err) => err.fmt(f),
         }
     }
@@ -32,16 +33,16 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::Io(err) => err.source(),
+            Error::Fs(err) => err.source(),
             Error::Syn(err) => err.source(),
             _ => None,
         }
     }
 }
 
-impl From<io::Error> for Error {
-    fn from(err: io::Error) -> Self {
-        Error::Io(err)
+impl From<fs::Error> for Error {
+    fn from(err: fs::Error) -> Self {
+        Error::Fs(err)
     }
 }
 
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
new file mode 100644
index 0000000..6ad92f8
--- /dev/null
+++ b/gen/src/fs.rs
@@ -0,0 +1,121 @@
+#![allow(dead_code)]
+
+use std::error::Error as StdError;
+use std::fmt::{self, Display};
+use std::io;
+use std::path::{Path, PathBuf};
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug)]
+pub(crate) struct Error {
+    source: io::Error,
+    message: String,
+}
+
+impl Display for Error {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.message)
+    }
+}
+
+impl StdError for Error {
+    fn source(&self) -> Option<&(dyn StdError + 'static)> {
+        Some(&self.source)
+    }
+}
+
+macro_rules! err {
+    ($io_error:expr, $fmt:expr $(, $path:expr)* $(,)?) => {
+        Err(Error {
+            source: $io_error,
+            message: format!($fmt $(, $path.display())*),
+        })
+    }
+}
+
+pub(crate) fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
+    let path = path.as_ref();
+    match std::fs::canonicalize(path) {
+        Ok(string) => Ok(string),
+        Err(e) => err!(e, "Unable to canonicalize path: `{}`", path),
+    }
+}
+
+pub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64> {
+    let from = from.as_ref();
+    let to = to.as_ref();
+    match std::fs::copy(from, to) {
+        Ok(n) => Ok(n),
+        Err(e) => err!(e, "Failed to copy `{}` -> `{}`", from, to),
+    }
+}
+
+pub(crate) fn create_dir_all(path: impl AsRef<Path>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::create_dir_all(path) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to create directory `{}`", path),
+    }
+}
+
+pub(crate) fn current_dir() -> Result<PathBuf> {
+    match std::env::current_dir() {
+        Ok(dir) => Ok(dir),
+        Err(e) => err!(e, "Failed to determine current directory"),
+    }
+}
+
+pub(crate) fn read_to_string(path: impl AsRef<Path>) -> Result<String> {
+    let path = path.as_ref();
+    match std::fs::read_to_string(path) {
+        Ok(string) => Ok(string),
+        Err(e) => err!(e, "Failed to read file `{}`", path),
+    }
+}
+
+pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::remove_file(path) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to remove file `{}`", path),
+    }
+}
+
+#[cfg(unix)]
+pub(crate) fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+    match std::os::unix::fs::symlink(src, dst) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(
+            e,
+            "Failed to create symlink `{}` pointing to `{}`",
+            dst,
+            src,
+        ),
+    }
+}
+
+#[cfg(windows)]
+pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+    match std::os::windows::fs::symlink_file(src, dst) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(
+            e,
+            "Failed to create symlink `{}` pointing to `{}`",
+            dst,
+            src,
+        ),
+    }
+}
+
+pub(crate) fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::write(path, contents) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to write file `{}`", path),
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 873ce1d..c52d273 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -3,6 +3,7 @@
 
 pub(super) mod error;
 mod file;
+pub(super) mod fs;
 pub(super) mod include;
 pub(super) mod out;
 mod write;
@@ -15,7 +16,6 @@ use self::error::{format_err, Result};
 use self::file::File;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
-use std::fs;
 use std::path::Path;
 
 /// Options for C++ code generation.
@@ -71,7 +71,7 @@ impl Default for Opt {
 pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
     let source = match fs::read_to_string(path) {
         Ok(source) => source,
-        Err(err) => format_err(path, "", Error::Io(err)),
+        Err(err) => format_err(path, "", Error::Fs(err)),
     };
     match generate_from_string(&source, opt) {
         Ok(out) => out,

From 585a9fe8d4d3a89e5c05ee4b5f02d3746ca03fca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 04:03:38 +0000
Subject: [PATCH 778/2232] Remove link-cplusplus dependency from non-Cargo builds


---

diff --git a/BUCK b/BUCK
index 2c60139..0dfa11b 100644
--- a/BUCK
+++ b/BUCK
@@ -6,7 +6,6 @@ rust_library(
     deps = [
         ":core",
         ":macro",
-        "//third-party:link-cplusplus",
     ],
 )
 
diff --git a/BUILD b/BUILD
index 0248173..27c6931 100644
--- a/BUILD
+++ b/BUILD
@@ -7,10 +7,7 @@ rust_library(
         ":cxxbridge-macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [
-        ":core-lib",
-        "//third-party:link-cplusplus",
-    ],
+    deps = [":core-lib"],
 )
 
 rust_binary(
diff --git a/build.rs b/build.rs
index 2aad99f..cecf0e5 100644
--- a/build.rs
+++ b/build.rs
@@ -7,4 +7,5 @@ fn main() {
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
+    println!("cargo:rustc-cfg=built_with_cargo");
 }
diff --git a/src/lib.rs b/src/lib.rs
index dc26f67..4053c85 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -368,6 +368,7 @@
     clippy::useless_let_if_seq
 )]
 
+#[cfg(built_with_cargo)]
 extern crate link_cplusplus;
 
 #[macro_use]
diff --git a/third-party/BUCK b/third-party/BUCK
index 95c879a..86e8e72 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -39,12 +39,6 @@ rust_library(
 )
 
 rust_library(
-    name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
-    visibility = ["PUBLIC"],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
diff --git a/third-party/BUILD b/third-party/BUILD
index 081737e..7ceec9b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -44,12 +44,6 @@ rust_library(
 )
 
 rust_library(
-    name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
-    visibility = ["//visibility:public"],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     crate_features = [

From bc7fd41907d7b17d37eef03dc6c60b192cf3a455 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 04:10:51 +0000
Subject: [PATCH 779/2232] Merge pull request #273 from dtolnay/built


Remove link-cplusplus dependency from non-Cargo builds
---

diff --git a/BUCK b/BUCK
index 2c60139..0dfa11b 100644
--- a/BUCK
+++ b/BUCK
@@ -6,7 +6,6 @@ rust_library(
     deps = [
         ":core",
         ":macro",
-        "//third-party:link-cplusplus",
     ],
 )
 
diff --git a/BUILD b/BUILD
index 0248173..27c6931 100644
--- a/BUILD
+++ b/BUILD
@@ -7,10 +7,7 @@ rust_library(
         ":cxxbridge-macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [
-        ":core-lib",
-        "//third-party:link-cplusplus",
-    ],
+    deps = [":core-lib"],
 )
 
 rust_binary(
diff --git a/build.rs b/build.rs
index 2aad99f..cecf0e5 100644
--- a/build.rs
+++ b/build.rs
@@ -7,4 +7,5 @@ fn main() {
         .compile("cxxbridge03");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
+    println!("cargo:rustc-cfg=built_with_cargo");
 }
diff --git a/src/lib.rs b/src/lib.rs
index dc26f67..4053c85 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -368,6 +368,7 @@
     clippy::useless_let_if_seq
 )]
 
+#[cfg(built_with_cargo)]
 extern crate link_cplusplus;
 
 #[macro_use]
diff --git a/third-party/BUCK b/third-party/BUCK
index 95c879a..86e8e72 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -39,12 +39,6 @@ rust_library(
 )
 
 rust_library(
-    name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
-    visibility = ["PUBLIC"],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     visibility = ["PUBLIC"],
diff --git a/third-party/BUILD b/third-party/BUILD
index 081737e..7ceec9b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -44,12 +44,6 @@ rust_library(
 )
 
 rust_library(
-    name = "link-cplusplus",
-    srcs = glob(["vendor/link-cplusplus-1.0.2/src/**"]),
-    visibility = ["//visibility:public"],
-)
-
-rust_library(
     name = "proc-macro2",
     srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
     crate_features = [

From f574c5ed0fdb17cb9ed759760ec3fba554e334cb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 07:22:28 +0000
Subject: [PATCH 780/2232] Import cc::Build


The lack of import here was left over from cxx 0.2 where this code was
part of a distinct cxx::Build type. Now that the entry point to
cxx-build is a function rather than a Build type, we are free to import
cc's Build.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8f48f20..c7d452f 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -60,6 +60,7 @@ mod syntax;
 use crate::error::Result;
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
+use cc::Build;
 use std::io::{self, Write};
 use std::iter;
 use std::path::Path;
@@ -71,7 +72,7 @@ use std::process;
 ///
 /// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
 #[must_use]
-pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
+pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
     bridges(iter::once(rust_source_file))
 }
 
@@ -85,7 +86,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> cc::Build {
 ///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
-pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> cc::Build {
+pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
     let mut build = paths::cc_build();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
@@ -100,7 +101,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
     build
 }
 
-fn try_generate_bridge(build: &mut cc::Build, rust_source_file: &Path) -> Result<()> {
+fn try_generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
 

From 27991968aa1cbf221edbdf8221270b0050e29028 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 07:25:05 +0000
Subject: [PATCH 781/2232] Factor out Result-returning logic of cxx-build


This arrangement makes it easy to insert fallible steps into `build`
which will be able to use `?` operator.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index c7d452f..8d2e519 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -87,18 +87,23 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
 ///     .compile("cxxbridge-demo");
 /// ```
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
+    let ref mut rust_source_files = rust_source_files.into_iter();
+    build(rust_source_files).unwrap_or_else(|err| {
+        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
+        process::exit(1);
+    })
+}
+
+fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let mut build = paths::cc_build();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
 
     for path in rust_source_files {
-        if let Err(err) = try_generate_bridge(&mut build, path.as_ref()) {
-            let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
-            process::exit(1);
-        }
+        try_generate_bridge(&mut build, path.as_ref())?;
     }
 
-    build
+    Ok(build)
 }
 
 fn try_generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {

From f7c0426a9fa8580c2e6700f5725a3c3f11013fda Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 07:28:54 +0000
Subject: [PATCH 782/2232] Write rust/cxx.h header only once


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8d2e519..afbcbe1 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -98,15 +98,24 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut build = paths::cc_build();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+    write_header()?;
 
     for path in rust_source_files {
-        try_generate_bridge(&mut build, path.as_ref())?;
+        generate_bridge(&mut build, path.as_ref())?;
     }
 
     Ok(build)
 }
 
-fn try_generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
+fn write_header() -> Result<()> {
+    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
+    let _ = fs::remove_file(cxx_h);
+    let _ = fs::write(cxx_h, gen::include::HEADER);
+    Ok(())
+}
+
+fn generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
 
@@ -118,11 +127,5 @@ fn try_generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()>
     let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
     fs::write(&implementation_path, generated.implementation)?;
     build.file(&implementation_path);
-
-    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
-    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
-    let _ = fs::remove_file(cxx_h);
-    let _ = fs::write(cxx_h, gen::include::HEADER);
-
     Ok(())
 }

From dbff3c4dc24466a4870e40fdad9cb83bb254c2a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 07:58:02 +0000
Subject: [PATCH 783/2232] Handle non-utf8 input file with better error


---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index f140577..b269286 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -8,8 +8,9 @@ use std::error::Error as StdError;
 use std::fmt::{self, Display};
 use std::io::{self, Write};
 use std::ops::Range;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process;
+use std::str::Utf8Error;
 
 pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 
@@ -17,6 +18,7 @@ pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
 pub(crate) enum Error {
     NoBridgeMod,
     Fs(fs::Error),
+    Utf8(PathBuf, Utf8Error),
     Syn(syn::Error),
 }
 
@@ -25,6 +27,7 @@ impl Display for Error {
         match self {
             Error::NoBridgeMod => write!(f, "no #[cxx::bridge] module found"),
             Error::Fs(err) => err.fmt(f),
+            Error::Utf8(path, _) => write!(f, "Failed to read file `{}`", path.display()),
             Error::Syn(err) => err.fmt(f),
         }
     }
@@ -34,6 +37,7 @@ impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
             Error::Fs(err) => err.source(),
+            Error::Utf8(_, err) => Some(err),
             Error::Syn(err) => err.source(),
             _ => None,
         }
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 6ad92f8..d1b0b70 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -66,9 +66,9 @@ pub(crate) fn current_dir() -> Result<PathBuf> {
     }
 }
 
-pub(crate) fn read_to_string(path: impl AsRef<Path>) -> Result<String> {
+pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
     let path = path.as_ref();
-    match std::fs::read_to_string(path) {
+    match std::fs::read(path) {
         Ok(string) => Ok(string),
         Err(e) => err!(e, "Failed to read file `{}`", path),
     }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index c52d273..f4d643d 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -69,9 +69,9 @@ impl Default for Opt {
 }
 
 pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
-    let source = match fs::read_to_string(path) {
+    let source = match read_to_string(path) {
         Ok(source) => source,
-        Err(err) => format_err(path, "", Error::Fs(err)),
+        Err(err) => format_err(path, "", err),
     };
     match generate_from_string(&source, opt) {
         Ok(out) => out,
@@ -79,6 +79,14 @@ pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
     }
 }
 
+fn read_to_string(path: &Path) -> Result<String> {
+    let bytes = fs::read(path)?;
+    match String::from_utf8(bytes) {
+        Ok(string) => Ok(string),
+        Err(err) => Err(Error::Utf8(path.to_owned(), err.utf8_error())),
+    }
+}
+
 fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
     let mut source = source;
     if source.starts_with("#!") && !source.starts_with("#![") {

From ad3dbdc535c7195c54fa0d5eca325135da9149bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 08:01:39 +0000
Subject: [PATCH 784/2232] Avoid bumping modified time of existing up to date files


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index afbcbe1..001f346 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -109,9 +109,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
 fn write_header() -> Result<()> {
     let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
-    let _ = fs::create_dir_all(cxx_h.parent().unwrap());
-    let _ = fs::remove_file(cxx_h);
-    let _ = fs::write(cxx_h, gen::include::HEADER);
+    let _ = write(cxx_h, gen::include::HEADER.as_bytes());
     Ok(())
 }
 
@@ -121,11 +119,27 @@ fn generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
 
     let header_path = paths::out_with_extension(rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
-    fs::write(&header_path, generated.header)?;
+    write(&header_path, &generated.header)?;
     paths::symlink_header(&header_path, rust_source_file);
 
     let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
-    fs::write(&implementation_path, generated.implementation)?;
+    write(&implementation_path, &generated.implementation)?;
     build.file(&implementation_path);
     Ok(())
 }
+
+fn write(path: &Path, content: &[u8]) -> Result<()> {
+    if path.exists() {
+        if let Ok(existing) = fs::read(path) {
+            if existing == content {
+                // Avoid bumping modified time with unchanged contents.
+                return Ok(());
+            }
+        }
+        let _ = fs::remove_file(path);
+    } else {
+        let _ = fs::create_dir_all(path.parent().unwrap());
+    }
+    fs::write(path, content)?;
+    Ok(())
+}

From d300109c6f3875367457c01ba7fcabcc0203ac93 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Aug 31 2020 08:05:57 +0000
Subject: [PATCH 785/2232] Update bazel build to rustc 1.46


---

diff --git a/WORKSPACE b/WORKSPACE
index 08e7c80..5e0cf9e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,13 +24,13 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_45_linux",
+    name = "rust_1_46_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.45.0",
+    version = "1.46.0",
 )
 
 rust_repository_set(
-    name = "rust_1_45_darwin",
+    name = "rust_1_46_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.45.0",
+    version = "1.46.0",
 )

From 1de699da146b4ebfd376ed572bc7710809ba3870 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 01 2020 03:29:06 +0000
Subject: [PATCH 786/2232] Treat cxx_build::bridges as must_use, same as ::bridge


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 001f346..1b4bbaa 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -86,6 +86,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
 ///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
+#[must_use]
 pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
     let ref mut rust_source_files = rust_source_files.into_iter();
     build(rust_source_files).unwrap_or_else(|err| {

From 9f1e3d76a366acf2ead31a43256766bfcef5352f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 01 2020 19:40:51 +0000
Subject: [PATCH 787/2232] Release 0.3.8


---

diff --git a/Cargo.toml b/Cargo.toml
index c21f683..5458398 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.7" # remember to update html_root_url
+version = "0.3.8" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.7", path = "macro" }
+cxxbridge-macro = { version = "=0.3.8", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.3.7", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.3.8", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.7", path = "gen/build" }
+cxx-build = { version = "=0.3.8", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 7d7453b..061237a 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.3.7"
+version = "0.3.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 9858005..2e536f7 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.7"
+version = "0.3.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index cd74cee..a49e22f 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.7"
+version = "0.3.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 6ca6182..aabd4d1 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.7"
+version = "0.3.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 4053c85..a707338 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.8")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6e7a504..268c9f4 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.7"
+version = "0.3.8"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.7"
+version = "0.3.8"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.7"
+version = "0.3.8"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -124,11 +124,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.3.7"
+version = "0.3.8"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.7"
+version = "0.3.8"
 dependencies = [
  "cxx",
  "proc-macro2",

From 8eb3dcef466c74d8dfb42e74d8f8f8b624f1bb0b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 01 2020 20:02:08 +0000
Subject: [PATCH 788/2232] Remove version number from cmd help test


---

diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index cecb292..f119189 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -1,5 +1,5 @@
 const EXPECTED: &str = "\
-cxxbridge 0.3.7
+cxxbridge $VERSION
 David Tolnay <dtolnay@gmail.com>
 https://github.com/dtolnay/cxx
 
@@ -41,5 +41,7 @@ fn test_help() {
     let mut out = Vec::new();
     app.write_long_help(&mut out).unwrap();
     let help = String::from_utf8(out).unwrap();
-    assert_eq!(help, EXPECTED);
+    let version = option_env!("CARGO_PKG_VERSION").unwrap_or_default();
+    let expected = EXPECTED.replace("$VERSION", version);
+    assert_eq!(help, expected);
 }

From f48e97e55a31de50b4c0b455db48bbcc7554b9fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 01 2020 21:17:17 +0000
Subject: [PATCH 789/2232] Use correct target dir determined by cargo


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
new file mode 100644
index 0000000..91f229d
--- /dev/null
+++ b/gen/build/src/cargo.rs
@@ -0,0 +1,30 @@
+use crate::error::TargetDirError;
+use std::path::PathBuf;
+use std::process::Command;
+use std::str;
+
+pub(crate) fn target_dir() -> Result<PathBuf, TargetDirError> {
+    let cargo = option_env!("CARGO").unwrap_or("cargo");
+    let output = Command::new(cargo)
+        .arg("metadata")
+        .arg("--no-deps")
+        .arg("--format-version=1")
+        .output()
+        .map_err(TargetDirError::Io)?;
+
+    (|| {
+        // Cargo only outputs utf8 encoded JSON.
+        let mut metadata = str::from_utf8(&output.stdout).ok()?;
+
+        let key_pattern = "\"target_directory\":";
+        let key_index = metadata.rfind(key_pattern)?;
+        metadata = &metadata[key_index + key_pattern.len()..];
+        let open_quote_index = metadata.find('"')?;
+        metadata = &metadata[open_quote_index + 1..];
+        let close_quote_index = metadata.find('"')?;
+        let string = &metadata[..close_quote_index];
+        let target_directory = string.replace("\\\\", "\\");
+        Some(PathBuf::from(target_directory))
+    })()
+    .ok_or(TargetDirError::NotFound)
+}
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index e1bfff2..ed4c6af 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,21 +1,28 @@
 use crate::gen::fs;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
+use std::io;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub(super) enum Error {
     MissingOutDir,
-    TargetDir,
+    TargetDir(TargetDirError),
     Fs(fs::Error),
 }
 
+#[derive(Debug)]
+pub(crate) enum TargetDirError {
+    Io(io::Error),
+    NotFound,
+}
+
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
-            Error::TargetDir => write!(f, "failed to locate target dir"),
+            Error::TargetDir(_) => write!(f, "unable to identify target dir"),
             Error::Fs(err) => err.fmt(f),
         }
     }
@@ -24,6 +31,10 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
+            Error::TargetDir(err) => match err {
+                TargetDirError::Io(err) => Some(err),
+                TargetDirError::NotFound => None,
+            },
             Error::Fs(err) => err.source(),
             _ => None,
         }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 1b4bbaa..2560aee 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -52,6 +52,7 @@
     clippy::toplevel_ref_arg
 )]
 
+mod cargo;
 mod error;
 mod gen;
 mod paths;
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 7c572ec..82cb5cc 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,3 +1,4 @@
+use crate::cargo;
 use crate::error::{Error, Result};
 use crate::gen::fs;
 use std::env;
@@ -72,13 +73,19 @@ pub(crate) fn include_dir() -> Result<PathBuf> {
 }
 
 fn target_dir() -> Result<PathBuf> {
+    let fallback_err = match cargo::target_dir() {
+        Ok(target_dir) => return Ok(target_dir),
+        Err(err) => Error::TargetDir(err),
+    };
+
+    // Fallback if Cargo did not work.
     let mut dir = out_dir().and_then(canonicalize)?;
     loop {
         if dir.ends_with("target") {
             return Ok(dir);
         }
         if !dir.pop() {
-            return Err(Error::TargetDir);
+            return Err(fallback_err);
         }
     }
 }

From 7273963a616c0346759f0f50b7d1efb7f253e11e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 03:48:11 +0000
Subject: [PATCH 790/2232] Sort buck genrule args the way buildifier wants


https://github.com/bazelbuild/buildtools/tree/master/buildifier

---

diff --git a/demo-rs/BUCK b/demo-rs/BUCK
index d4164d3..a3f460b 100644
--- a/demo-rs/BUCK
+++ b/demo-rs/BUCK
@@ -20,17 +20,17 @@ cxx_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
+    out = "generated.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
     type = "cxxbridge",
-    out = "generated.h",
 )
 
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
+    out = "generated.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     type = "cxxbridge",
-    out = "generated.cc",
 )
 
 cxx_library(
diff --git a/tests/BUCK b/tests/BUCK
index 41781c8..4bfc9e8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -34,20 +34,20 @@ cxx_library(
 genrule(
     name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
     out = "lib.rs.h",
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     out = "lib.rs.cc",
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-module-source",
     srcs = ["ffi/module.rs"],
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     out = "module.rs.cc",
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )

From 37531b477eb9576c798ce96d8672fdc3b8bd82d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 03:48:12 +0000
Subject: [PATCH 791/2232] Combine demo into one root directory


---

diff --git a/Cargo.toml b/Cargo.toml
index 5458398..c950d2e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
 readme = "README.md"
-exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
+exclude = ["/demo", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
@@ -34,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
+members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
deleted file mode 100644
index f60200b..0000000
--- a/demo-cxx/BUCK
+++ /dev/null
@@ -1,17 +0,0 @@
-cxx_library(
-    name = "demo-cxx",
-    srcs = ["demo.cc"],
-    compiler_flags = ["-std=c++14"],
-    visibility = ["PUBLIC"],
-    deps = [
-        ":include",
-        "//demo-rs:include",
-    ],
-)
-
-cxx_library(
-    name = "include",
-    exported_headers = ["demo.h"],
-    visibility = ["PUBLIC"],
-    deps = ["//:core"],
-)
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
deleted file mode 100644
index 7b1860a..0000000
--- a/demo-cxx/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-cc_library(
-    name = "demo-cxx",
-    srcs = ["demo.cc"],
-    copts = ["-std=c++14"],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":include",
-        "//demo-rs:include",
-    ],
-)
-
-cc_library(
-    name = "include",
-    hdrs = ["demo.h"],
-    visibility = ["//visibility:public"],
-    deps = ["//:core"],
-)
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
deleted file mode 100644
index 21bdad4..0000000
--- a/demo-cxx/demo.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "demo-cxx/demo.h"
-#include "demo-rs/src/main.rs.h"
-#include <iostream>
-
-namespace org {
-namespace example {
-
-ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
-
-ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::make_unique<ThingC>(std::string(appname));
-}
-
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
-void do_thing(SharedThing state) { print_r(*state.y); }
-
-} // namespace example
-} // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
deleted file mode 100644
index fafc474..0000000
--- a/demo-cxx/demo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-#include "rust/cxx.h"
-#include <memory>
-#include <string>
-
-namespace org {
-namespace example {
-
-class ThingC {
-public:
-  ThingC(std::string appname);
-  ~ThingC();
-
-  std::string appname;
-};
-
-struct SharedThing;
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
-
-} // namespace example
-} // namespace org
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
deleted file mode 100644
index a3f460b..0000000
--- a/demo-rs/BUCK
+++ /dev/null
@@ -1,42 +0,0 @@
-rust_binary(
-    name = "demo-rs",
-    srcs = glob(["src/**"]),
-    deps = [
-        ":gen",
-        "//:cxx",
-        "//demo-cxx:demo-cxx",
-    ],
-)
-
-cxx_library(
-    name = "gen",
-    srcs = [":gen-source"],
-    deps = [
-        ":include",
-        "//demo-cxx:include",
-    ],
-)
-
-genrule(
-    name = "gen-header",
-    srcs = ["src/main.rs"],
-    out = "generated.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-genrule(
-    name = "gen-source",
-    srcs = ["src/main.rs"],
-    out = "generated.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-cxx_library(
-    name = "include",
-    exported_headers = {
-        "src/main.rs.h": ":gen-header",
-    },
-    visibility = ["PUBLIC"],
-)
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
deleted file mode 100644
index e3ebb96..0000000
--- a/demo-rs/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
-
-rust_binary(
-    name = "demo-rs",
-    srcs = glob(["src/**"]),
-    deps = [
-        ":gen",
-        "//:cxx",
-        "//demo-cxx",
-    ],
-)
-
-cc_library(
-    name = "gen",
-    srcs = [":gen-source"],
-    deps = [
-        ":include",
-        "//demo-cxx:include",
-    ],
-)
-
-genrule(
-    name = "gen-header",
-    srcs = ["src/main.rs"],
-    outs = ["main.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "gen-source",
-    srcs = ["src/main.rs"],
-    outs = ["generated.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
-    include_prefix = "demo-rs/src",
-    visibility = ["//visibility:public"],
-)
diff --git a/demo-rs/Cargo.toml b/demo-rs/Cargo.toml
deleted file mode 100644
index d2147ab..0000000
--- a/demo-rs/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "cxxbridge-demo"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-cxx = { path = ".." }
-
-[build-dependencies]
-cxx-build = { path = "../gen/build" }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
deleted file mode 100644
index f32b8ef..0000000
--- a/demo-rs/build.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    cxx_build::bridge("src/main.rs")
-        .file("../demo-cxx/demo.cc")
-        .flag_if_supported("-std=c++14")
-        .compile("cxxbridge-demo");
-
-    println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
-}
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
deleted file mode 100644
index 66dfc79..0000000
--- a/demo-rs/src/main.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#[cxx::bridge(namespace = org::example)]
-mod ffi {
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
-    }
-
-    extern "C" {
-        include!("demo-cxx/demo.h");
-
-        type ThingC;
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
-    }
-
-    extern "Rust" {
-        type ThingR;
-        fn print_r(r: &ThingR);
-    }
-}
-
-pub struct ThingR(usize);
-
-fn print_r(r: &ThingR) {
-    println!("called back with r={}", r.0);
-}
-
-fn main() {
-    let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
-
-    ffi::do_thing(ffi::SharedThing {
-        z: 222,
-        y: Box::new(ThingR(333)),
-        x,
-    });
-}
diff --git a/demo/BUCK b/demo/BUCK
new file mode 100644
index 0000000..78e75e6
--- /dev/null
+++ b/demo/BUCK
@@ -0,0 +1,57 @@
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":demo-sys",
+        ":gen",
+        "//:cxx",
+    ],
+)
+
+cxx_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    out = "generated.h",
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    out = "generated.cc",
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = {
+        "src/main.rs.h": ":gen-header",
+    },
+)
+
+cxx_library(
+    name = "demo-sys",
+    srcs = ["src/demo.cc"],
+    compiler_flags = ["-std=c++14"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+cxx_library(
+    name = "demo-include",
+    exported_headers = ["include/demo.h"],
+    deps = ["//:core"],
+)
diff --git a/demo/BUILD b/demo/BUILD
new file mode 100644
index 0000000..1edc65c
--- /dev/null
+++ b/demo/BUILD
@@ -0,0 +1,58 @@
+load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
+
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":demo-sys",
+        ":gen",
+        "//:cxx",
+    ],
+)
+
+cc_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    outs = ["main.rs.h"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    outs = ["generated.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "demo/src",
+)
+
+cc_library(
+    name = "demo-sys",
+    srcs = ["src/demo.cc"],
+    copts = ["-std=c++14"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+cc_library(
+    name = "demo-include",
+    hdrs = ["include/demo.h"],
+    deps = ["//:core"],
+)
diff --git a/demo/Cargo.toml b/demo/Cargo.toml
new file mode 100644
index 0000000..d2147ab
--- /dev/null
+++ b/demo/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "cxxbridge-demo"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+publish = false
+
+[dependencies]
+cxx = { path = ".." }
+
+[build-dependencies]
+cxx-build = { path = "../gen/build" }
diff --git a/demo/build.rs b/demo/build.rs
new file mode 100644
index 0000000..a3c31b3
--- /dev/null
+++ b/demo/build.rs
@@ -0,0 +1,10 @@
+fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/demo.cc")
+        .flag_if_supported("-std=c++14")
+        .compile("cxxbridge-demo");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
+}
diff --git a/demo/include/demo.h b/demo/include/demo.h
new file mode 100644
index 0000000..fafc474
--- /dev/null
+++ b/demo/include/demo.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "rust/cxx.h"
+#include <memory>
+#include <string>
+
+namespace org {
+namespace example {
+
+class ThingC {
+public:
+  ThingC(std::string appname);
+  ~ThingC();
+
+  std::string appname;
+};
+
+struct SharedThing;
+
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
+const std::string &get_name(const ThingC &thing);
+void do_thing(SharedThing state);
+
+} // namespace example
+} // namespace org
diff --git a/demo/src/demo.cc b/demo/src/demo.cc
new file mode 100644
index 0000000..79c693f
--- /dev/null
+++ b/demo/src/demo.cc
@@ -0,0 +1,21 @@
+#include "demo/include/demo.h"
+#include "demo/src/main.rs.h"
+#include <iostream>
+
+namespace org {
+namespace example {
+
+ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
+
+ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
+
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
+  return std::make_unique<ThingC>(std::string(appname));
+}
+
+const std::string &get_name(const ThingC &thing) { return thing.appname; }
+
+void do_thing(SharedThing state) { print_r(*state.y); }
+
+} // namespace example
+} // namespace org
diff --git a/demo/src/main.rs b/demo/src/main.rs
new file mode 100644
index 0000000..ee7e093
--- /dev/null
+++ b/demo/src/main.rs
@@ -0,0 +1,39 @@
+#[cxx::bridge(namespace = org::example)]
+mod ffi {
+    struct SharedThing {
+        z: i32,
+        y: Box<ThingR>,
+        x: UniquePtr<ThingC>,
+    }
+
+    extern "C" {
+        include!("demo/include/demo.h");
+
+        type ThingC;
+        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
+        fn get_name(thing: &ThingC) -> &CxxString;
+        fn do_thing(state: SharedThing);
+    }
+
+    extern "Rust" {
+        type ThingR;
+        fn print_r(r: &ThingR);
+    }
+}
+
+pub struct ThingR(usize);
+
+fn print_r(r: &ThingR) {
+    println!("called back with r={}", r.0);
+}
+
+fn main() {
+    let x = ffi::make_demo("demo of cxx::bridge");
+    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
+
+    ffi::do_thing(ffi::SharedThing {
+        z: 222,
+        y: Box::new(ThingR(333)),
+        x,
+    });
+}

From 278f6fc8cdc30637b4998d3b840f1311f1cebf66 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 03:48:13 +0000
Subject: [PATCH 792/2232] Update demo documentation


---

diff --git a/README.md b/README.md
index 345ce7d..9c65df6 100644
--- a/README.md
+++ b/README.md
@@ -60,9 +60,8 @@ function calls Rust's `len()`.
 
 ## Example
 
-A runnable version of this example is provided under the *demo-rs* directory of
-this repo (with the C++ side of the implementation in the *demo-cxx* directory).
-To try it out, jump into demo-rs and run `cargo run`.
+A runnable version of this example is provided under the *demo* directory of
+this repo. To try it out, run `cargo run` from that directory.
 
 ```rust
 #[cxx::bridge]
@@ -78,7 +77,7 @@ mod ffi {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
-        include!("demo-cxx/demo.h");
+        include!("demo/include/demo.h");
 
         // Zero or more opaque types which both languages can pass around but
         // only C++ can see the fields.
@@ -107,10 +106,10 @@ get to call back and forth safely.
 
 Here are links to the complete set of source files involved in the demo:
 
-- [demo-rs/src/main.rs](demo-rs/src/main.rs)
-- [demo-rs/build.rs](demo-rs/build.rs)
-- [demo-cxx/demo.h](demo-cxx/demo.h)
-- [demo-cxx/demo.cc](demo-cxx/demo.cc)
+- [demo/src/main.rs](demo/src/main.rs)
+- [demo/build.rs](demo/build.rs)
+- [demo/include/demo.h](demo/include/demo.h)
+- [demo/src/demo.cc](demo/src/demo.cc)
 
 To look at the code generated in both languages for the example by the CXX code
 generators:
@@ -118,10 +117,10 @@ generators:
 ```console
    # run Rust code generator and print to stdout
    # (requires https://github.com/dtolnay/cargo-expand)
-$ cargo expand --manifest-path demo-rs/Cargo.toml
+$ cargo expand --manifest-path demo/Cargo.toml
 
    # run C++ code generator and print to stdout
-$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
+$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
 ```
 
 <br>
@@ -228,13 +227,13 @@ cxx-build = "0.3"
 
 fn main() {
     cxx_build::bridge("src/main.rs")  // returns a cc::Build
-        .file("../demo-cxx/demo.cc")
+        .file("src/demo.cc")
         .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
 }
 ```
 
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 2560aee..768de15 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -15,18 +15,18 @@
 //!
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")
-//!         .file("../demo-cxx/demo.cc")
+//!         .file("src/demo.cc")
 //!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//!     println!("cargo:rerun-if-changed=src/demo.cc");
+//!     println!("cargo:rerun-if-changed=include/demo.h");
 //! }
 //! ```
 //!
-//! A runnable working setup with this build script is shown in the
-//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
+//! A runnable working setup with this build script is shown in the *demo*
+//! directory of [https://github.com/dtolnay/cxx].
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 //!
@@ -83,7 +83,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
 /// ```no_run
 /// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
 /// cxx_build::bridges(source_files)
-///     .file("../demo-cxx/demo.cc")
+///     .file("src/demo.cc")
 ///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
diff --git a/src/lib.rs b/src/lib.rs
index a707338..94a9037 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,10 +57,9 @@
 //!
 //! # Example
 //!
-//! A runnable version of this example is provided under the *demo-rs* directory
-//! of [https://github.com/dtolnay/cxx] (with the C++ side of the implementation
-//! in the *demo-cxx* directory). To try it out, jump into demo-rs and run
-//! `cargo run`.
+//! A runnable version of this example is provided under the *demo* directory of
+//! [https://github.com/dtolnay/cxx]. To try it out, run `cargo run` from that
+//! directory.
 //!
 //! ```no_run
 //! #[cxx::bridge]
@@ -76,7 +75,7 @@
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
-//!         include!("demo-cxx/demo.h");
+//!         include!("demo/include/demo.h");
 //!
 //!         // Zero or more opaque types which both languages can pass around but
 //!         // only C++ can see the fields.
@@ -113,10 +112,10 @@
 //!
 //! Here are links to the complete set of source files involved in the demo:
 //!
-//! - [demo-rs/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/src/main.rs)
-//! - [demo-rs/build.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/build.rs)
-//! - [demo-cxx/demo.h](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.h)
-//! - [demo-cxx/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.cc)
+//! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
+//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
+//! - [demo/include/demo.h](https://github.com/dtolnay/cxx/blob/master/demo/include/demo.h)
+//! - [demo/src/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/demo.cc)
 //!
 //! To look at the code generated in both languages for the example by the CXX
 //! code generators:
@@ -124,10 +123,10 @@
 //! ```console
 //!    # run Rust code generator and print to stdout
 //!    # (requires https://github.com/dtolnay/cargo-expand)
-//! $ cargo expand --manifest-path demo-rs/Cargo.toml
+//! $ cargo expand --manifest-path demo/Cargo.toml
 //!
 //!    # run C++ code generator and print to stdout
-//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
+//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
 //! ```
 //!
 //! <br>
@@ -237,13 +236,13 @@
 //!
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
-//!         .file("../demo-cxx/demo.cc")
+//!         .file("src/demo.cc")
 //!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//!     println!("cargo:rerun-if-changed=src/demo.cc");
+//!     println!("cargo:rerun-if-changed=include/demo.h");
 //! }
 //! ```
 //!

From f401e882a32adf3ed3c8fac4f1721f845d954b08 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 03:58:48 +0000
Subject: [PATCH 793/2232] Update demo path in CI workflow


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 55431b6..315bac2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,7 +34,7 @@ jobs:
       - uses: dtolnay/rust-toolchain@master
         with:
           toolchain: ${{matrix.rust}}
-      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
 
   msrv:
@@ -43,7 +43,7 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@1.42.0
-      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo run --manifest-path demo/Cargo.toml
 
   buck:
     name: Buck
@@ -66,7 +66,7 @@ jobs:
           cp third-party/Cargo.lock .
           cargo vendor --versioned-dirs --locked third-party/vendor
       - run: buck build :cxx#check --verbose=0
-      - run: buck run demo-rs --verbose=0
+      - run: buck run demo --verbose=0
       - run: buck test ... --verbose=0
 
   bazel:
@@ -84,5 +84,5 @@ jobs:
         run: |
           cp third-party/Cargo.lock .
           cargo vendor --versioned-dirs --locked third-party/vendor
-      - run: bazel run demo-rs --verbose_failures --noshow_progress
+      - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress

From 9ffb7b66e38be6ce9b7fa4c385012e55036adadb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:04:36 +0000
Subject: [PATCH 794/2232] Merge pull request #275 from dtolnay/demo


Combine demo into one root directory
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 55431b6..315bac2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,7 +34,7 @@ jobs:
       - uses: dtolnay/rust-toolchain@master
         with:
           toolchain: ${{matrix.rust}}
-      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
 
   msrv:
@@ -43,7 +43,7 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@1.42.0
-      - run: cargo run --manifest-path demo-rs/Cargo.toml
+      - run: cargo run --manifest-path demo/Cargo.toml
 
   buck:
     name: Buck
@@ -66,7 +66,7 @@ jobs:
           cp third-party/Cargo.lock .
           cargo vendor --versioned-dirs --locked third-party/vendor
       - run: buck build :cxx#check --verbose=0
-      - run: buck run demo-rs --verbose=0
+      - run: buck run demo --verbose=0
       - run: buck test ... --verbose=0
 
   bazel:
@@ -84,5 +84,5 @@ jobs:
         run: |
           cp third-party/Cargo.lock .
           cargo vendor --versioned-dirs --locked third-party/vendor
-      - run: bazel run demo-rs --verbose_failures --noshow_progress
+      - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
diff --git a/Cargo.toml b/Cargo.toml
index 5458398..c950d2e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
 readme = "README.md"
-exclude = ["/demo-cxx", "/gen", "/syntax", "/third-party"]
+exclude = ["/demo", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi", "api-bindings"]
 
@@ -34,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo-rs", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
+members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/README.md b/README.md
index 345ce7d..9c65df6 100644
--- a/README.md
+++ b/README.md
@@ -60,9 +60,8 @@ function calls Rust's `len()`.
 
 ## Example
 
-A runnable version of this example is provided under the *demo-rs* directory of
-this repo (with the C++ side of the implementation in the *demo-cxx* directory).
-To try it out, jump into demo-rs and run `cargo run`.
+A runnable version of this example is provided under the *demo* directory of
+this repo. To try it out, run `cargo run` from that directory.
 
 ```rust
 #[cxx::bridge]
@@ -78,7 +77,7 @@ mod ffi {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
-        include!("demo-cxx/demo.h");
+        include!("demo/include/demo.h");
 
         // Zero or more opaque types which both languages can pass around but
         // only C++ can see the fields.
@@ -107,10 +106,10 @@ get to call back and forth safely.
 
 Here are links to the complete set of source files involved in the demo:
 
-- [demo-rs/src/main.rs](demo-rs/src/main.rs)
-- [demo-rs/build.rs](demo-rs/build.rs)
-- [demo-cxx/demo.h](demo-cxx/demo.h)
-- [demo-cxx/demo.cc](demo-cxx/demo.cc)
+- [demo/src/main.rs](demo/src/main.rs)
+- [demo/build.rs](demo/build.rs)
+- [demo/include/demo.h](demo/include/demo.h)
+- [demo/src/demo.cc](demo/src/demo.cc)
 
 To look at the code generated in both languages for the example by the CXX code
 generators:
@@ -118,10 +117,10 @@ generators:
 ```console
    # run Rust code generator and print to stdout
    # (requires https://github.com/dtolnay/cargo-expand)
-$ cargo expand --manifest-path demo-rs/Cargo.toml
+$ cargo expand --manifest-path demo/Cargo.toml
 
    # run C++ code generator and print to stdout
-$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
+$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
 ```
 
 <br>
@@ -228,13 +227,13 @@ cxx-build = "0.3"
 
 fn main() {
     cxx_build::bridge("src/main.rs")  // returns a cc::Build
-        .file("../demo-cxx/demo.cc")
+        .file("src/demo.cc")
         .flag_if_supported("-std=c++11")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
 }
 ```
 
diff --git a/demo-cxx/BUCK b/demo-cxx/BUCK
deleted file mode 100644
index f60200b..0000000
--- a/demo-cxx/BUCK
+++ /dev/null
@@ -1,17 +0,0 @@
-cxx_library(
-    name = "demo-cxx",
-    srcs = ["demo.cc"],
-    compiler_flags = ["-std=c++14"],
-    visibility = ["PUBLIC"],
-    deps = [
-        ":include",
-        "//demo-rs:include",
-    ],
-)
-
-cxx_library(
-    name = "include",
-    exported_headers = ["demo.h"],
-    visibility = ["PUBLIC"],
-    deps = ["//:core"],
-)
diff --git a/demo-cxx/BUILD b/demo-cxx/BUILD
deleted file mode 100644
index 7b1860a..0000000
--- a/demo-cxx/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-cc_library(
-    name = "demo-cxx",
-    srcs = ["demo.cc"],
-    copts = ["-std=c++14"],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":include",
-        "//demo-rs:include",
-    ],
-)
-
-cc_library(
-    name = "include",
-    hdrs = ["demo.h"],
-    visibility = ["//visibility:public"],
-    deps = ["//:core"],
-)
diff --git a/demo-cxx/demo.cc b/demo-cxx/demo.cc
deleted file mode 100644
index 21bdad4..0000000
--- a/demo-cxx/demo.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "demo-cxx/demo.h"
-#include "demo-rs/src/main.rs.h"
-#include <iostream>
-
-namespace org {
-namespace example {
-
-ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
-
-ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::make_unique<ThingC>(std::string(appname));
-}
-
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
-void do_thing(SharedThing state) { print_r(*state.y); }
-
-} // namespace example
-} // namespace org
diff --git a/demo-cxx/demo.h b/demo-cxx/demo.h
deleted file mode 100644
index fafc474..0000000
--- a/demo-cxx/demo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-#include "rust/cxx.h"
-#include <memory>
-#include <string>
-
-namespace org {
-namespace example {
-
-class ThingC {
-public:
-  ThingC(std::string appname);
-  ~ThingC();
-
-  std::string appname;
-};
-
-struct SharedThing;
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
-
-} // namespace example
-} // namespace org
diff --git a/demo-rs/BUCK b/demo-rs/BUCK
deleted file mode 100644
index a3f460b..0000000
--- a/demo-rs/BUCK
+++ /dev/null
@@ -1,42 +0,0 @@
-rust_binary(
-    name = "demo-rs",
-    srcs = glob(["src/**"]),
-    deps = [
-        ":gen",
-        "//:cxx",
-        "//demo-cxx:demo-cxx",
-    ],
-)
-
-cxx_library(
-    name = "gen",
-    srcs = [":gen-source"],
-    deps = [
-        ":include",
-        "//demo-cxx:include",
-    ],
-)
-
-genrule(
-    name = "gen-header",
-    srcs = ["src/main.rs"],
-    out = "generated.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-genrule(
-    name = "gen-source",
-    srcs = ["src/main.rs"],
-    out = "generated.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-cxx_library(
-    name = "include",
-    exported_headers = {
-        "src/main.rs.h": ":gen-header",
-    },
-    visibility = ["PUBLIC"],
-)
diff --git a/demo-rs/BUILD b/demo-rs/BUILD
deleted file mode 100644
index e3ebb96..0000000
--- a/demo-rs/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
-
-rust_binary(
-    name = "demo-rs",
-    srcs = glob(["src/**"]),
-    deps = [
-        ":gen",
-        "//:cxx",
-        "//demo-cxx",
-    ],
-)
-
-cc_library(
-    name = "gen",
-    srcs = [":gen-source"],
-    deps = [
-        ":include",
-        "//demo-cxx:include",
-    ],
-)
-
-genrule(
-    name = "gen-header",
-    srcs = ["src/main.rs"],
-    outs = ["main.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "gen-source",
-    srcs = ["src/main.rs"],
-    outs = ["generated.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
-    include_prefix = "demo-rs/src",
-    visibility = ["//visibility:public"],
-)
diff --git a/demo-rs/Cargo.toml b/demo-rs/Cargo.toml
deleted file mode 100644
index d2147ab..0000000
--- a/demo-rs/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "cxxbridge-demo"
-version = "0.0.0"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-publish = false
-
-[dependencies]
-cxx = { path = ".." }
-
-[build-dependencies]
-cxx-build = { path = "../gen/build" }
diff --git a/demo-rs/build.rs b/demo-rs/build.rs
deleted file mode 100644
index f32b8ef..0000000
--- a/demo-rs/build.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    cxx_build::bridge("src/main.rs")
-        .file("../demo-cxx/demo.cc")
-        .flag_if_supported("-std=c++14")
-        .compile("cxxbridge-demo");
-
-    println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-    println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
-}
diff --git a/demo-rs/src/main.rs b/demo-rs/src/main.rs
deleted file mode 100644
index 66dfc79..0000000
--- a/demo-rs/src/main.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#[cxx::bridge(namespace = org::example)]
-mod ffi {
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
-    }
-
-    extern "C" {
-        include!("demo-cxx/demo.h");
-
-        type ThingC;
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
-    }
-
-    extern "Rust" {
-        type ThingR;
-        fn print_r(r: &ThingR);
-    }
-}
-
-pub struct ThingR(usize);
-
-fn print_r(r: &ThingR) {
-    println!("called back with r={}", r.0);
-}
-
-fn main() {
-    let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
-
-    ffi::do_thing(ffi::SharedThing {
-        z: 222,
-        y: Box::new(ThingR(333)),
-        x,
-    });
-}
diff --git a/demo/BUCK b/demo/BUCK
new file mode 100644
index 0000000..78e75e6
--- /dev/null
+++ b/demo/BUCK
@@ -0,0 +1,57 @@
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":demo-sys",
+        ":gen",
+        "//:cxx",
+    ],
+)
+
+cxx_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    out = "generated.h",
+    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    out = "generated.cc",
+    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+    type = "cxxbridge",
+)
+
+cxx_library(
+    name = "include",
+    exported_headers = {
+        "src/main.rs.h": ":gen-header",
+    },
+)
+
+cxx_library(
+    name = "demo-sys",
+    srcs = ["src/demo.cc"],
+    compiler_flags = ["-std=c++14"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+cxx_library(
+    name = "demo-include",
+    exported_headers = ["include/demo.h"],
+    deps = ["//:core"],
+)
diff --git a/demo/BUILD b/demo/BUILD
new file mode 100644
index 0000000..1edc65c
--- /dev/null
+++ b/demo/BUILD
@@ -0,0 +1,58 @@
+load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
+
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":demo-sys",
+        ":gen",
+        "//:cxx",
+    ],
+)
+
+cc_library(
+    name = "gen",
+    srcs = [":gen-source"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+genrule(
+    name = "gen-header",
+    srcs = ["src/main.rs"],
+    outs = ["main.rs.h"],
+    cmd = "$(location //:codegen) --header $< > $@",
+    tools = ["//:codegen"],
+)
+
+genrule(
+    name = "gen-source",
+    srcs = ["src/main.rs"],
+    outs = ["generated.cc"],
+    cmd = "$(location //:codegen) $< > $@",
+    tools = ["//:codegen"],
+)
+
+cc_library(
+    name = "include",
+    hdrs = [":gen-header"],
+    include_prefix = "demo/src",
+)
+
+cc_library(
+    name = "demo-sys",
+    srcs = ["src/demo.cc"],
+    copts = ["-std=c++14"],
+    deps = [
+        ":demo-include",
+        ":include",
+    ],
+)
+
+cc_library(
+    name = "demo-include",
+    hdrs = ["include/demo.h"],
+    deps = ["//:core"],
+)
diff --git a/demo/Cargo.toml b/demo/Cargo.toml
new file mode 100644
index 0000000..d2147ab
--- /dev/null
+++ b/demo/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "cxxbridge-demo"
+version = "0.0.0"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+publish = false
+
+[dependencies]
+cxx = { path = ".." }
+
+[build-dependencies]
+cxx-build = { path = "../gen/build" }
diff --git a/demo/build.rs b/demo/build.rs
new file mode 100644
index 0000000..a3c31b3
--- /dev/null
+++ b/demo/build.rs
@@ -0,0 +1,10 @@
+fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/demo.cc")
+        .flag_if_supported("-std=c++14")
+        .compile("cxxbridge-demo");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
+}
diff --git a/demo/include/demo.h b/demo/include/demo.h
new file mode 100644
index 0000000..fafc474
--- /dev/null
+++ b/demo/include/demo.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "rust/cxx.h"
+#include <memory>
+#include <string>
+
+namespace org {
+namespace example {
+
+class ThingC {
+public:
+  ThingC(std::string appname);
+  ~ThingC();
+
+  std::string appname;
+};
+
+struct SharedThing;
+
+std::unique_ptr<ThingC> make_demo(rust::Str appname);
+const std::string &get_name(const ThingC &thing);
+void do_thing(SharedThing state);
+
+} // namespace example
+} // namespace org
diff --git a/demo/src/demo.cc b/demo/src/demo.cc
new file mode 100644
index 0000000..79c693f
--- /dev/null
+++ b/demo/src/demo.cc
@@ -0,0 +1,21 @@
+#include "demo/include/demo.h"
+#include "demo/src/main.rs.h"
+#include <iostream>
+
+namespace org {
+namespace example {
+
+ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
+
+ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
+
+std::unique_ptr<ThingC> make_demo(rust::Str appname) {
+  return std::make_unique<ThingC>(std::string(appname));
+}
+
+const std::string &get_name(const ThingC &thing) { return thing.appname; }
+
+void do_thing(SharedThing state) { print_r(*state.y); }
+
+} // namespace example
+} // namespace org
diff --git a/demo/src/main.rs b/demo/src/main.rs
new file mode 100644
index 0000000..ee7e093
--- /dev/null
+++ b/demo/src/main.rs
@@ -0,0 +1,39 @@
+#[cxx::bridge(namespace = org::example)]
+mod ffi {
+    struct SharedThing {
+        z: i32,
+        y: Box<ThingR>,
+        x: UniquePtr<ThingC>,
+    }
+
+    extern "C" {
+        include!("demo/include/demo.h");
+
+        type ThingC;
+        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
+        fn get_name(thing: &ThingC) -> &CxxString;
+        fn do_thing(state: SharedThing);
+    }
+
+    extern "Rust" {
+        type ThingR;
+        fn print_r(r: &ThingR);
+    }
+}
+
+pub struct ThingR(usize);
+
+fn print_r(r: &ThingR) {
+    println!("called back with r={}", r.0);
+}
+
+fn main() {
+    let x = ffi::make_demo("demo of cxx::bridge");
+    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
+
+    ffi::do_thing(ffi::SharedThing {
+        z: 222,
+        y: Box::new(ThingR(333)),
+        x,
+    });
+}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 2560aee..768de15 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -15,18 +15,18 @@
 //!
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")
-//!         .file("../demo-cxx/demo.cc")
+//!         .file("src/demo.cc")
 //!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//!     println!("cargo:rerun-if-changed=src/demo.cc");
+//!     println!("cargo:rerun-if-changed=include/demo.h");
 //! }
 //! ```
 //!
-//! A runnable working setup with this build script is shown in the
-//! *demo-rs* and *demo-cxx* directories of [https://github.com/dtolnay/cxx].
+//! A runnable working setup with this build script is shown in the *demo*
+//! directory of [https://github.com/dtolnay/cxx].
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 //!
@@ -83,7 +83,7 @@ pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
 /// ```no_run
 /// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
 /// cxx_build::bridges(source_files)
-///     .file("../demo-cxx/demo.cc")
+///     .file("src/demo.cc")
 ///     .flag_if_supported("-std=c++11")
 ///     .compile("cxxbridge-demo");
 /// ```
diff --git a/src/lib.rs b/src/lib.rs
index a707338..94a9037 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,10 +57,9 @@
 //!
 //! # Example
 //!
-//! A runnable version of this example is provided under the *demo-rs* directory
-//! of [https://github.com/dtolnay/cxx] (with the C++ side of the implementation
-//! in the *demo-cxx* directory). To try it out, jump into demo-rs and run
-//! `cargo run`.
+//! A runnable version of this example is provided under the *demo* directory of
+//! [https://github.com/dtolnay/cxx]. To try it out, run `cargo run` from that
+//! directory.
 //!
 //! ```no_run
 //! #[cxx::bridge]
@@ -76,7 +75,7 @@
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
-//!         include!("demo-cxx/demo.h");
+//!         include!("demo/include/demo.h");
 //!
 //!         // Zero or more opaque types which both languages can pass around but
 //!         // only C++ can see the fields.
@@ -113,10 +112,10 @@
 //!
 //! Here are links to the complete set of source files involved in the demo:
 //!
-//! - [demo-rs/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/src/main.rs)
-//! - [demo-rs/build.rs](https://github.com/dtolnay/cxx/blob/master/demo-rs/build.rs)
-//! - [demo-cxx/demo.h](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.h)
-//! - [demo-cxx/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo-cxx/demo.cc)
+//! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
+//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
+//! - [demo/include/demo.h](https://github.com/dtolnay/cxx/blob/master/demo/include/demo.h)
+//! - [demo/src/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/demo.cc)
 //!
 //! To look at the code generated in both languages for the example by the CXX
 //! code generators:
@@ -124,10 +123,10 @@
 //! ```console
 //!    # run Rust code generator and print to stdout
 //!    # (requires https://github.com/dtolnay/cargo-expand)
-//! $ cargo expand --manifest-path demo-rs/Cargo.toml
+//! $ cargo expand --manifest-path demo/Cargo.toml
 //!
 //!    # run C++ code generator and print to stdout
-//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo-rs/src/main.rs
+//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs
 //! ```
 //!
 //! <br>
@@ -237,13 +236,13 @@
 //!
 //! fn main() {
 //!     cxx_build::bridge("src/main.rs")  // returns a cc::Build
-//!         .file("../demo-cxx/demo.cc")
+//!         .file("src/demo.cc")
 //!         .flag_if_supported("-std=c++11")
 //!         .compile("cxxbridge-demo");
 //!
 //!     println!("cargo:rerun-if-changed=src/main.rs");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.h");
-//!     println!("cargo:rerun-if-changed=../demo-cxx/demo.cc");
+//!     println!("cargo:rerun-if-changed=src/demo.cc");
+//!     println!("cargo:rerun-if-changed=include/demo.h");
 //! }
 //! ```
 //!

From bcc0a1c9f943401d58e9ee9111958ab242279cfc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:09:08 +0000
Subject: [PATCH 795/2232] Release 0.3.9


---

diff --git a/Cargo.toml b/Cargo.toml
index c950d2e..5e6fe27 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.8" # remember to update html_root_url
+version = "0.3.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge03"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.8", path = "macro" }
+cxxbridge-macro = { version = "=0.3.9", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.3.8", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.3.9", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.8", path = "gen/build" }
+cxx-build = { version = "=0.3.9", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 061237a..5bff819 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.3.8"
+version = "0.3.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 2e536f7..eed5281 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.8"
+version = "0.3.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index a49e22f..68ec3ec 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.8"
+version = "0.3.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index aabd4d1..b273229 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.8"
+version = "0.3.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 94a9037..bbd79f3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.8")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.3.9")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 268c9f4..1f3e760 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.8"
+version = "0.3.9"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.8"
+version = "0.3.9"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.8"
+version = "0.3.9"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -124,11 +124,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.3.8"
+version = "0.3.9"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.8"
+version = "0.3.9"
 dependencies = [
  "cxx",
  "proc-macro2",

From 97b69c66753f66ab671eb785c32ee6599a4ee53a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:13:21 +0000
Subject: [PATCH 796/2232] Ignore or_fun_call lint


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 768de15..5c0f12a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -49,6 +49,7 @@
     clippy::inherent_to_string,
     clippy::needless_doctest_main,
     clippy::new_without_default,
+    clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index c5cc396..14b75e6 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -3,6 +3,7 @@
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
+    clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
 

From b6614db28b1c81ec2e9c980ec541720c3d53cad7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:17:48 +0000
Subject: [PATCH 797/2232] Add symlink_dir to fs lib


To be used in cxx-build refactor.

---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 82cb5cc..c554ef0 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -105,7 +105,7 @@ fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
 }
 
 #[cfg(unix)]
-use self::fs::symlink as symlink_or_copy;
+use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
 fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index d1b0b70..77488f8 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -82,11 +82,12 @@ pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
     }
 }
 
-#[cfg(unix)]
-pub(crate) fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
-    let src = src.as_ref();
-    let dst = dst.as_ref();
-    match std::os::unix::fs::symlink(src, dst) {
+fn symlink<'a>(
+    src: &'a Path,
+    dst: &'a Path,
+    fun: fn(&'a Path, &'a Path) -> io::Result<()>,
+) -> Result<()> {
+    match fun(src, dst) {
         Ok(()) => Ok(()),
         Err(e) => err!(
             e,
@@ -97,19 +98,31 @@ pub(crate) fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()
     }
 }
 
+#[cfg(unix)]
+#[allow(unused_imports)]
+pub(crate) use self::symlink_file as symlink_dir;
+
+#[cfg(unix)]
+pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    symlink(src.as_ref(), dst.as_ref(), std::os::unix::fs::symlink)
+}
+
 #[cfg(windows)]
 pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
-    let src = src.as_ref();
-    let dst = dst.as_ref();
-    match std::os::windows::fs::symlink_file(src, dst) {
-        Ok(()) => Ok(()),
-        Err(e) => err!(
-            e,
-            "Failed to create symlink `{}` pointing to `{}`",
-            dst,
-            src,
-        ),
-    }
+    symlink(
+        src.as_ref(),
+        dst.as_ref(),
+        std::os::windows::fs::symlink_file,
+    )
+}
+
+#[cfg(windows)]
+pub(crate) fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    symlink(
+        src.as_ref(),
+        dst.as_ref(),
+        std::os::windows::fs::symlink_dir,
+    )
 }
 
 pub(crate) fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> Result<()> {

From 7ac98fa9726adfb051fda2822c04ebc7e4892d16 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:16 +0000
Subject: [PATCH 798/2232] Introduce newtype for target dir


I plan to cache the target dir determination, which will require passing
it around somewhat more in function arguments. Having a unique type will
make that less error prone.

---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 91f229d..3bddc6e 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -1,9 +1,10 @@
 use crate::error::TargetDirError;
+use crate::paths::TargetDir;
 use std::path::PathBuf;
 use std::process::Command;
 use std::str;
 
-pub(crate) fn target_dir() -> Result<PathBuf, TargetDirError> {
+pub(crate) fn target_dir() -> Result<TargetDir, TargetDirError> {
     let cargo = option_env!("CARGO").unwrap_or("cargo");
     let output = Command::new(cargo)
         .arg("metadata")
@@ -24,7 +25,7 @@ pub(crate) fn target_dir() -> Result<PathBuf, TargetDirError> {
         let close_quote_index = metadata.find('"')?;
         let string = &metadata[..close_quote_index];
         let target_directory = string.replace("\\\\", "\\");
-        Some(PathBuf::from(target_directory))
+        Some(TargetDir(PathBuf::from(target_directory)))
     })()
     .ok_or(TargetDirError::NotFound)
 }
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index c554ef0..e6b29bd 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -2,8 +2,18 @@ use crate::cargo;
 use crate::error::{Error, Result};
 use crate::gen::fs;
 use std::env;
+use std::ops::Deref;
 use std::path::{Path, PathBuf};
 
+pub(crate) struct TargetDir(pub PathBuf);
+
+impl Deref for TargetDir {
+    type Target = Path;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
 fn out_dir() -> Result<PathBuf> {
     env::var_os("OUT_DIR")
         .map(PathBuf::from)
@@ -72,7 +82,7 @@ pub(crate) fn include_dir() -> Result<PathBuf> {
     Ok(target_dir.join("cxxbridge"))
 }
 
-fn target_dir() -> Result<PathBuf> {
+fn target_dir() -> Result<TargetDir> {
     let fallback_err = match cargo::target_dir() {
         Ok(target_dir) => return Ok(target_dir),
         Err(err) => Error::TargetDir(err),
@@ -82,7 +92,7 @@ fn target_dir() -> Result<PathBuf> {
     let mut dir = out_dir().and_then(canonicalize)?;
     loop {
         if dir.ends_with("target") {
-            return Ok(dir);
+            return Ok(TargetDir(dir));
         }
         if !dir.pop() {
             return Err(fallback_err);

From cad9ff6c9e98431658d0797ae29c4ef004584357 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 799/2232] Cache computation of target directory


Previously we would be repeating at least 7 successive Cargo invocation.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 5c0f12a..eea9e68 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -62,6 +62,7 @@ mod syntax;
 use crate::error::Result;
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
+use crate::paths::TargetDir;
 use cc::Build;
 use std::io::{self, Write};
 use std::iter;
@@ -98,34 +99,39 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let mut build = paths::cc_build();
+    let ref target_dir = paths::target_dir()?;
+    let mut build = paths::cc_build(target_dir);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    write_header()?;
+    write_header(target_dir)?;
 
     for path in rust_source_files {
-        generate_bridge(&mut build, path.as_ref())?;
+        generate_bridge(&mut build, path.as_ref(), target_dir)?;
     }
 
     Ok(build)
 }
 
-fn write_header() -> Result<()> {
-    let ref cxx_h = paths::include_dir()?.join("rust").join("cxx.h");
+fn write_header(target_dir: &TargetDir) -> Result<()> {
+    let ref cxx_h = paths::include_dir(target_dir)?.join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
     Ok(())
 }
 
-fn generate_bridge(build: &mut Build, rust_source_file: &Path) -> Result<()> {
+fn generate_bridge(
+    build: &mut Build,
+    rust_source_file: &Path,
+    target_dir: &TargetDir,
+) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
 
-    let header_path = paths::out_with_extension(rust_source_file, ".h")?;
+    let header_path = paths::out_with_extension(rust_source_file, ".h", target_dir)?;
     fs::create_dir_all(header_path.parent().unwrap())?;
     write(&header_path, &generated.header)?;
-    paths::symlink_header(&header_path, rust_source_file);
+    paths::symlink_header(&header_path, rust_source_file, target_dir);
 
-    let implementation_path = paths::out_with_extension(rust_source_file, ".cc")?;
+    let implementation_path = paths::out_with_extension(rust_source_file, ".cc", target_dir)?;
     write(&implementation_path, &generated.implementation)?;
     build.file(&implementation_path);
     Ok(())
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index e6b29bd..3f4814e 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -20,26 +20,26 @@ fn out_dir() -> Result<PathBuf> {
         .ok_or(Error::MissingOutDir)
 }
 
-pub(crate) fn cc_build() -> cc::Build {
-    try_cc_build().unwrap_or_default()
+pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
+    try_cc_build(target_dir).unwrap_or_default()
 }
 
-fn try_cc_build() -> Result<cc::Build> {
+fn try_cc_build(target_dir: &TargetDir) -> Result<cc::Build> {
     let mut build = cc::Build::new();
-    build.include(include_dir()?);
-    build.include(target_dir()?.parent().unwrap());
+    build.include(include_dir(target_dir)?);
+    build.include(target_dir.parent().unwrap());
     Ok(build)
 }
 
 // Symlink the header file into a predictable place. The header generated from
 // path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(path: &Path, original: &Path) {
-    let _ = try_symlink_header(path, original);
+pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
+    let _ = try_symlink_header(path, original, target_dir);
 }
 
-fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(original)?;
-    let ref dst = include_dir()?.join(suffix);
+fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
+    let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
+    let ref dst = include_dir(target_dir)?.join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
@@ -53,8 +53,7 @@ fn try_symlink_header(path: &Path, original: &Path) -> Result<()> {
     Ok(())
 }
 
-fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
-    let target_dir = target_dir()?;
+fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
     let mut outer = target_dir.parent().unwrap();
     let original = canonicalize(original)?;
     loop {
@@ -68,21 +67,24 @@ fn relative_to_parent_of_target_dir(original: &Path) -> Result<PathBuf> {
     }
 }
 
-pub(crate) fn out_with_extension(path: &Path, ext: &str) -> Result<PathBuf> {
+pub(crate) fn out_with_extension(
+    path: &Path,
+    ext: &str,
+    target_dir: &TargetDir,
+) -> Result<PathBuf> {
     let mut file_name = path.file_name().unwrap().to_owned();
     file_name.push(ext);
 
     let out_dir = out_dir()?;
-    let rel = relative_to_parent_of_target_dir(path)?;
+    let rel = relative_to_parent_of_target_dir(path, target_dir)?;
     Ok(out_dir.join(rel).with_file_name(file_name))
 }
 
-pub(crate) fn include_dir() -> Result<PathBuf> {
-    let target_dir = target_dir()?;
+pub(crate) fn include_dir(target_dir: &TargetDir) -> Result<PathBuf> {
     Ok(target_dir.join("cxxbridge"))
 }
 
-fn target_dir() -> Result<TargetDir> {
+pub(crate) fn target_dir() -> Result<TargetDir> {
     let fallback_err = match cargo::target_dir() {
         Ok(target_dir) => return Ok(target_dir),
         Err(err) => Error::TargetDir(err),

From 4057e8ea212a7858ab11756ea6d51d70d2bf3878 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 800/2232] Include dir can be infallible


Enabled by the target dir refactor.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index eea9e68..15a4348 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -113,7 +113,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 }
 
 fn write_header(target_dir: &TargetDir) -> Result<()> {
-    let ref cxx_h = paths::include_dir(target_dir)?.join("rust").join("cxx.h");
+    let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
     Ok(())
 }
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 3f4814e..6bc3e8a 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -26,7 +26,7 @@ pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
 
 fn try_cc_build(target_dir: &TargetDir) -> Result<cc::Build> {
     let mut build = cc::Build::new();
-    build.include(include_dir(target_dir)?);
+    build.include(include_dir(target_dir));
     build.include(target_dir.parent().unwrap());
     Ok(build)
 }
@@ -39,7 +39,7 @@ pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDi
 
 fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
     let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
-    let ref dst = include_dir(target_dir)?.join(suffix);
+    let ref dst = include_dir(target_dir).join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
@@ -80,8 +80,8 @@ pub(crate) fn out_with_extension(
     Ok(out_dir.join(rel).with_file_name(file_name))
 }
 
-pub(crate) fn include_dir(target_dir: &TargetDir) -> Result<PathBuf> {
-    Ok(target_dir.join("cxxbridge"))
+pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
+    target_dir.join("cxxbridge")
 }
 
 pub(crate) fn target_dir() -> Result<TargetDir> {

From 28241a0d362ad9ab326f52e760428ae39f4e453b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 801/2232] Move cargo based logic out of paths module


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 22f53f6..2f94426 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,7 +59,7 @@ mod gen;
 mod paths;
 mod syntax;
 
-use crate::error::Result;
+use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
 use crate::paths::TargetDir;
@@ -99,7 +99,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let ref target_dir = paths::target_dir()?;
+    let ref target_dir = target_dir()?;
     let mut build = paths::cc_build(target_dir);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
@@ -151,3 +151,16 @@ fn write(path: &Path, content: &[u8]) -> Result<()> {
     fs::write(path, content)?;
     Ok(())
 }
+
+fn target_dir() -> Result<TargetDir> {
+    let fallback_err = match cargo::target_dir() {
+        Ok(target_dir) => return Ok(target_dir),
+        Err(err) => Error::TargetDir(err),
+    };
+
+    // Fallback if Cargo did not work.
+    match paths::search_parents_for_target_dir() {
+        Some(target_dir) => Ok(target_dir),
+        None => Err(fallback_err),
+    }
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 870c49d..47a28a0 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,4 +1,3 @@
-use crate::cargo;
 use crate::error::{Error, Result};
 use crate::gen::fs;
 use std::env;
@@ -80,20 +79,14 @@ pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
     target_dir.join("cxxbridge")
 }
 
-pub(crate) fn target_dir() -> Result<TargetDir> {
-    let fallback_err = match cargo::target_dir() {
-        Ok(target_dir) => return Ok(target_dir),
-        Err(err) => Error::TargetDir(err),
-    };
-
-    // Fallback if Cargo did not work.
-    let mut dir = out_dir().and_then(canonicalize)?;
+pub(crate) fn search_parents_for_target_dir() -> Option<TargetDir> {
+    let mut dir = out_dir().and_then(canonicalize).ok()?;
     loop {
         if dir.ends_with("target") {
-            return Ok(TargetDir(dir));
+            return Some(TargetDir(dir));
         }
         if !dir.pop() {
-            return Err(fallback_err);
+            return None;
         }
     }
 }

From 58c5b150d329f94f3919075d588149715fd416ab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 802/2232] Construction of cc build can be infallible


Enabled by the target dir refactor.

---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 6bc3e8a..870c49d 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -21,14 +21,10 @@ fn out_dir() -> Result<PathBuf> {
 }
 
 pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
-    try_cc_build(target_dir).unwrap_or_default()
-}
-
-fn try_cc_build(target_dir: &TargetDir) -> Result<cc::Build> {
     let mut build = cc::Build::new();
     build.include(include_dir(target_dir));
     build.include(target_dir.parent().unwrap());
-    Ok(build)
+    build
 }
 
 // Symlink the header file into a predictable place. The header generated from

From 073dbf58ea2a8d019ae075cfa41e87d9de047630 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 803/2232] Continue if target dir not found


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 3bddc6e..6a4f1a6 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -1,19 +1,18 @@
-use crate::error::TargetDirError;
 use crate::paths::TargetDir;
 use std::path::PathBuf;
 use std::process::Command;
 use std::str;
 
-pub(crate) fn target_dir() -> Result<TargetDir, TargetDirError> {
-    let cargo = option_env!("CARGO").unwrap_or("cargo");
-    let output = Command::new(cargo)
-        .arg("metadata")
-        .arg("--no-deps")
-        .arg("--format-version=1")
-        .output()
-        .map_err(TargetDirError::Io)?;
-
+pub(crate) fn target_dir() -> TargetDir {
     (|| {
+        let cargo = option_env!("CARGO").unwrap_or("cargo");
+        let output = Command::new(cargo)
+            .arg("metadata")
+            .arg("--no-deps")
+            .arg("--format-version=1")
+            .output()
+            .ok()?;
+
         // Cargo only outputs utf8 encoded JSON.
         let mut metadata = str::from_utf8(&output.stdout).ok()?;
 
@@ -25,7 +24,7 @@ pub(crate) fn target_dir() -> Result<TargetDir, TargetDirError> {
         let close_quote_index = metadata.find('"')?;
         let string = &metadata[..close_quote_index];
         let target_directory = string.replace("\\\\", "\\");
-        Some(TargetDir(PathBuf::from(target_directory)))
+        Some(TargetDir::Path(PathBuf::from(target_directory)))
     })()
-    .ok_or(TargetDirError::NotFound)
+    .unwrap_or(TargetDir::Unknown)
 }
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index ed4c6af..0ed4d74 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,28 +1,19 @@
 use crate::gen::fs;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub(super) enum Error {
     MissingOutDir,
-    TargetDir(TargetDirError),
     Fs(fs::Error),
 }
 
-#[derive(Debug)]
-pub(crate) enum TargetDirError {
-    Io(io::Error),
-    NotFound,
-}
-
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
-            Error::TargetDir(_) => write!(f, "unable to identify target dir"),
             Error::Fs(err) => err.fmt(f),
         }
     }
@@ -31,10 +22,6 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::TargetDir(err) => match err {
-                TargetDirError::Io(err) => Some(err),
-                TargetDirError::NotFound => None,
-            },
             Error::Fs(err) => err.source(),
             _ => None,
         }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 2f94426..111f592 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,7 +59,7 @@ mod gen;
 mod paths;
 mod syntax;
 
-use crate::error::{Error, Result};
+use crate::error::Result;
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
 use crate::paths::TargetDir;
@@ -99,7 +99,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let ref target_dir = target_dir()?;
+    let ref target_dir = target_dir();
     let mut build = paths::cc_build(target_dir);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
@@ -152,15 +152,10 @@ fn write(path: &Path, content: &[u8]) -> Result<()> {
     Ok(())
 }
 
-fn target_dir() -> Result<TargetDir> {
-    let fallback_err = match cargo::target_dir() {
-        Ok(target_dir) => return Ok(target_dir),
-        Err(err) => Error::TargetDir(err),
-    };
-
-    // Fallback if Cargo did not work.
-    match paths::search_parents_for_target_dir() {
-        Some(target_dir) => Ok(target_dir),
-        None => Err(fallback_err),
+fn target_dir() -> TargetDir {
+    match cargo::target_dir() {
+        target_dir @ TargetDir::Path(_) => target_dir,
+        // Fallback if Cargo did not work.
+        TargetDir::Unknown => paths::search_parents_for_target_dir(),
     }
 }
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 47a28a0..1814f82 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,16 +1,11 @@
 use crate::error::{Error, Result};
 use crate::gen::fs;
 use std::env;
-use std::ops::Deref;
 use std::path::{Path, PathBuf};
 
-pub(crate) struct TargetDir(pub PathBuf);
-
-impl Deref for TargetDir {
-    type Target = Path;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
+pub(crate) enum TargetDir {
+    Path(PathBuf),
+    Unknown,
 }
 
 fn out_dir() -> Result<PathBuf> {
@@ -22,13 +17,18 @@ fn out_dir() -> Result<PathBuf> {
 pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
     let mut build = cc::Build::new();
     build.include(include_dir(target_dir));
-    build.include(target_dir.parent().unwrap());
+    if let TargetDir::Path(target_dir) = target_dir {
+        build.include(target_dir.parent().unwrap());
+    }
     build
 }
 
 // Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
+// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
 pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
+    if let TargetDir::Unknown = target_dir {
+        return;
+    }
     let _ = try_symlink_header(path, original, target_dir);
 }
 
@@ -49,7 +49,10 @@ fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> R
 }
 
 fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
-    let mut outer = target_dir.parent().unwrap();
+    let mut outer = match target_dir {
+        TargetDir::Path(target_dir) => target_dir.parent().unwrap(),
+        TargetDir::Unknown => unimplemented!(), // FIXME
+    };
     let original = canonicalize(original)?;
     loop {
         if let Ok(suffix) = original.strip_prefix(outer) {
@@ -76,17 +79,23 @@ pub(crate) fn out_with_extension(
 }
 
 pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
-    target_dir.join("cxxbridge")
+    match target_dir {
+        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
+        TargetDir::Unknown => out_dir().unwrap().join("cxxbridge"), // FIXME no unwrap
+    }
 }
 
-pub(crate) fn search_parents_for_target_dir() -> Option<TargetDir> {
-    let mut dir = out_dir().and_then(canonicalize).ok()?;
+pub(crate) fn search_parents_for_target_dir() -> TargetDir {
+    let mut dir = match out_dir().and_then(canonicalize) {
+        Ok(dir) => dir,
+        Err(_) => return TargetDir::Unknown,
+    };
     loop {
         if dir.ends_with("target") {
-            return Some(TargetDir(dir));
+            return TargetDir::Path(dir);
         }
         if !dir.pop() {
-            return None;
+            return TargetDir::Unknown;
         }
     }
 }

From 7f4b3ca2f9b84fea9358b6187ae1dfe096a8b9f3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:18:17 +0000
Subject: [PATCH 804/2232] Write header can be infallible


Enabled by the target dir refactor.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 15a4348..22f53f6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -103,7 +103,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut build = paths::cc_build(target_dir);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    write_header(target_dir)?;
+    write_header(target_dir);
 
     for path in rust_source_files {
         generate_bridge(&mut build, path.as_ref(), target_dir)?;
@@ -112,10 +112,9 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     Ok(build)
 }
 
-fn write_header(target_dir: &TargetDir) -> Result<()> {
+fn write_header(target_dir: &TargetDir) {
     let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
-    Ok(())
 }
 
 fn generate_bridge(

From 8c0849a4f268b3f2fc6fd0d0d4ebf830583bbfd7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:38 +0000
Subject: [PATCH 805/2232] Keep target dir in Project struct


We'll put the OUT_DIR in here as well, to reduce the amount of code that
needs to be fallible.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 111f592..02df064 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -98,39 +98,51 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
     })
 }
 
+struct Project {
+    target_dir: TargetDir,
+}
+
+impl Project {
+    fn init() -> Self {
+        Project {
+            target_dir: match cargo::target_dir() {
+                target_dir @ TargetDir::Path(_) => target_dir,
+                // Fallback if Cargo did not work.
+                TargetDir::Unknown => paths::search_parents_for_target_dir(),
+            },
+        }
+    }
+}
+
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let ref target_dir = target_dir();
-    let mut build = paths::cc_build(target_dir);
+    let ref prj = Project::init();
+    let mut build = paths::cc_build(prj);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    write_header(target_dir);
+    write_header(prj);
 
     for path in rust_source_files {
-        generate_bridge(&mut build, path.as_ref(), target_dir)?;
+        generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
     Ok(build)
 }
 
-fn write_header(target_dir: &TargetDir) {
-    let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
+fn write_header(prj: &Project) {
+    let ref cxx_h = paths::include_dir(prj).join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
 }
 
-fn generate_bridge(
-    build: &mut Build,
-    rust_source_file: &Path,
-    target_dir: &TargetDir,
-) -> Result<()> {
+fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
 
-    let header_path = paths::out_with_extension(rust_source_file, ".h", target_dir)?;
+    let header_path = paths::out_with_extension(prj, rust_source_file, ".h")?;
     fs::create_dir_all(header_path.parent().unwrap())?;
     write(&header_path, &generated.header)?;
-    paths::symlink_header(&header_path, rust_source_file, target_dir);
+    paths::symlink_header(prj, &header_path, rust_source_file);
 
-    let implementation_path = paths::out_with_extension(rust_source_file, ".cc", target_dir)?;
+    let implementation_path = paths::out_with_extension(prj, rust_source_file, ".cc")?;
     write(&implementation_path, &generated.implementation)?;
     build.file(&implementation_path);
     Ok(())
@@ -151,11 +163,3 @@ fn write(path: &Path, content: &[u8]) -> Result<()> {
     fs::write(path, content)?;
     Ok(())
 }
-
-fn target_dir() -> TargetDir {
-    match cargo::target_dir() {
-        target_dir @ TargetDir::Path(_) => target_dir,
-        // Fallback if Cargo did not work.
-        TargetDir::Unknown => paths::search_parents_for_target_dir(),
-    }
-}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 1814f82..45df2a5 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,5 +1,6 @@
 use crate::error::{Error, Result};
 use crate::gen::fs;
+use crate::Project;
 use std::env;
 use std::path::{Path, PathBuf};
 
@@ -14,10 +15,10 @@ fn out_dir() -> Result<PathBuf> {
         .ok_or(Error::MissingOutDir)
 }
 
-pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
+pub(crate) fn cc_build(prj: &Project) -> cc::Build {
     let mut build = cc::Build::new();
-    build.include(include_dir(target_dir));
-    if let TargetDir::Path(target_dir) = target_dir {
+    build.include(include_dir(prj));
+    if let TargetDir::Path(target_dir) = &prj.target_dir {
         build.include(target_dir.parent().unwrap());
     }
     build
@@ -25,16 +26,16 @@ pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
 
 // Symlink the header file into a predictable place. The header generated from
 // path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
-    if let TargetDir::Unknown = target_dir {
+pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
+    if let TargetDir::Unknown = prj.target_dir {
         return;
     }
-    let _ = try_symlink_header(path, original, target_dir);
+    let _ = try_symlink_header(prj, path, original);
 }
 
-fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
-    let ref dst = include_dir(target_dir).join(suffix);
+fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
+    let suffix = relative_to_parent_of_target_dir(prj, original)?;
+    let ref dst = include_dir(prj).join(suffix);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
@@ -48,8 +49,8 @@ fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> R
     Ok(())
 }
 
-fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
-    let mut outer = match target_dir {
+fn relative_to_parent_of_target_dir(prj: &Project, original: &Path) -> Result<PathBuf> {
+    let mut outer = match &prj.target_dir {
         TargetDir::Path(target_dir) => target_dir.parent().unwrap(),
         TargetDir::Unknown => unimplemented!(), // FIXME
     };
@@ -65,21 +66,17 @@ fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> 
     }
 }
 
-pub(crate) fn out_with_extension(
-    path: &Path,
-    ext: &str,
-    target_dir: &TargetDir,
-) -> Result<PathBuf> {
+pub(crate) fn out_with_extension(prj: &Project, path: &Path, ext: &str) -> Result<PathBuf> {
     let mut file_name = path.file_name().unwrap().to_owned();
     file_name.push(ext);
 
     let out_dir = out_dir()?;
-    let rel = relative_to_parent_of_target_dir(path, target_dir)?;
+    let rel = relative_to_parent_of_target_dir(prj, path)?;
     Ok(out_dir.join(rel).with_file_name(file_name))
 }
 
-pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
-    match target_dir {
+pub(crate) fn include_dir(prj: &Project) -> PathBuf {
+    match &prj.target_dir {
         TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
         TargetDir::Unknown => out_dir().unwrap().join("cxxbridge"), // FIXME no unwrap
     }

From 502d4d407ea5a9287a61dbf78cc8a8cbe217076c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 806/2232] Include out dir in Project


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 02df064..0e77088 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -66,7 +66,7 @@ use crate::paths::TargetDir;
 use cc::Build;
 use std::io::{self, Write};
 use std::iter;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process;
 
 /// This returns a [`cc::Build`] on which you should continue to set up any
@@ -99,23 +99,29 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 struct Project {
+    out_dir: PathBuf,
     target_dir: TargetDir,
 }
 
 impl Project {
-    fn init() -> Self {
-        Project {
-            target_dir: match cargo::target_dir() {
-                target_dir @ TargetDir::Path(_) => target_dir,
-                // Fallback if Cargo did not work.
-                TargetDir::Unknown => paths::search_parents_for_target_dir(),
-            },
-        }
+    fn init() -> Result<Self> {
+        let out_dir = paths::out_dir()?;
+
+        let target_dir = match cargo::target_dir() {
+            target_dir @ TargetDir::Path(_) => target_dir,
+            // Fallback if Cargo did not work.
+            TargetDir::Unknown => paths::search_parents_for_target_dir(),
+        };
+
+        Ok(Project {
+            out_dir,
+            target_dir,
+        })
     }
 }
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let ref prj = Project::init();
+    let ref prj = Project::init()?;
     let mut build = paths::cc_build(prj);
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 45df2a5..47ceecc 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -9,7 +9,7 @@ pub(crate) enum TargetDir {
     Unknown,
 }
 
-fn out_dir() -> Result<PathBuf> {
+pub(crate) fn out_dir() -> Result<PathBuf> {
     env::var_os("OUT_DIR")
         .map(PathBuf::from)
         .ok_or(Error::MissingOutDir)

From bc2c8e1f4daa6f4c512a5d8d4563dd0009d0aa74 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 807/2232] Access out dir through project struct


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 0e77088..27f7a8d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -110,7 +110,7 @@ impl Project {
         let target_dir = match cargo::target_dir() {
             target_dir @ TargetDir::Path(_) => target_dir,
             // Fallback if Cargo did not work.
-            TargetDir::Unknown => paths::search_parents_for_target_dir(),
+            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
         };
 
         Ok(Project {
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 47ceecc..e49dddb 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -70,20 +70,19 @@ pub(crate) fn out_with_extension(prj: &Project, path: &Path, ext: &str) -> Resul
     let mut file_name = path.file_name().unwrap().to_owned();
     file_name.push(ext);
 
-    let out_dir = out_dir()?;
     let rel = relative_to_parent_of_target_dir(prj, path)?;
-    Ok(out_dir.join(rel).with_file_name(file_name))
+    Ok(prj.out_dir.join(rel).with_file_name(file_name))
 }
 
 pub(crate) fn include_dir(prj: &Project) -> PathBuf {
     match &prj.target_dir {
         TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
-        TargetDir::Unknown => out_dir().unwrap().join("cxxbridge"), // FIXME no unwrap
+        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
     }
 }
 
-pub(crate) fn search_parents_for_target_dir() -> TargetDir {
-    let mut dir = match out_dir().and_then(canonicalize) {
+pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
+    let mut dir = match out_dir.canonicalize() {
         Ok(dir) => dir,
         Err(_) => return TargetDir::Unknown,
     };

From ebe05fbd9188cdec78ed695497f08f0605505fac Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 808/2232] Remove redundant create_dir_all


This one is already handled by the following call to `write`.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 27f7a8d..5882191 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -144,7 +144,6 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let generated = gen::generate_from_path(rust_source_file, &opt);
 
     let header_path = paths::out_with_extension(prj, rust_source_file, ".h")?;
-    fs::create_dir_all(header_path.parent().unwrap())?;
     write(&header_path, &generated.header)?;
     paths::symlink_header(prj, &header_path, rust_source_file);
 

From 1bd7a7088b936e1f7feeedfb7a42920de61c0188 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 809/2232] Propagate create dir error if subsequent write fails


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 5882191..ef075c1 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,7 +59,7 @@ mod gen;
 mod paths;
 mod syntax;
 
-use crate::error::Result;
+use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
 use crate::paths::TargetDir;
@@ -154,6 +154,7 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
 }
 
 fn write(path: &Path, content: &[u8]) -> Result<()> {
+    let mut create_dir_error = None;
     if path.exists() {
         if let Ok(existing) = fs::read(path) {
             if existing == content {
@@ -163,8 +164,14 @@ fn write(path: &Path, content: &[u8]) -> Result<()> {
         }
         let _ = fs::remove_file(path);
     } else {
-        let _ = fs::create_dir_all(path.parent().unwrap());
+        let parent = path.parent().unwrap();
+        create_dir_error = fs::create_dir_all(parent).err();
+    }
+
+    match fs::write(path, content) {
+        // As long as write succeeded, ignore any create_dir_all error.
+        Ok(()) => Ok(()),
+        // If create_dir_all and write both failed, prefer the first error.
+        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
     }
-    fs::write(path, content)?;
-    Ok(())
 }

From b7ba747b5cd147a5ef6cd02eb59877b4352fbd3a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 810/2232] Only assume target dir if parent contains Cargo.toml


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index e49dddb..f05a927 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -87,7 +87,9 @@ pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
         Err(_) => return TargetDir::Unknown,
     };
     loop {
-        if dir.ends_with("target") {
+        let is_target = dir.ends_with("target");
+        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
+        if is_target && parent_contains_cargo_toml {
             return TargetDir::Path(dir);
         }
         if !dir.pop() {

From c0b3d9f055a91bc73fd541bc415e18a98fd46978 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 811/2232] Try finding target dir without canonicalize


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index f05a927..0145a38 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -82,19 +82,25 @@ pub(crate) fn include_dir(prj: &Project) -> PathBuf {
 }
 
 pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
-    let mut dir = match out_dir.canonicalize() {
-        Ok(dir) => dir,
-        Err(_) => return TargetDir::Unknown,
-    };
+    let mut dir = out_dir.to_owned();
+    let mut also_try_canonical = true;
     loop {
         let is_target = dir.ends_with("target");
         let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
         if is_target && parent_contains_cargo_toml {
             return TargetDir::Path(dir);
         }
-        if !dir.pop() {
-            return TargetDir::Unknown;
+        if dir.pop() {
+            continue;
+        }
+        if also_try_canonical {
+            if let Ok(canonical_dir) = out_dir.canonicalize() {
+                dir = canonical_dir;
+                also_try_canonical = false;
+                continue;
+            }
         }
+        return TargetDir::Unknown;
     }
 }
 

From 8079aa11cfaed5688d2a0bc9f4fdf1bb6c15c96a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 812/2232] Don't try canonicalize on windows


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 0145a38..f8b1ee9 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -82,8 +82,13 @@ pub(crate) fn include_dir(prj: &Project) -> PathBuf {
 }
 
 pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
+    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
+    // handle in includes.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    let mut also_try_canonical = cfg!(not(windows));
+
     let mut dir = out_dir.to_owned();
-    let mut also_try_canonical = true;
     loop {
         let is_target = dir.ends_with("target");
         let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();

From db44775d301868cb450ee74132df25ce522a04b8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:39 +0000
Subject: [PATCH 813/2232] Use relative paths as provided by caller's build.rs


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ef075c1..bdaf4f6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -143,11 +143,11 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
 
-    let header_path = paths::out_with_extension(prj, rust_source_file, ".h")?;
+    let header_path = paths::out_with_extension(prj, rust_source_file, ".h");
     write(&header_path, &generated.header)?;
     paths::symlink_header(prj, &header_path, rust_source_file);
 
-    let implementation_path = paths::out_with_extension(prj, rust_source_file, ".cc")?;
+    let implementation_path = paths::out_with_extension(prj, rust_source_file, ".cc");
     write(&implementation_path, &generated.implementation)?;
     build.file(&implementation_path);
     Ok(())
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index f8b1ee9..fc06157 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -34,8 +34,7 @@ pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
 }
 
 fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(prj, original)?;
-    let ref dst = include_dir(prj).join(suffix);
+    let ref dst = include_dir(prj).join(original);
 
     fs::create_dir_all(dst.parent().unwrap())?;
     let _ = fs::remove_file(dst);
@@ -49,29 +48,14 @@ fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()>
     Ok(())
 }
 
-fn relative_to_parent_of_target_dir(prj: &Project, original: &Path) -> Result<PathBuf> {
-    let mut outer = match &prj.target_dir {
-        TargetDir::Path(target_dir) => target_dir.parent().unwrap(),
-        TargetDir::Unknown => unimplemented!(), // FIXME
-    };
-    let original = canonicalize(original)?;
-    loop {
-        if let Ok(suffix) = original.strip_prefix(outer) {
-            return Ok(suffix.to_owned());
-        }
-        match outer.parent() {
-            Some(parent) => outer = parent,
-            None => return Ok(original.components().skip(1).collect()),
-        }
-    }
-}
-
-pub(crate) fn out_with_extension(prj: &Project, path: &Path, ext: &str) -> Result<PathBuf> {
-    let mut file_name = path.file_name().unwrap().to_owned();
+pub(crate) fn out_with_extension(prj: &Project, rel_path: &Path, ext: &str) -> PathBuf {
+    let mut file_name = rel_path.file_name().unwrap().to_owned();
     file_name.push(ext);
 
-    let rel = relative_to_parent_of_target_dir(prj, path)?;
-    Ok(prj.out_dir.join(rel).with_file_name(file_name))
+    prj.out_dir
+        .join("cxxbridge")
+        .join(rel_path)
+        .with_file_name(file_name)
 }
 
 pub(crate) fn include_dir(prj: &Project) -> PathBuf {
@@ -109,20 +93,6 @@ pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
     }
 }
 
-#[cfg(not(windows))]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    Ok(fs::canonicalize(path)?)
-}
-
-#[cfg(windows)]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
-    // unable to handle in includes. Use a poor approximation instead.
-    // https://github.com/rust-lang/rust/issues/42869
-    // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(fs::current_dir()?.join(path))
-}
-
 #[cfg(unix)]
 use self::fs::symlink_file as symlink_or_copy;
 
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 77488f8..fe15f86 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -34,14 +34,6 @@ macro_rules! err {
     }
 }
 
-pub(crate) fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    let path = path.as_ref();
-    match std::fs::canonicalize(path) {
-        Ok(string) => Ok(string),
-        Err(e) => err!(e, "Unable to canonicalize path: `{}`", path),
-    }
-}
-
 pub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64> {
     let from = from.as_ref();
     let to = to.as_ref();

From ba220ca7af20e71abed0f184a97a7ab155b0942d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 814/2232] Include package names in include path


---

diff --git a/demo/Cargo.toml b/demo/Cargo.toml
index d2147ab..dc94861 100644
--- a/demo/Cargo.toml
+++ b/demo/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cxxbridge-demo"
+name = "demo"
 version = "0.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index fc06157..007c5f1 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -2,6 +2,7 @@ use crate::error::{Error, Result};
 use crate::gen::fs;
 use crate::Project;
 use std::env;
+use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 
 pub(crate) enum TargetDir {
@@ -34,11 +35,14 @@ pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
 }
 
 fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
-    let ref dst = include_dir(prj).join(original);
+    let mut dst = include_dir(prj);
+    dst.extend(package_name());
+    dst.push(original);
 
-    fs::create_dir_all(dst.parent().unwrap())?;
-    let _ = fs::remove_file(dst);
-    symlink_or_copy(path, dst)?;
+    let parent = dst.parent().unwrap();
+    fs::create_dir_all(parent)?;
+    let _ = fs::remove_file(&dst);
+    symlink_or_copy(path, &dst)?;
 
     let mut file_name = dst.file_name().unwrap().to_os_string();
     file_name.push(".h");
@@ -52,10 +56,11 @@ pub(crate) fn out_with_extension(prj: &Project, rel_path: &Path, ext: &str) -> P
     let mut file_name = rel_path.file_name().unwrap().to_owned();
     file_name.push(ext);
 
-    prj.out_dir
-        .join("cxxbridge")
-        .join(rel_path)
-        .with_file_name(file_name)
+    let mut res = prj.out_dir.clone();
+    res.push("cxxbridge");
+    res.extend(package_name());
+    res.push(rel_path);
+    res.with_file_name(file_name)
 }
 
 pub(crate) fn include_dir(prj: &Project) -> PathBuf {
@@ -65,6 +70,10 @@ pub(crate) fn include_dir(prj: &Project) -> PathBuf {
     }
 }
 
+fn package_name() -> Option<OsString> {
+    env::var_os("CARGO_PKG_NAME")
+}
+
 pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
     // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
     // handle in includes.

From 65c0ac885bc777a27fe4c03dc4b2ceed48260548 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 815/2232] Remove "parent of target dir" from include path


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 007c5f1..8fe86ae 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -19,9 +19,6 @@ pub(crate) fn out_dir() -> Result<PathBuf> {
 pub(crate) fn cc_build(prj: &Project) -> cc::Build {
     let mut build = cc::Build::new();
     build.include(include_dir(prj));
-    if let TargetDir::Path(target_dir) = &prj.target_dir {
-        build.include(target_dir.parent().unwrap());
-    }
     build
 }
 

From 2f40fc93e6b305d45889b13a0e74823419da1c41 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 816/2232] Include manifest dir


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 8fe86ae..9d922ed 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -19,6 +19,9 @@ pub(crate) fn out_dir() -> Result<PathBuf> {
 pub(crate) fn cc_build(prj: &Project) -> cc::Build {
     let mut build = cc::Build::new();
     build.include(include_dir(prj));
+    if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
+        build.include(manifest_dir);
+    }
     build
 }
 

From 421a250d7808f592ffbb08e733d0c16b96dd48ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 817/2232] Prefix crate name to the import paths


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index bdaf4f6..88a1874 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -126,6 +126,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
     write_header(prj);
+    symlink_crate(prj, &mut build);
 
     for path in rust_source_files {
         generate_bridge(prj, &mut build, path.as_ref())?;
@@ -135,10 +136,28 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 }
 
 fn write_header(prj: &Project) {
-    let ref cxx_h = paths::include_dir(prj).join("rust").join("cxx.h");
+    let include_dir = paths::include_dir(prj);
+    let ref cxx_h = include_dir.join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
 }
 
+fn symlink_crate(prj: &Project, build: &mut Build) {
+    let manifest_dir = match paths::manifest_dir() {
+        Some(manifest_dir) => manifest_dir,
+        None => return,
+    };
+    let package_name = match paths::package_name() {
+        Some(package_name) => package_name,
+        None => return,
+    };
+
+    let mut link = paths::include_dir(prj);
+    link.push("CRATE");
+    let _ = fs::create_dir_all(&link);
+    let _ = paths::symlink_dir(manifest_dir, link.join(package_name));
+    build.include(link);
+}
+
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 9d922ed..e02246a 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -19,9 +19,6 @@ pub(crate) fn out_dir() -> Result<PathBuf> {
 pub(crate) fn cc_build(prj: &Project) -> cc::Build {
     let mut build = cc::Build::new();
     build.include(include_dir(prj));
-    if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
-        build.include(manifest_dir);
-    }
     build
 }
 
@@ -70,7 +67,11 @@ pub(crate) fn include_dir(prj: &Project) -> PathBuf {
     }
 }
 
-fn package_name() -> Option<OsString> {
+pub(crate) fn manifest_dir() -> Option<PathBuf> {
+    env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
+}
+
+pub(crate) fn package_name() -> Option<OsString> {
     env::var_os("CARGO_PKG_NAME")
 }
 
@@ -117,3 +118,11 @@ fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
 
 #[cfg(not(any(unix, windows)))]
 use self::fs::copy as symlink_or_copy;
+
+#[cfg(any(unix, windows))]
+pub(crate) use self::fs::symlink_dir;
+
+#[cfg(not(any(unix, windows)))]
+pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> Result<()> {
+    Ok(())
+}

From dd24f74dfcf1990a3f74988a95c148b0e80efbcc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 818/2232] Move cc-related code out of paths module


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 88a1874..c611eea 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -122,9 +122,10 @@ impl Project {
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
-    let mut build = paths::cc_build(prj);
+    let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+    build.include(paths::include_dir(prj));
     write_header(prj);
     symlink_crate(prj, &mut build);
 
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index e02246a..d6ff359 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -16,12 +16,6 @@ pub(crate) fn out_dir() -> Result<PathBuf> {
         .ok_or(Error::MissingOutDir)
 }
 
-pub(crate) fn cc_build(prj: &Project) -> cc::Build {
-    let mut build = cc::Build::new();
-    build.include(include_dir(prj));
-    build
-}
-
 // Symlink the header file into a predictable place. The header generated from
 // path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
 pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {

From 8f18318902f205002b13ea17b3bf53a712f3c879 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 819/2232] Guard our path joins from going outside out-dir


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index c611eea..fa7b825 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -62,7 +62,7 @@ mod syntax;
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
-use crate::paths::TargetDir;
+use crate::paths::{PathExt, TargetDir};
 use cc::Build;
 use std::io::{self, Write};
 use std::iter;
@@ -162,14 +162,21 @@ fn symlink_crate(prj: &Project, build: &mut Build) {
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
+    let ref rel_path = paths::local_relative_path(rust_source_file);
+
+    let ref rel_path_h = rel_path.with_appended_extension(".h");
+    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
+    write(header_path, &generated.header)?;
+    paths::symlink_namespaced(header_path, &prj.out_dir, rel_path);
+    if let TargetDir::Path(target_dir) = &prj.target_dir {
+        paths::symlink_namespaced(header_path, target_dir, rel_path);
+        paths::symlink_namespaced(header_path, target_dir, rel_path_h);
+    }
 
-    let header_path = paths::out_with_extension(prj, rust_source_file, ".h");
-    write(&header_path, &generated.header)?;
-    paths::symlink_header(prj, &header_path, rust_source_file);
-
-    let implementation_path = paths::out_with_extension(prj, rust_source_file, ".cc");
-    write(&implementation_path, &generated.implementation)?;
-    build.file(&implementation_path);
+    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
+    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
+    write(implementation_path, &generated.implementation)?;
+    build.file(implementation_path);
     Ok(())
 }
 
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index d6ff359..1a423dc 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -2,8 +2,8 @@ use crate::error::{Error, Result};
 use crate::gen::fs;
 use crate::Project;
 use std::env;
-use std::ffi::OsString;
-use std::path::{Path, PathBuf};
+use std::ffi::{OsStr, OsString};
+use std::path::{Component, Path, PathBuf};
 
 pub(crate) enum TargetDir {
     Path(PathBuf),
@@ -16,42 +16,44 @@ pub(crate) fn out_dir() -> Result<PathBuf> {
         .ok_or(Error::MissingOutDir)
 }
 
-// Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
-    if let TargetDir::Unknown = prj.target_dir {
-        return;
+// Given a path provided by the user, determines where generated files related
+// to that path should go in our out dir. In particular we don't want to
+// accidentally write generated code upward of our out dir, even if the user
+// passed a path containing lots of `..` or an absolute path.
+pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
+    let mut rel_path = PathBuf::new();
+    for component in path.components() {
+        match component {
+            Component::Prefix(_) | Component::RootDir | Component::CurDir => {}
+            Component::ParentDir => drop(rel_path.pop()), // noop if empty
+            Component::Normal(name) => rel_path.push(name),
+        }
     }
-    let _ = try_symlink_header(prj, path, original);
+    rel_path
 }
 
-fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
-    let mut dst = include_dir(prj);
-    dst.extend(package_name());
-    dst.push(original);
-
-    let parent = dst.parent().unwrap();
-    fs::create_dir_all(parent)?;
-    let _ = fs::remove_file(&dst);
-    symlink_or_copy(path, &dst)?;
-
-    let mut file_name = dst.file_name().unwrap().to_os_string();
-    file_name.push(".h");
-    let ref dst2 = dst.with_file_name(file_name);
-    symlink_or_copy(path, dst2)?;
+pub(crate) fn namespaced(base: &Path, rel_path: &Path) -> PathBuf {
+    let mut path = base.to_owned();
+    path.push("cxxbridge");
+    path.extend(package_name());
+    path.push(rel_path);
+    path
+}
 
-    Ok(())
+pub(crate) fn symlink_namespaced(src: &Path, base: &Path, rel_path: &Path) {
+    let _ = symlink_or_copy(src, namespaced(base, rel_path));
 }
 
-pub(crate) fn out_with_extension(prj: &Project, rel_path: &Path, ext: &str) -> PathBuf {
-    let mut file_name = rel_path.file_name().unwrap().to_owned();
-    file_name.push(ext);
+pub(crate) trait PathExt {
+    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
+}
 
-    let mut res = prj.out_dir.clone();
-    res.push("cxxbridge");
-    res.extend(package_name());
-    res.push(rel_path);
-    res.with_file_name(file_name)
+impl PathExt for Path {
+    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf {
+        let mut file_name = self.file_name().unwrap().to_owned();
+        file_name.push(suffix);
+        self.with_file_name(file_name)
+    }
 }
 
 pub(crate) fn include_dir(prj: &Project) -> PathBuf {

From 63b34b8981579ddd2bd04ed80b81b5c3415e3acd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:24:40 +0000
Subject: [PATCH 820/2232] Write cxx.h to out dir and target dir


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index fa7b825..a36f925 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -137,9 +137,14 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 }
 
 fn write_header(prj: &Project) {
-    let include_dir = paths::include_dir(prj);
-    let ref cxx_h = include_dir.join("rust").join("cxx.h");
+    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+    if let TargetDir::Path(target_dir) = &prj.target_dir {
+        let ref header_dir = target_dir.join("cxxbridge").join("rust");
+        let _ = fs::create_dir_all(header_dir);
+        let ref cxx_h = header_dir.join("cxx.h");
+        let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+    }
 }
 
 fn symlink_crate(prj: &Project, build: &mut Build) {

From 825ad27691dfba1edbe8401686bd6a7ed8f51d73 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:37:02 +0000
Subject: [PATCH 821/2232] Create dir for the links in the target dir


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index a36f925..9a1ad0a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -174,8 +174,10 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     write(header_path, &generated.header)?;
     paths::symlink_namespaced(header_path, &prj.out_dir, rel_path);
     if let TargetDir::Path(target_dir) = &prj.target_dir {
-        paths::symlink_namespaced(header_path, target_dir, rel_path);
-        paths::symlink_namespaced(header_path, target_dir, rel_path_h);
+        let ref link_path = paths::namespaced(target_dir, rel_path);
+        let _ = fs::create_dir_all(link_path.parent().unwrap());
+        let _ = paths::symlink_or_copy(header_path, link_path);
+        let _ = paths::symlink_or_copy(header_path, link_path.with_appended_extension(".h"));
     }
 
     let ref rel_path_cc = rel_path.with_appended_extension(".cc");
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 1a423dc..c3238b3 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -100,10 +100,10 @@ pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
 }
 
 #[cfg(unix)]
-use self::fs::symlink_file as symlink_or_copy;
+pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
-fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+pub(crate) fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
     if fs::symlink_file(src, dst).is_err() {
@@ -113,7 +113,7 @@ fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
 }
 
 #[cfg(not(any(unix, windows)))]
-use self::fs::copy as symlink_or_copy;
+pub(crate) use self::fs::copy as symlink_or_copy;
 
 #[cfg(any(unix, windows))]
 pub(crate) use self::fs::symlink_dir;

From 913067940435431c95a6a42f2447b24d0958742e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 04:38:15 +0000
Subject: [PATCH 822/2232] Inline once used symlink function


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 9a1ad0a..b42bbe0 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -172,7 +172,9 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let ref rel_path_h = rel_path.with_appended_extension(".h");
     let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
     write(header_path, &generated.header)?;
-    paths::symlink_namespaced(header_path, &prj.out_dir, rel_path);
+
+    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
+    let _ = paths::symlink_or_copy(header_path, link_path);
     if let TargetDir::Path(target_dir) = &prj.target_dir {
         let ref link_path = paths::namespaced(target_dir, rel_path);
         let _ = fs::create_dir_all(link_path.parent().unwrap());
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index c3238b3..5f6243f 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -40,10 +40,6 @@ pub(crate) fn namespaced(base: &Path, rel_path: &Path) -> PathBuf {
     path
 }
 
-pub(crate) fn symlink_namespaced(src: &Path, base: &Path, rel_path: &Path) {
-    let _ = symlink_or_copy(src, namespaced(base, rel_path));
-}
-
 pub(crate) trait PathExt {
     fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
 }

From 6eeaeef36caf7e41e6c7481d96b36bae3c0ca882 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:14:03 +0000
Subject: [PATCH 823/2232] Run cargo metadata from top level crate's dir


When Cargo runs a build script, its current directory is set to the
manifest directory of the crate whose build script it is. That means if
crate A depends on crate B depends on cxx-build, the previous logic
would have found B's target dir (somewhere in the Cargo registry cache)
rather than the intended A target dir being used for the current build.

---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 6a4f1a6..b67c21b 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -1,12 +1,13 @@
 use crate::paths::TargetDir;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
-pub(crate) fn target_dir() -> TargetDir {
+pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
     (|| {
         let cargo = option_env!("CARGO").unwrap_or("cargo");
         let output = Command::new(cargo)
+            .current_dir(out_dir)
             .arg("metadata")
             .arg("--no-deps")
             .arg("--format-version=1")
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b42bbe0..1628510 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -107,7 +107,7 @@ impl Project {
     fn init() -> Result<Self> {
         let out_dir = paths::out_dir()?;
 
-        let target_dir = match cargo::target_dir() {
+        let target_dir = match cargo::target_dir(&out_dir) {
             target_dir @ TargetDir::Path(_) => target_dir,
             // Fallback if Cargo did not work.
             TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),

From 25db1555f5211c4ff09c65a5c69a266a41e86cb9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:41:15 +0000
Subject: [PATCH 824/2232] Update import path scheme for tests


---

diff --git a/tests/BUCK b/tests/BUCK
index 4bfc9e8..a96bfb8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -24,9 +24,10 @@ cxx_library(
         ":gen-lib-source",
         ":gen-module-source",
     ],
+    header_namespace = "cxx-test-suite",
     headers = {
-        "ffi/lib.rs.h": ":gen-lib-header",
-        "ffi/tests.h": "ffi/tests.h",
+        "lib.rs.h": ":gen-lib-header",
+        "tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
diff --git a/tests/BUILD b/tests/BUILD
index e1f1637..29cc79c 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -26,6 +26,8 @@ cc_library(
         ":gen-module-source",
     ],
     hdrs = ["ffi/tests.h"],
+    include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
     deps = [
         ":lib-include",
         "//:core",
@@ -51,7 +53,7 @@ genrule(
 cc_library(
     name = "lib-include",
     hdrs = [":gen-lib-header"],
-    include_prefix = "tests/ffi",
+    include_prefix = "cxx-test-suite",
 )
 
 genrule(
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 8aaac75..d6724f5 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -23,7 +23,7 @@ pub mod ffi {
     }
 
     extern "C" {
-        include!("tests/ffi/tests.h");
+        include!("cxx-test-suite/tests.h");
 
         type C;
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 77bae06..8862dc1 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -4,7 +4,7 @@
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     extern "C" {
-        include!("tests/ffi/tests.h");
+        include!("cxx-test-suite/tests.h");
 
         type C = crate::ffi::C;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d45d5d5..8dd16e8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
-#include "tests/ffi/tests.h"
-#include "tests/ffi/lib.rs.h"
+#include "cxx-test-suite/tests.h"
+#include "cxx-test-suite/lib.rs.h"
 #include <cstring>
 #include <iterator>
 #include <numeric>

From 70d476cd875f77622680e612f90a6b09a02b3b94 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:45:36 +0000
Subject: [PATCH 825/2232] Match symlink_file's signature on windows


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 5f6243f..96e3708 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -99,9 +99,11 @@ pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
 pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
-pub(crate) fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+pub(crate) fn symlink_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
+    let src = src.as_ref();
+    let dst = dst.as_ref();
     if fs::symlink_file(src, dst).is_err() {
         fs::copy(src, dst)?;
     }

From 759be0fabecdf21099ecc93504ba914ed88b15e6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:46:14 +0000
Subject: [PATCH 826/2232] Regenerate Cargo.lock for renamed demo crate


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1f3e760..b335d31 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -115,14 +115,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "cxxbridge-demo"
-version = "0.0.0"
-dependencies = [
- "cxx",
- "cxx-build",
-]
-
-[[package]]
 name = "cxxbridge-flags"
 version = "0.3.9"
 
@@ -137,6 +129,14 @@ dependencies = [
 ]
 
 [[package]]
+name = "demo"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
 name = "dissimilar"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From 34e603ea5e9d38cd2b561d498b5faf101244101b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:57:22 +0000
Subject: [PATCH 827/2232] Merge pull request #276 from dtolnay/build


Rewrite cxx-build crate
---

diff --git a/demo/Cargo.toml b/demo/Cargo.toml
index d2147ab..dc94861 100644
--- a/demo/Cargo.toml
+++ b/demo/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "cxxbridge-demo"
+name = "demo"
 version = "0.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 3bddc6e..b67c21b 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -1,19 +1,19 @@
-use crate::error::TargetDirError;
 use crate::paths::TargetDir;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
 
-pub(crate) fn target_dir() -> Result<TargetDir, TargetDirError> {
-    let cargo = option_env!("CARGO").unwrap_or("cargo");
-    let output = Command::new(cargo)
-        .arg("metadata")
-        .arg("--no-deps")
-        .arg("--format-version=1")
-        .output()
-        .map_err(TargetDirError::Io)?;
-
+pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
     (|| {
+        let cargo = option_env!("CARGO").unwrap_or("cargo");
+        let output = Command::new(cargo)
+            .current_dir(out_dir)
+            .arg("metadata")
+            .arg("--no-deps")
+            .arg("--format-version=1")
+            .output()
+            .ok()?;
+
         // Cargo only outputs utf8 encoded JSON.
         let mut metadata = str::from_utf8(&output.stdout).ok()?;
 
@@ -25,7 +25,7 @@ pub(crate) fn target_dir() -> Result<TargetDir, TargetDirError> {
         let close_quote_index = metadata.find('"')?;
         let string = &metadata[..close_quote_index];
         let target_directory = string.replace("\\\\", "\\");
-        Some(TargetDir(PathBuf::from(target_directory)))
+        Some(TargetDir::Path(PathBuf::from(target_directory)))
     })()
-    .ok_or(TargetDirError::NotFound)
+    .unwrap_or(TargetDir::Unknown)
 }
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index ed4c6af..0ed4d74 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,28 +1,19 @@
 use crate::gen::fs;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub(super) enum Error {
     MissingOutDir,
-    TargetDir(TargetDirError),
     Fs(fs::Error),
 }
 
-#[derive(Debug)]
-pub(crate) enum TargetDirError {
-    Io(io::Error),
-    NotFound,
-}
-
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
-            Error::TargetDir(_) => write!(f, "unable to identify target dir"),
             Error::Fs(err) => err.fmt(f),
         }
     }
@@ -31,10 +22,6 @@ impl Display for Error {
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
         match self {
-            Error::TargetDir(err) => match err {
-                TargetDirError::Io(err) => Some(err),
-                TargetDirError::NotFound => None,
-            },
             Error::Fs(err) => err.source(),
             _ => None,
         }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 22f53f6..1628510 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -59,14 +59,14 @@ mod gen;
 mod paths;
 mod syntax;
 
-use crate::error::Result;
+use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
-use crate::paths::TargetDir;
+use crate::paths::{PathExt, TargetDir};
 use cc::Build;
 use std::io::{self, Write};
 use std::iter;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process;
 
 /// This returns a [`cc::Build`] on which you should continue to set up any
@@ -98,45 +98,99 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
     })
 }
 
+struct Project {
+    out_dir: PathBuf,
+    target_dir: TargetDir,
+}
+
+impl Project {
+    fn init() -> Result<Self> {
+        let out_dir = paths::out_dir()?;
+
+        let target_dir = match cargo::target_dir(&out_dir) {
+            target_dir @ TargetDir::Path(_) => target_dir,
+            // Fallback if Cargo did not work.
+            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
+        };
+
+        Ok(Project {
+            out_dir,
+            target_dir,
+        })
+    }
+}
+
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    let ref target_dir = paths::target_dir()?;
-    let mut build = paths::cc_build(target_dir);
+    let ref prj = Project::init()?;
+    let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    write_header(target_dir);
+    build.include(paths::include_dir(prj));
+    write_header(prj);
+    symlink_crate(prj, &mut build);
 
     for path in rust_source_files {
-        generate_bridge(&mut build, path.as_ref(), target_dir)?;
+        generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
     Ok(build)
 }
 
-fn write_header(target_dir: &TargetDir) {
-    let ref cxx_h = paths::include_dir(target_dir).join("rust").join("cxx.h");
+fn write_header(prj: &Project) {
+    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
     let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+    if let TargetDir::Path(target_dir) = &prj.target_dir {
+        let ref header_dir = target_dir.join("cxxbridge").join("rust");
+        let _ = fs::create_dir_all(header_dir);
+        let ref cxx_h = header_dir.join("cxx.h");
+        let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+    }
 }
 
-fn generate_bridge(
-    build: &mut Build,
-    rust_source_file: &Path,
-    target_dir: &TargetDir,
-) -> Result<()> {
+fn symlink_crate(prj: &Project, build: &mut Build) {
+    let manifest_dir = match paths::manifest_dir() {
+        Some(manifest_dir) => manifest_dir,
+        None => return,
+    };
+    let package_name = match paths::package_name() {
+        Some(package_name) => package_name,
+        None => return,
+    };
+
+    let mut link = paths::include_dir(prj);
+    link.push("CRATE");
+    let _ = fs::create_dir_all(&link);
+    let _ = paths::symlink_dir(manifest_dir, link.join(package_name));
+    build.include(link);
+}
+
+fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
     let opt = Opt::default();
     let generated = gen::generate_from_path(rust_source_file, &opt);
+    let ref rel_path = paths::local_relative_path(rust_source_file);
+
+    let ref rel_path_h = rel_path.with_appended_extension(".h");
+    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
+    write(header_path, &generated.header)?;
 
-    let header_path = paths::out_with_extension(rust_source_file, ".h", target_dir)?;
-    fs::create_dir_all(header_path.parent().unwrap())?;
-    write(&header_path, &generated.header)?;
-    paths::symlink_header(&header_path, rust_source_file, target_dir);
+    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
+    let _ = paths::symlink_or_copy(header_path, link_path);
+    if let TargetDir::Path(target_dir) = &prj.target_dir {
+        let ref link_path = paths::namespaced(target_dir, rel_path);
+        let _ = fs::create_dir_all(link_path.parent().unwrap());
+        let _ = paths::symlink_or_copy(header_path, link_path);
+        let _ = paths::symlink_or_copy(header_path, link_path.with_appended_extension(".h"));
+    }
 
-    let implementation_path = paths::out_with_extension(rust_source_file, ".cc", target_dir)?;
-    write(&implementation_path, &generated.implementation)?;
-    build.file(&implementation_path);
+    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
+    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
+    write(implementation_path, &generated.implementation)?;
+    build.file(implementation_path);
     Ok(())
 }
 
 fn write(path: &Path, content: &[u8]) -> Result<()> {
+    let mut create_dir_error = None;
     if path.exists() {
         if let Ok(existing) = fs::read(path) {
             if existing == content {
@@ -146,8 +200,14 @@ fn write(path: &Path, content: &[u8]) -> Result<()> {
         }
         let _ = fs::remove_file(path);
     } else {
-        let _ = fs::create_dir_all(path.parent().unwrap());
+        let parent = path.parent().unwrap();
+        create_dir_error = fs::create_dir_all(parent).err();
+    }
+
+    match fs::write(path, content) {
+        // As long as write succeeded, ignore any create_dir_all error.
+        Ok(()) => Ok(()),
+        // If create_dir_all and write both failed, prefer the first error.
+        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
     }
-    fs::write(path, content)?;
-    Ok(())
 }
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 870c49d..96e3708 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,124 +1,109 @@
-use crate::cargo;
 use crate::error::{Error, Result};
 use crate::gen::fs;
+use crate::Project;
 use std::env;
-use std::ops::Deref;
-use std::path::{Path, PathBuf};
+use std::ffi::{OsStr, OsString};
+use std::path::{Component, Path, PathBuf};
 
-pub(crate) struct TargetDir(pub PathBuf);
-
-impl Deref for TargetDir {
-    type Target = Path;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
+pub(crate) enum TargetDir {
+    Path(PathBuf),
+    Unknown,
 }
 
-fn out_dir() -> Result<PathBuf> {
+pub(crate) fn out_dir() -> Result<PathBuf> {
     env::var_os("OUT_DIR")
         .map(PathBuf::from)
         .ok_or(Error::MissingOutDir)
 }
 
-pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
-    let mut build = cc::Build::new();
-    build.include(include_dir(target_dir));
-    build.include(target_dir.parent().unwrap());
-    build
+// Given a path provided by the user, determines where generated files related
+// to that path should go in our out dir. In particular we don't want to
+// accidentally write generated code upward of our out dir, even if the user
+// passed a path containing lots of `..` or an absolute path.
+pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
+    let mut rel_path = PathBuf::new();
+    for component in path.components() {
+        match component {
+            Component::Prefix(_) | Component::RootDir | Component::CurDir => {}
+            Component::ParentDir => drop(rel_path.pop()), // noop if empty
+            Component::Normal(name) => rel_path.push(name),
+        }
+    }
+    rel_path
 }
 
-// Symlink the header file into a predictable place. The header generated from
-// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
-pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
-    let _ = try_symlink_header(path, original, target_dir);
+pub(crate) fn namespaced(base: &Path, rel_path: &Path) -> PathBuf {
+    let mut path = base.to_owned();
+    path.push("cxxbridge");
+    path.extend(package_name());
+    path.push(rel_path);
+    path
 }
 
-fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
-    let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
-    let ref dst = include_dir(target_dir).join(suffix);
-
-    fs::create_dir_all(dst.parent().unwrap())?;
-    let _ = fs::remove_file(dst);
-    symlink_or_copy(path, dst)?;
-
-    let mut file_name = dst.file_name().unwrap().to_os_string();
-    file_name.push(".h");
-    let ref dst2 = dst.with_file_name(file_name);
-    symlink_or_copy(path, dst2)?;
+pub(crate) trait PathExt {
+    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
+}
 
-    Ok(())
+impl PathExt for Path {
+    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf {
+        let mut file_name = self.file_name().unwrap().to_owned();
+        file_name.push(suffix);
+        self.with_file_name(file_name)
+    }
 }
 
-fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
-    let mut outer = target_dir.parent().unwrap();
-    let original = canonicalize(original)?;
-    loop {
-        if let Ok(suffix) = original.strip_prefix(outer) {
-            return Ok(suffix.to_owned());
-        }
-        match outer.parent() {
-            Some(parent) => outer = parent,
-            None => return Ok(original.components().skip(1).collect()),
-        }
+pub(crate) fn include_dir(prj: &Project) -> PathBuf {
+    match &prj.target_dir {
+        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
+        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
     }
 }
 
-pub(crate) fn out_with_extension(
-    path: &Path,
-    ext: &str,
-    target_dir: &TargetDir,
-) -> Result<PathBuf> {
-    let mut file_name = path.file_name().unwrap().to_owned();
-    file_name.push(ext);
-
-    let out_dir = out_dir()?;
-    let rel = relative_to_parent_of_target_dir(path, target_dir)?;
-    Ok(out_dir.join(rel).with_file_name(file_name))
+pub(crate) fn manifest_dir() -> Option<PathBuf> {
+    env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
 }
 
-pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
-    target_dir.join("cxxbridge")
+pub(crate) fn package_name() -> Option<OsString> {
+    env::var_os("CARGO_PKG_NAME")
 }
 
-pub(crate) fn target_dir() -> Result<TargetDir> {
-    let fallback_err = match cargo::target_dir() {
-        Ok(target_dir) => return Ok(target_dir),
-        Err(err) => Error::TargetDir(err),
-    };
+pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
+    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
+    // handle in includes.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    let mut also_try_canonical = cfg!(not(windows));
 
-    // Fallback if Cargo did not work.
-    let mut dir = out_dir().and_then(canonicalize)?;
+    let mut dir = out_dir.to_owned();
     loop {
-        if dir.ends_with("target") {
-            return Ok(TargetDir(dir));
+        let is_target = dir.ends_with("target");
+        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
+        if is_target && parent_contains_cargo_toml {
+            return TargetDir::Path(dir);
         }
-        if !dir.pop() {
-            return Err(fallback_err);
+        if dir.pop() {
+            continue;
         }
+        if also_try_canonical {
+            if let Ok(canonical_dir) = out_dir.canonicalize() {
+                dir = canonical_dir;
+                also_try_canonical = false;
+                continue;
+            }
+        }
+        return TargetDir::Unknown;
     }
 }
 
-#[cfg(not(windows))]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    Ok(fs::canonicalize(path)?)
-}
-
-#[cfg(windows)]
-fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
-    // unable to handle in includes. Use a poor approximation instead.
-    // https://github.com/rust-lang/rust/issues/42869
-    // https://github.com/alexcrichton/cc-rs/issues/169
-    Ok(fs::current_dir()?.join(path))
-}
-
 #[cfg(unix)]
-use self::fs::symlink_file as symlink_or_copy;
+pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
-fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
+pub(crate) fn symlink_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
+    let src = src.as_ref();
+    let dst = dst.as_ref();
     if fs::symlink_file(src, dst).is_err() {
         fs::copy(src, dst)?;
     }
@@ -126,4 +111,12 @@ fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
 }
 
 #[cfg(not(any(unix, windows)))]
-use self::fs::copy as symlink_or_copy;
+pub(crate) use self::fs::copy as symlink_or_copy;
+
+#[cfg(any(unix, windows))]
+pub(crate) use self::fs::symlink_dir;
+
+#[cfg(not(any(unix, windows)))]
+pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> Result<()> {
+    Ok(())
+}
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 77488f8..fe15f86 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -34,14 +34,6 @@ macro_rules! err {
     }
 }
 
-pub(crate) fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
-    let path = path.as_ref();
-    match std::fs::canonicalize(path) {
-        Ok(string) => Ok(string),
-        Err(e) => err!(e, "Unable to canonicalize path: `{}`", path),
-    }
-}
-
 pub(crate) fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64> {
     let from = from.as_ref();
     let to = to.as_ref();
diff --git a/tests/BUCK b/tests/BUCK
index 4bfc9e8..a96bfb8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -24,9 +24,10 @@ cxx_library(
         ":gen-lib-source",
         ":gen-module-source",
     ],
+    header_namespace = "cxx-test-suite",
     headers = {
-        "ffi/lib.rs.h": ":gen-lib-header",
-        "ffi/tests.h": "ffi/tests.h",
+        "lib.rs.h": ":gen-lib-header",
+        "tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
diff --git a/tests/BUILD b/tests/BUILD
index e1f1637..29cc79c 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -26,6 +26,8 @@ cc_library(
         ":gen-module-source",
     ],
     hdrs = ["ffi/tests.h"],
+    include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
     deps = [
         ":lib-include",
         "//:core",
@@ -51,7 +53,7 @@ genrule(
 cc_library(
     name = "lib-include",
     hdrs = [":gen-lib-header"],
-    include_prefix = "tests/ffi",
+    include_prefix = "cxx-test-suite",
 )
 
 genrule(
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 8aaac75..d6724f5 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -23,7 +23,7 @@ pub mod ffi {
     }
 
     extern "C" {
-        include!("tests/ffi/tests.h");
+        include!("cxx-test-suite/tests.h");
 
         type C;
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 77bae06..8862dc1 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -4,7 +4,7 @@
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     extern "C" {
-        include!("tests/ffi/tests.h");
+        include!("cxx-test-suite/tests.h");
 
         type C = crate::ffi::C;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d45d5d5..8dd16e8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
-#include "tests/ffi/tests.h"
-#include "tests/ffi/lib.rs.h"
+#include "cxx-test-suite/tests.h"
+#include "cxx-test-suite/lib.rs.h"
 #include <cstring>
 #include <iterator>
 #include <numeric>
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1f3e760..b335d31 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -115,14 +115,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "cxxbridge-demo"
-version = "0.0.0"
-dependencies = [
- "cxx",
- "cxx-build",
-]
-
-[[package]]
 name = "cxxbridge-flags"
 version = "0.3.9"
 
@@ -137,6 +129,14 @@ dependencies = [
 ]
 
 [[package]]
+name = "demo"
+version = "0.0.0"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
 name = "dissimilar"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From 84f8cf973862311b293d540acc1bc3e74fb8ed15 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 05:58:35 +0000
Subject: [PATCH 828/2232] Unindent target dir cargo logic


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index b67c21b..35b6606 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -4,28 +4,29 @@ use std::process::Command;
 use std::str;
 
 pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
-    (|| {
-        let cargo = option_env!("CARGO").unwrap_or("cargo");
-        let output = Command::new(cargo)
-            .current_dir(out_dir)
-            .arg("metadata")
-            .arg("--no-deps")
-            .arg("--format-version=1")
-            .output()
-            .ok()?;
+    try_target_dir(out_dir).map_or(TargetDir::Unknown, TargetDir::Path)
+}
+
+fn try_target_dir(out_dir: &Path) -> Option<PathBuf> {
+    let cargo = option_env!("CARGO").unwrap_or("cargo");
+    let output = Command::new(cargo)
+        .current_dir(out_dir)
+        .arg("metadata")
+        .arg("--no-deps")
+        .arg("--format-version=1")
+        .output()
+        .ok()?;
 
-        // Cargo only outputs utf8 encoded JSON.
-        let mut metadata = str::from_utf8(&output.stdout).ok()?;
+    // Cargo only outputs utf8 encoded JSON.
+    let mut metadata = str::from_utf8(&output.stdout).ok()?;
 
-        let key_pattern = "\"target_directory\":";
-        let key_index = metadata.rfind(key_pattern)?;
-        metadata = &metadata[key_index + key_pattern.len()..];
-        let open_quote_index = metadata.find('"')?;
-        metadata = &metadata[open_quote_index + 1..];
-        let close_quote_index = metadata.find('"')?;
-        let string = &metadata[..close_quote_index];
-        let target_directory = string.replace("\\\\", "\\");
-        Some(TargetDir::Path(PathBuf::from(target_directory)))
-    })()
-    .unwrap_or(TargetDir::Unknown)
+    let key_pattern = "\"target_directory\":";
+    let key_index = metadata.rfind(key_pattern)?;
+    metadata = &metadata[key_index + key_pattern.len()..];
+    let open_quote_index = metadata.find('"')?;
+    metadata = &metadata[open_quote_index + 1..];
+    let close_quote_index = metadata.find('"')?;
+    let string = &metadata[..close_quote_index];
+    let target_directory = string.replace("\\\\", "\\");
+    Some(PathBuf::from(target_directory))
 }

From 591dcb647d711d252519c61249116c13f06a3fa1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 06:00:38 +0000
Subject: [PATCH 829/2232] Bump namespace to 04


---

diff --git a/Cargo.toml b/Cargo.toml
index 5e6fe27..2513633 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "cxx"
 version = "0.3.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge03"
+links = "cxxbridge04"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
diff --git a/build.rs b/build.rs
index cecf0e5..502a60b 100644
--- a/build.rs
+++ b/build.rs
@@ -4,7 +4,7 @@ fn main() {
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
-        .compile("cxxbridge03");
+        .compile("cxxbridge04");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
index 76ff987..dbf4c62 100644
--- a/gen/src/tests.rs
+++ b/gen/src/tests.rs
@@ -21,7 +21,7 @@ fn test_cpp() {
     let output = std::str::from_utf8(&output.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
 }
 
 #[test]
@@ -34,5 +34,5 @@ fn test_annotation() {
     };
     let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
     let output = std::str::from_utf8(&output.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge03$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index ccb9f61..20c63a9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -230,7 +230,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge03");
+    out.begin_block("inline namespace cxxbridge04");
 
     if needs_rust_string
         || needs_rust_str
@@ -253,15 +253,15 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    include::write(out, needs_rust_string, "CXXBRIDGE03_RUST_STRING");
-    include::write(out, needs_rust_str, "CXXBRIDGE03_RUST_STR");
-    include::write(out, needs_rust_slice, "CXXBRIDGE03_RUST_SLICE");
-    include::write(out, needs_rust_box, "CXXBRIDGE03_RUST_BOX");
-    include::write(out, needs_rust_vec, "CXXBRIDGE03_RUST_VEC");
-    include::write(out, needs_rust_fn, "CXXBRIDGE03_RUST_FN");
-    include::write(out, needs_rust_error, "CXXBRIDGE03_RUST_ERROR");
-    include::write(out, needs_rust_isize, "CXXBRIDGE03_RUST_ISIZE");
-    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE03_RUST_BITCOPY");
+    include::write(out, needs_rust_string, "CXXBRIDGE04_RUST_STRING");
+    include::write(out, needs_rust_str, "CXXBRIDGE04_RUST_STR");
+    include::write(out, needs_rust_slice, "CXXBRIDGE04_RUST_SLICE");
+    include::write(out, needs_rust_box, "CXXBRIDGE04_RUST_BOX");
+    include::write(out, needs_rust_vec, "CXXBRIDGE04_RUST_VEC");
+    include::write(out, needs_rust_fn, "CXXBRIDGE04_RUST_FN");
+    include::write(out, needs_rust_error, "CXXBRIDGE04_RUST_ERROR");
+    include::write(out, needs_rust_isize, "CXXBRIDGE04_RUST_ISIZE");
+    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE04_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();
@@ -287,7 +287,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace cxxbridge03");
+    out.end_block("namespace cxxbridge04");
 
     if needs_trycatch {
         out.begin_block("namespace behavior");
@@ -316,7 +316,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
-    let guard = format!("CXXBRIDGE03_STRUCT_{}{}", out.namespace, strct.ident);
+    let guard = format!("CXXBRIDGE04_STRUCT_{}{}", out.namespace, strct.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in strct.doc.to_string().lines() {
@@ -341,7 +341,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    let guard = format!("CXXBRIDGE03_STRUCT_{}{}", out.namespace, ety.ident);
+    let guard = format!("CXXBRIDGE04_STRUCT_{}{}", out.namespace, ety.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in ety.doc.to_string().lines() {
@@ -362,7 +362,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    let guard = format!("CXXBRIDGE03_ENUM_{}{}", out.namespace, enm.ident);
+    let guard = format!("CXXBRIDGE04_ENUM_{}{}", out.namespace, enm.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in enm.doc.to_string().lines() {
@@ -408,7 +408,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
         out.next_section();
         writeln!(
             out,
-            "const char *cxxbridge03$exception(const char *, size_t);",
+            "const char *cxxbridge04$exception(const char *, size_t);",
         );
     }
 }
@@ -553,7 +553,7 @@ fn write_cxx_function_shim(
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = cxxbridge03$exception(catch$, throw$.len);",
+            "        throw$.ptr = cxxbridge04$exception(catch$, throw$.len);",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -1026,7 +1026,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("extern \"C\"");
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge03");
+    out.begin_block("inline namespace cxxbridge04");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1040,7 +1040,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block("namespace cxxbridge03");
+    out.end_block("namespace cxxbridge04");
     out.end_block("namespace rust");
 }
 
@@ -1053,19 +1053,19 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE03_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE03_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE04_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE04_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge03$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge04$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge03$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge04$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE03_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE04_RUST_BOX_{}", instance);
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
@@ -1073,34 +1073,34 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE03_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE03_RUST_VEC_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE04_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE04_RUST_VEC_{}", instance);
     writeln!(
         out,
-        "void cxxbridge03$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge04$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge03$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge04$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge03$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        "size_t cxxbridge04$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge03$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        "const {} *cxxbridge04$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
     writeln!(
         out,
-        "size_t cxxbridge03$rust_vec${}$stride() noexcept;",
+        "size_t cxxbridge04$rust_vec${}$stride() noexcept;",
         instance,
     );
-    writeln!(out, "#endif // CXXBRIDGE03_RUST_VEC_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE04_RUST_VEC_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
@@ -1114,12 +1114,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge03$box${}$uninit(this);", instance);
+    writeln!(out, "  cxxbridge04$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge03$box${}$drop(this);", instance);
+    writeln!(out, "  cxxbridge04$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 
@@ -1130,35 +1130,35 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge03$rust_vec${}$new(this);", instance);
+    writeln!(out, "  cxxbridge04$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge03$rust_vec${}$drop(this);",
+        "  return cxxbridge04$rust_vec${}$drop(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge03$rust_vec${}$len(this);", instance);
+    writeln!(out, "  return cxxbridge04$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge03$rust_vec${}$data(this);",
+        "  return cxxbridge04$rust_vec${}$data(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge03$rust_vec${}$stride();", instance);
+    writeln!(out, "  return cxxbridge04$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
 }
 
@@ -1166,12 +1166,12 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     let ty = Type::Ident(ident.clone());
     let instance = to_mangled(&out.namespace, &ty);
 
-    writeln!(out, "#ifndef CXXBRIDGE03_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE03_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE04_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE04_UNIQUE_PTR_{}", instance);
 
     write_unique_ptr_common(out, &ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE03_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE04_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
@@ -1198,7 +1198,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(
         out,
-        "void cxxbridge03$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge04$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
@@ -1206,7 +1206,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     if can_construct_from_value {
         writeln!(
             out,
-            "void cxxbridge03$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            "void cxxbridge04$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
         writeln!(
@@ -1218,28 +1218,28 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     }
     writeln!(
         out,
-        "void cxxbridge03$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge04$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge03$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge04$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge03$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge04$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge03$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge04$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
@@ -1251,18 +1251,18 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE03_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE03_VECTOR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE04_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE04_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge03$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge04$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge03$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge04$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return &s[pos];");
@@ -1270,5 +1270,5 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
 
     write_unique_ptr_common(out, vector_ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE03_VECTOR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE04_VECTOR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index 9a9d5fa..f050248 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,12 +15,12 @@
 #endif
 
 namespace rust {
-inline namespace cxxbridge03 {
+inline namespace cxxbridge04 {
 
 struct unsafe_bitcopy_t;
 
-#ifndef CXXBRIDGE03_RUST_STRING
-#define CXXBRIDGE03_RUST_STRING
+#ifndef CXXBRIDGE04_RUST_STRING
+#define CXXBRIDGE04_RUST_STRING
 class String final {
 public:
   String() noexcept;
@@ -49,10 +49,10 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE03_RUST_STRING
+#endif // CXXBRIDGE04_RUST_STRING
 
-#ifndef CXXBRIDGE03_RUST_STR
-#define CXXBRIDGE03_RUST_STR
+#ifndef CXXBRIDGE04_RUST_STR
+#define CXXBRIDGE04_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -86,9 +86,9 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE03_RUST_STR
+#endif // CXXBRIDGE04_RUST_STR
 
-#ifndef CXXBRIDGE03_RUST_SLICE
+#ifndef CXXBRIDGE04_RUST_SLICE
 template <typename T>
 class Slice final {
 public:
@@ -117,9 +117,9 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE03_RUST_SLICE
+#endif // CXXBRIDGE04_RUST_SLICE
 
-#ifndef CXXBRIDGE03_RUST_BOX
+#ifndef CXXBRIDGE04_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -158,9 +158,9 @@ private:
   void drop() noexcept;
   T *ptr;
 };
-#endif // CXXBRIDGE03_RUST_BOX
+#endif // CXXBRIDGE04_RUST_BOX
 
-#ifndef CXXBRIDGE03_RUST_VEC
+#ifndef CXXBRIDGE04_RUST_VEC
 template <typename T>
 class Vec final {
 public:
@@ -218,10 +218,10 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE03_RUST_VEC
+#endif // CXXBRIDGE04_RUST_VEC
 
-#ifndef CXXBRIDGE03_RUST_FN
-#define CXXBRIDGE03_RUST_FN
+#ifndef CXXBRIDGE04_RUST_FN
+#define CXXBRIDGE04_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -238,10 +238,10 @@ private:
 
 template <typename Signature>
 using TryFn = Fn<Signature, true>;
-#endif // CXXBRIDGE03_RUST_FN
+#endif // CXXBRIDGE04_RUST_FN
 
-#ifndef CXXBRIDGE03_RUST_ERROR
-#define CXXBRIDGE03_RUST_ERROR
+#ifndef CXXBRIDGE04_RUST_ERROR
+#define CXXBRIDGE04_RUST_ERROR
 class Error final : std::exception {
 public:
   Error(const Error &);
@@ -253,16 +253,16 @@ public:
 private:
   Str::Repr msg;
 };
-#endif // CXXBRIDGE03_RUST_ERROR
+#endif // CXXBRIDGE04_RUST_ERROR
 
-#ifndef CXXBRIDGE03_RUST_ISIZE
-#define CXXBRIDGE03_RUST_ISIZE
+#ifndef CXXBRIDGE04_RUST_ISIZE
+#define CXXBRIDGE04_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
-#endif // CXXBRIDGE03_RUST_ISIZE
+#endif // CXXBRIDGE04_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -296,17 +296,17 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 
-#ifndef CXXBRIDGE03_RUST_BITCOPY
-#define CXXBRIDGE03_RUST_BITCOPY
+#ifndef CXXBRIDGE04_RUST_BITCOPY
+#define CXXBRIDGE04_RUST_BITCOPY
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
 };
 
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE03_RUST_BITCOPY
+#endif // CXXBRIDGE04_RUST_BITCOPY
 
-#ifndef CXXBRIDGE03_RUST_SLICE
-#define CXXBRIDGE03_RUST_SLICE
+#ifndef CXXBRIDGE04_RUST_SLICE
+#define CXXBRIDGE04_RUST_SLICE
 template <typename T>
 Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
 
@@ -344,10 +344,10 @@ template <typename T>
 Slice<T>::operator Repr() noexcept {
   return this->repr;
 }
-#endif // CXXBRIDGE03_RUST_SLICE
+#endif // CXXBRIDGE04_RUST_SLICE
 
-#ifndef CXXBRIDGE03_RUST_BOX
-#define CXXBRIDGE03_RUST_BOX
+#ifndef CXXBRIDGE04_RUST_BOX
+#define CXXBRIDGE04_RUST_BOX
 template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
@@ -443,10 +443,10 @@ T *Box<T>::into_raw() noexcept {
 
 template <typename T>
 Box<T>::Box() noexcept {}
-#endif // CXXBRIDGE03_RUST_BOX
+#endif // CXXBRIDGE04_RUST_BOX
 
-#ifndef CXXBRIDGE03_RUST_VEC
-#define CXXBRIDGE03_RUST_VEC
+#ifndef CXXBRIDGE04_RUST_VEC
+#define CXXBRIDGE04_RUST_VEC
 template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept {
   this->repr = other.repr;
@@ -551,7 +551,7 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 // Internal API only intended for the cxxbridge code generator.
 template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
-#endif // CXXBRIDGE03_RUST_VEC
+#endif // CXXBRIDGE04_RUST_VEC
 
-} // namespace cxxbridge03
+} // namespace cxxbridge04
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c2d88ce..2f797b0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -689,7 +689,7 @@ fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge03$box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge04$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
@@ -718,7 +718,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge03$rust_vec${}{}$", namespace, elem);
+    let link_prefix = format!("cxxbridge04$rust_vec${}{}$", namespace, elem);
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -764,7 +764,7 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
 
 fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
     let name = ident.to_string();
-    let prefix = format!("cxxbridge03$unique_ptr${}{}$", namespace, ident);
+    let prefix = format!("cxxbridge04$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -837,10 +837,10 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
 
 fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let name = elem.to_string();
-    let prefix = format!("cxxbridge03$std$vector${}{}$", namespace, elem);
+    let prefix = format!("cxxbridge04$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge03$unique_ptr$std$vector${}{}$", namespace, elem);
+    let unique_ptr_prefix = format!("cxxbridge04$unique_ptr$std$vector${}{}$", namespace, elem);
     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/src/cxx.cc b/src/cxx.cc
index 2114598..cd75162 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -7,30 +7,30 @@
 #include <vector>
 
 extern "C" {
-const char *cxxbridge03$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge04$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge03$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge04$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
 // rust::String
-void cxxbridge03$string$new(rust::String *self) noexcept;
-void cxxbridge03$string$clone(rust::String *self,
+void cxxbridge04$string$new(rust::String *self) noexcept;
+void cxxbridge04$string$clone(rust::String *self,
                               const rust::String &other) noexcept;
-bool cxxbridge03$string$from(rust::String *self, const char *ptr,
+bool cxxbridge04$string$from(rust::String *self, const char *ptr,
                              size_t len) noexcept;
-void cxxbridge03$string$drop(rust::String *self) noexcept;
-const char *cxxbridge03$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge03$string$len(const rust::String *self) noexcept;
+void cxxbridge04$string$drop(rust::String *self) noexcept;
+const char *cxxbridge04$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge04$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge03$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge04$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge03 {
+inline namespace cxxbridge04 {
 
 template <typename Exception>
 void panic [[noreturn]] (const char *msg) {
@@ -44,42 +44,42 @@ void panic [[noreturn]] (const char *msg) {
 
 template void panic<std::out_of_range>[[noreturn]] (const char *msg);
 
-String::String() noexcept { cxxbridge03$string$new(this); }
+String::String() noexcept { cxxbridge04$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge03$string$clone(this, other);
+  cxxbridge04$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge03$string$new(&other);
+  cxxbridge04$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge03$string$drop(this); }
+String::~String() noexcept { cxxbridge04$string$drop(this); }
 
 String::String(const std::string &s) : String(s.data(), s.length()) {}
 
 String::String(const char *s) : String(s, std::strlen(s)) {}
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge03$string$from(this, s, len)) {
+  if (!cxxbridge04$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge03$string$drop(this);
-    cxxbridge03$string$clone(this, other);
+    cxxbridge04$string$drop(this);
+    cxxbridge04$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge03$string$drop(this);
+    cxxbridge04$string$drop(this);
     this->repr = other.repr;
-    cxxbridge03$string$new(&other);
+    cxxbridge04$string$new(&other);
   }
   return *this;
 }
@@ -89,12 +89,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge03$string$ptr(this);
+  return cxxbridge04$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge03$string$len(this); }
+size_t String::size() const noexcept { return cxxbridge04$string$len(this); }
 
-size_t String::length() const noexcept { return cxxbridge03$string$len(this); }
+size_t String::length() const noexcept { return cxxbridge04$string$len(this); }
 
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
@@ -113,7 +113,7 @@ Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
 Str::Str(const char *s) : Str(s, std::strlen(s)) {}
 
 Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
-  if (!cxxbridge03$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge04$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
@@ -143,7 +143,7 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
 }
 
 extern "C" {
-const char *cxxbridge03$error(const char *ptr, size_t len) {
+const char *cxxbridge04$error(const char *ptr, size_t len) {
   char *copy = new char[len];
   strncpy(copy, ptr, len);
   return copy;
@@ -153,7 +153,7 @@ const char *cxxbridge03$error(const char *ptr, size_t len) {
 Error::Error(Str::Repr msg) noexcept : msg(msg) {}
 
 Error::Error(const Error &other) {
-  this->msg.ptr = cxxbridge03$error(other.msg.ptr, other.msg.len);
+  this->msg.ptr = cxxbridge04$error(other.msg.ptr, other.msg.len);
   this->msg.len = other.msg.len;
 }
 
@@ -168,96 +168,96 @@ Error::~Error() noexcept { delete[] this->msg.ptr; }
 
 const char *Error::what() const noexcept { return this->msg.ptr; }
 
-} // namespace cxxbridge03
+} // namespace cxxbridge04
 } // namespace rust
 
 extern "C" {
-void cxxbridge03$unique_ptr$std$string$null(
+void cxxbridge04$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge03$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+void cxxbridge04$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge03$unique_ptr$std$string$get(
+const std::string *cxxbridge04$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge03$unique_ptr$std$string$release(
+std::string *cxxbridge04$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge03$unique_ptr$std$string$drop(
+void cxxbridge04$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
 } // extern "C"
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  size_t cxxbridge03$std$vector$##RUST_TYPE##$size(                            \
+  size_t cxxbridge04$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge03$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE *cxxbridge04$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
-  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
   const std::vector<CXX_TYPE>                                                  \
-      *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
+      *cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
           const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
   std::vector<CXX_TYPE>                                                        \
-      *cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$release(                \
+      *cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$release(                \
           std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
-  void cxxbridge03$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
   }
 
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
-  void cxxbridge03$rust_vec$##RUST_TYPE##$new(                                 \
+  void cxxbridge04$rust_vec$##RUST_TYPE##$new(                                 \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  void cxxbridge03$rust_vec$##RUST_TYPE##$drop(                                \
+  void cxxbridge04$rust_vec$##RUST_TYPE##$drop(                                \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  size_t cxxbridge03$rust_vec$##RUST_TYPE##$len(                               \
+  size_t cxxbridge04$rust_vec$##RUST_TYPE##$len(                               \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  const CXX_TYPE *cxxbridge03$rust_vec$##RUST_TYPE##$data(                     \
+  const CXX_TYPE *cxxbridge04$rust_vec$##RUST_TYPE##$data(                     \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  size_t cxxbridge03$rust_vec$##RUST_TYPE##$stride() noexcept;
+  size_t cxxbridge04$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
   Vec<CXX_TYPE>::Vec() noexcept {                                              \
-    cxxbridge03$rust_vec$##RUST_TYPE##$new(this);                              \
+    cxxbridge04$rust_vec$##RUST_TYPE##$new(this);                              \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::drop() noexcept {                                        \
-    return cxxbridge03$rust_vec$##RUST_TYPE##$drop(this);                      \
+    return cxxbridge04$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::size() const noexcept {                                \
-    return cxxbridge03$rust_vec$##RUST_TYPE##$len(this);                       \
+    return cxxbridge04$rust_vec$##RUST_TYPE##$len(this);                       \
   }                                                                            \
   template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
-    return cxxbridge03$rust_vec$##RUST_TYPE##$data(this);                      \
+    return cxxbridge04$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
-    return cxxbridge03$rust_vec$##RUST_TYPE##$stride();                        \
+    return cxxbridge04$rust_vec$##RUST_TYPE##$stride();                        \
   }
 
 // Usize and isize are the same type as one of the below.
@@ -290,7 +290,7 @@ FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge03 {
+inline namespace cxxbridge04 {
 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
-} // namespace cxxbridge03
+} // namespace cxxbridge04
 } // namespace rust
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index ffd0c5c..95d560e 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -4,9 +4,9 @@ use std::slice;
 use std::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge03$cxx_string$data"]
+    #[link_name = "cxxbridge04$cxx_string$data"]
     fn string_data(_: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge03$cxx_string$length"]
+    #[link_name = "cxxbridge04$cxx_string$length"]
     fn string_length(_: &CxxString) -> usize;
 }
 
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 10853a6..a7d3f2f 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -139,7 +139,7 @@ macro_rules! impl_vector_element {
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$size")]
+                        #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -148,7 +148,7 @@ macro_rules! impl_vector_element {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -157,7 +157,7 @@ macro_rules! impl_vector_element {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$null")]
+                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -168,7 +168,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$raw")]
+                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -179,7 +179,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$get")]
+                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -188,7 +188,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$release")]
+                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -197,7 +197,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$drop")]
+                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
diff --git a/src/result.rs b/src/result.rs
index 0373bd8..72c4959 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -32,7 +32,7 @@ unsafe fn to_c_error(msg: String) -> Result {
     let len = msg.len();
 
     extern "C" {
-        #[link_name = "cxxbridge03$error"]
+        #[link_name = "cxxbridge04$error"]
         fn error(ptr: *const u8, len: usize) -> *const u8;
     }
 
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index 849db3b..7484d1c 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -1,6 +1,6 @@
 use std::slice;
 
-#[export_name = "cxxbridge03$exception"]
+#[export_name = "cxxbridge04$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
     let slice = slice::from_raw_parts(ptr, len);
     let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 6dc04ac..5111c6a 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,7 +1,7 @@
 use std::slice;
 use std::str;
 
-#[export_name = "cxxbridge03$str$valid"]
+#[export_name = "cxxbridge04$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index d8e0f4a..94b2110 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -8,17 +8,17 @@ pub(crate) struct RustString {
     repr: String,
 }
 
-#[export_name = "cxxbridge03$string$new"]
+#[export_name = "cxxbridge04$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge03$string$clone"]
+#[export_name = "cxxbridge04$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge03$string$from"]
+#[export_name = "cxxbridge04$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -34,17 +34,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge03$string$drop"]
+#[export_name = "cxxbridge04$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge03$string$ptr"]
+#[export_name = "cxxbridge04$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge03$string$len"]
+#[export_name = "cxxbridge04$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 5465471..5081ec3 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -21,31 +21,31 @@ macro_rules! rust_vec_shims {
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$new")]
+                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec { repr: Vec::new() });
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$drop")]
+                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$len")]
+                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).repr.len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$data")]
+                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge03$rust_vec$", $segment, "$stride")]
+                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 34a1f0e..0428b5f 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -174,15 +174,15 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge03$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge04$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge03$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge04$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge03$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge04$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge03$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge04$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge03$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge04$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index c9392db..1c8c917 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -3,7 +3,7 @@ use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::ExternFn;
 use proc_macro2::Ident;
 
-const CXXBRIDGE: &str = "cxxbridge03";
+const CXXBRIDGE: &str = "cxxbridge04";
 
 macro_rules! join {
     ($($segment:expr),*) => {
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 066d238..c8500b9 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -4,7 +4,7 @@ use quote::ToTokens;
 use std::fmt::{self, Display, Write};
 
 // A mangled symbol consisting of segments separated by '$'.
-// For example: cxxbridge03$string$new
+// For example: cxxbridge04$string$new
 pub struct Symbol(String);
 
 impl Display for Symbol {

From 5f3fb89a2a71931ab911c0cf0dd17c72bfd60e5d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 06:03:46 +0000
Subject: [PATCH 830/2232] Release 0.4.0


---

diff --git a/Cargo.toml b/Cargo.toml
index 2513633..510623f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.3.9" # remember to update html_root_url
+version = "0.4.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.3.9", path = "macro" }
+cxxbridge-macro = { version = "=0.4.0", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.3.9", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.0", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.3.9", path = "gen/build" }
+cxx-build = { version = "=0.4.0", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/README.md b/README.md
index 9c65df6..5a4af1b 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ can be 100% safe.
 
 ```toml
 [dependencies]
-cxx = "0.3"
+cxx = "0.4"
 ```
 
 *Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
@@ -219,7 +219,7 @@ set up any additional source files and compiler flags as normal.
 # Cargo.toml
 
 [build-dependencies]
-cxx-build = "0.3"
+cxx-build = "0.4"
 ```
 
 ```rust
@@ -307,11 +307,11 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.3/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 5bff819..9fefd37 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.3.9"
+version = "0.4.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index eed5281..c23e82a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.3.9"
+version = "0.4.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 68ec3ec..6528cf0 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.3.9"
+version = "0.4.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index b273229..be24ab3 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.3.9"
+version = "0.4.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -19,7 +19,7 @@ quote = "1.0.4"
 syn = { version = "1.0.20", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.3", path = ".." }
+cxx = { version = "0.4", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index bbd79f3..1e76581 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -228,7 +228,7 @@
 //! # Cargo.toml
 //!
 //! [build-dependencies]
-//! cxx-build = "0.3"
+//! cxx-build = "0.4"
 //! ```
 //!
 //! ```no_run
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.3.9")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.0")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b335d31..f1ec3e0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.3.9"
+version = "0.4.0"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.3.9"
+version = "0.4.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.3.9"
+version = "0.4.0"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.3.9"
+version = "0.4.0"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.3.9"
+version = "0.4.0"
 dependencies = [
  "cxx",
  "proc-macro2",

From 1c7597933de540b1adfa07130eccf7331b0d81b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:16:28 +0000
Subject: [PATCH 831/2232] Move non-workflow-specific logic out of cxx-build root


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 1628510..4b81e1d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -56,10 +56,11 @@
 mod cargo;
 mod error;
 mod gen;
+mod out;
 mod paths;
 mod syntax;
 
-use crate::error::{Error, Result};
+use crate::error::Result;
 use crate::gen::error::report;
 use crate::gen::{fs, Opt};
 use crate::paths::{PathExt, TargetDir};
@@ -138,12 +139,12 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
 fn write_header(prj: &Project) {
     let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
-    let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+    let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
     if let TargetDir::Path(target_dir) = &prj.target_dir {
         let ref header_dir = target_dir.join("cxxbridge").join("rust");
         let _ = fs::create_dir_all(header_dir);
         let ref cxx_h = header_dir.join("cxx.h");
-        let _ = write(cxx_h, gen::include::HEADER.as_bytes());
+        let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
     }
 }
 
@@ -171,7 +172,7 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
 
     let ref rel_path_h = rel_path.with_appended_extension(".h");
     let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
-    write(header_path, &generated.header)?;
+    out::write(header_path, &generated.header)?;
 
     let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
     let _ = paths::symlink_or_copy(header_path, link_path);
@@ -184,30 +185,7 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
 
     let ref rel_path_cc = rel_path.with_appended_extension(".cc");
     let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
-    write(implementation_path, &generated.implementation)?;
+    out::write(implementation_path, &generated.implementation)?;
     build.file(implementation_path);
     Ok(())
 }
-
-fn write(path: &Path, content: &[u8]) -> Result<()> {
-    let mut create_dir_error = None;
-    if path.exists() {
-        if let Ok(existing) = fs::read(path) {
-            if existing == content {
-                // Avoid bumping modified time with unchanged contents.
-                return Ok(());
-            }
-        }
-        let _ = fs::remove_file(path);
-    } else {
-        let parent = path.parent().unwrap();
-        create_dir_error = fs::create_dir_all(parent).err();
-    }
-
-    match fs::write(path, content) {
-        // As long as write succeeded, ignore any create_dir_all error.
-        Ok(()) => Ok(()),
-        // If create_dir_all and write both failed, prefer the first error.
-        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
-    }
-}
diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
new file mode 100644
index 0000000..944c822
--- /dev/null
+++ b/gen/build/src/out.rs
@@ -0,0 +1,28 @@
+use crate::error::{Error, Result};
+use crate::gen::fs;
+use std::path::Path;
+
+pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
+    let path = path.as_ref();
+
+    let mut create_dir_error = None;
+    if path.exists() {
+        if let Ok(existing) = fs::read(path) {
+            if existing == content {
+                // Avoid bumping modified time with unchanged contents.
+                return Ok(());
+            }
+        }
+        let _ = fs::remove_file(path);
+    } else {
+        let parent = path.parent().unwrap();
+        create_dir_error = fs::create_dir_all(parent).err();
+    }
+
+    match fs::write(path, content) {
+        // As long as write succeeded, ignore any create_dir_all error.
+        Ok(()) => Ok(()),
+        // If create_dir_all and write both failed, prefer the first error.
+        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
+    }
+}

From a55c39460fac5e6b4c96c2b2414eaf2928c43809 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:19:28 +0000
Subject: [PATCH 832/2232] Fix error on creating symlink that already exists


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 4b81e1d..9498fe2 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -160,8 +160,7 @@ fn symlink_crate(prj: &Project, build: &mut Build) {
 
     let mut link = paths::include_dir(prj);
     link.push("CRATE");
-    let _ = fs::create_dir_all(&link);
-    let _ = paths::symlink_dir(manifest_dir, link.join(package_name));
+    let _ = out::symlink_dir(manifest_dir, link.join(package_name));
     build.include(link);
 }
 
@@ -175,12 +174,11 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     out::write(header_path, &generated.header)?;
 
     let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
-    let _ = paths::symlink_or_copy(header_path, link_path);
+    let _ = out::symlink_file(header_path, link_path);
     if let TargetDir::Path(target_dir) = &prj.target_dir {
         let ref link_path = paths::namespaced(target_dir, rel_path);
-        let _ = fs::create_dir_all(link_path.parent().unwrap());
-        let _ = paths::symlink_or_copy(header_path, link_path);
-        let _ = paths::symlink_or_copy(header_path, link_path.with_appended_extension(".h"));
+        let _ = out::symlink_file(header_path, link_path);
+        let _ = out::symlink_file(header_path, link_path.with_appended_extension(".h"));
     }
 
     let ref rel_path_cc = rel_path.with_appended_extension(".cc");
diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index 944c822..76e27f6 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -1,5 +1,6 @@
 use crate::error::{Error, Result};
 use crate::gen::fs;
+use crate::paths;
 use std::path::Path;
 
 pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
@@ -26,3 +27,43 @@ pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
         Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
     }
 }
+
+pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+
+    let mut create_dir_error = None;
+    if dst.exists() {
+        let _ = fs::remove_file(dst).unwrap();
+    } else {
+        let parent = dst.parent().unwrap();
+        create_dir_error = fs::create_dir_all(parent).err();
+    }
+
+    match paths::symlink_or_copy(src, dst) {
+        // As long as symlink_or_copy succeeded, ignore any create_dir_all error.
+        Ok(()) => Ok(()),
+        // If create_dir_all and symlink_or_copy both failed, prefer the first error.
+        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
+    }
+}
+
+pub(crate) fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+    let src = src.as_ref();
+    let dst = dst.as_ref();
+
+    let mut create_dir_error = None;
+    if dst.exists() {
+        let _ = fs::remove_file(dst).unwrap();
+    } else {
+        let parent = dst.parent().unwrap();
+        create_dir_error = fs::create_dir_all(parent).err();
+    }
+
+    match paths::symlink_dir(src, dst) {
+        // As long as symlink_dir succeeded, ignore any create_dir_all error.
+        Ok(()) => Ok(()),
+        // If create_dir_all and symlink_dir both failed, prefer the first error.
+        Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
+    }
+}

From f486d56bc18a8ae58ac43a721e2992a7903117d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:26:32 +0000
Subject: [PATCH 833/2232] Consistent signature for symlink_or_copy across platforms


---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 96e3708..d4b2ebb 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -99,7 +99,7 @@ pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
 pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
-pub(crate) fn symlink_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+pub(crate) fn symlink_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> fs::Result<()> {
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
     let src = src.as_ref();
@@ -117,6 +117,6 @@ pub(crate) use self::fs::copy as symlink_or_copy;
 pub(crate) use self::fs::symlink_dir;
 
 #[cfg(not(any(unix, windows)))]
-pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> Result<()> {
+pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> fs::Result<()> {
     Ok(())
 }
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index fe15f86..f135a8a 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -5,7 +5,7 @@ use std::fmt::{self, Display};
 use std::io;
 use std::path::{Path, PathBuf};
 
-type Result<T> = std::result::Result<T, Error>;
+pub(crate) type Result<T> = std::result::Result<T, Error>;
 
 #[derive(Debug)]
 pub(crate) struct Error {

From e61db0e4f9d0d2f2cb8d41bae58abb0f1c628712 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:38:03 +0000
Subject: [PATCH 834/2232] Fix symlink removal on windows


---

diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index 76e27f6..b97e992 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -54,7 +54,7 @@ pub(crate) fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Resul
 
     let mut create_dir_error = None;
     if dst.exists() {
-        let _ = fs::remove_file(dst).unwrap();
+        let _ = paths::remove_symlink_dir(dst).unwrap();
     } else {
         let parent = dst.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index d4b2ebb..1007730 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -120,3 +120,11 @@ pub(crate) use self::fs::symlink_dir;
 pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> fs::Result<()> {
     Ok(())
 }
+
+#[cfg(not(windows))]
+pub(crate) use self::fs::remove_file as remove_symlink_dir;
+
+// On Windows, trying to use remove_file to remove a symlink which points to a
+// directory fails with "Access is denied".
+#[cfg(windows)]
+pub(crate) use self::fs::remove_dir as remove_symlink_dir;
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index f135a8a..89965ee 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -74,6 +74,14 @@ pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
     }
 }
 
+pub(crate) fn remove_dir(path: impl AsRef<Path>) -> Result<()> {
+    let path = path.as_ref();
+    match std::fs::remove_dir(path) {
+        Ok(()) => Ok(()),
+        Err(e) => err!(e, "Failed to remove directory `{}`", path),
+    }
+}
+
 fn symlink<'a>(
     src: &'a Path,
     dst: &'a Path,

From 8745f7f5f8e547b9ebbc79dc9c10df232c99c239 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:46:06 +0000
Subject: [PATCH 835/2232] Release 0.4.1


---

diff --git a/Cargo.toml b/Cargo.toml
index 510623f..0e69aac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.0" # remember to update html_root_url
+version = "0.4.1" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.0", path = "macro" }
+cxxbridge-macro = { version = "=0.4.1", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.0", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.1", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.0", path = "gen/build" }
+cxx-build = { version = "=0.4.1", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 9fefd37..5bab2bc 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index c23e82a..6055066 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 6528cf0..bc84b98 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index be24ab3..531dbca 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 1e76581..ef5974d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.0")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.1")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f1ec3e0..4f1d809 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.0"
+version = "0.4.1"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "cxx",
  "proc-macro2",

From 9c815dfba2b29987b9e357990816a6380551034e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 16:54:19 +0000
Subject: [PATCH 836/2232] Rephrase build robustness note


---

diff --git a/README.md b/README.md
index 5a4af1b..6a7581d 100644
--- a/README.md
+++ b/README.md
@@ -343,10 +343,9 @@ This is still early days for CXX; I am releasing it as a minimum viable product
 to collect feedback on the direction and invite collaborators. Please check the
 open issues.
 
-On the build side, I don't have much experience with the `cc` crate so I expect
-there may be someone who can suggest ways to make that aspect of this crate
-friendlier or more robust. Please report issues if you run into trouble building
-or linking any of this stuff.
+Especially please report issues if you run into trouble building or linking any
+of this stuff. I'm sure there are ways to make the build aspects friendlier or
+more robust.
 
 Finally, I know more about Rust library design than C++ library design so I
 would appreciate help making the C++ APIs in this project more idiomatic where

From b75f59424cbf4e55174c34e4406dc75cc81c071a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 17:18:46 +0000
Subject: [PATCH 837/2232] Log the include directories


On build script failure, the output looks like:

    running: "c++" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-m64" "-I" "/git/cxx/target/cxxbridge" "-I" "/git/cxx/target/cxxbridge/CRATE" "-Wall" "-Wextra" "-std=c++14" "-o" "/git/cxx/target/debug/build/demo-33ada9770433c2cc/out/src/demo.o" "-c" "src/demo.cc"
    cargo:warning=src/demo.cc:2:10: fatal error: path/to/nonexistent.rs.h: No such file or directory
    cargo:warning=    2 | #include "path/to/nonexistent.rs.h"
    cargo:warning=      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
    cargo:warning=compilation terminated.
    exit code: 1

    --- stderr

    CXX include path:
      /git/cxx/target/cxxbridge
      /git/cxx/target/cxxbridge/CRATE

    error occurred: Command "c++" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-m64" "-I" "/git/cxx/target/cxxbridge" "-I" "/git/cxx/target/cxxbridge/CRATE" "-Wall" "-Wextra" "-std=c++14" "-o" "/git/cxx/target/debug/build/demo-33ada9770433c2cc/out/src/demo.o" "-c" "src/demo.cc" with args "c++" did not execute successfully (status code exit code: 1).

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 9498fe2..ef284c4 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -123,17 +123,24 @@ impl Project {
 
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
+    let include_dir = paths::include_dir(prj);
+
     let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    build.include(paths::include_dir(prj));
+    build.include(&include_dir);
     write_header(prj);
-    symlink_crate(prj, &mut build);
+    let crate_dir = symlink_crate(prj, &mut build);
 
     for path in rust_source_files {
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
+    eprintln!("\nCXX include path:");
+    eprintln!("  {}", include_dir.display());
+    if let Some(crate_dir) = crate_dir {
+        eprintln!("  {}", crate_dir.display());
+    }
     Ok(build)
 }
 
@@ -148,20 +155,21 @@ fn write_header(prj: &Project) {
     }
 }
 
-fn symlink_crate(prj: &Project, build: &mut Build) {
+fn symlink_crate(prj: &Project, build: &mut Build) -> Option<PathBuf> {
     let manifest_dir = match paths::manifest_dir() {
         Some(manifest_dir) => manifest_dir,
-        None => return,
+        None => return None,
     };
     let package_name = match paths::package_name() {
         Some(package_name) => package_name,
-        None => return,
+        None => return None,
     };
 
     let mut link = paths::include_dir(prj);
     link.push("CRATE");
     let _ = out::symlink_dir(manifest_dir, link.join(package_name));
-    build.include(link);
+    build.include(&link);
+    Some(link)
 }
 
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {

From 2d661b8480759abfca74519ecc0fe721958c249e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 18:40:05 +0000
Subject: [PATCH 838/2232] Add mdbook skeleton


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
new file mode 100644
index 0000000..c82d374
--- /dev/null
+++ b/.github/workflows/site.yml
@@ -0,0 +1,39 @@
+name: Deploy
+
+on:
+  push:
+    branches:
+      - master
+
+jobs:
+  deploy:
+    name: Deploy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Get mdBook
+        working-directory: book
+        run: |
+          export MDBOOK_VERSION="v0.4.2"
+          export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
+          export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
+          curl -Lf "${MDBOOK_URL}" | tar -xz
+
+      - name: Build
+        working-directory: book
+        run: |
+          ./mdbook build
+          echo "cxx.rs" > build/CNAME
+
+      - name: Push to gh-pages
+        working-directory: book/build
+        run: |
+          REV=$(git rev-parse --short HEAD)
+          git init
+          git remote add upstream https://x-access-token:${{secrets.GITHUB_TOKEN}}@github.com/dtolnay/cxx
+          git config user.name "CXX"
+          git config user.email "dtolnay+cxx@gmail.com"
+          git add -A .
+          git commit -qm "Website @ ${{github.repository}}@${REV}"
+          git push -q upstream HEAD:refs/heads/gh-pages --force
diff --git a/book/.gitignore b/book/.gitignore
new file mode 100644
index 0000000..690b5b8
--- /dev/null
+++ b/book/.gitignore
@@ -0,0 +1,2 @@
+/build
+/mdbook
diff --git a/book/book.toml b/book/book.toml
new file mode 100644
index 0000000..bc2e913
--- /dev/null
+++ b/book/book.toml
@@ -0,0 +1,13 @@
+[book]
+title = "CXX"
+authors = ["David Tolnay"]
+description = "Guide for the `cxx` crate, a safe approach to FFI between Rust and C++."
+
+[rust]
+edition = "2018"
+
+[build]
+build-dir = "build"
+
+[output.html]
+git-repository-url = "https://github.com/dtolnay/cxx"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
new file mode 100644
index 0000000..f3fa924
--- /dev/null
+++ b/book/src/SUMMARY.md
@@ -0,0 +1,3 @@
+# Summary
+
+[Rust ❤️ C++](about.md)
diff --git a/book/src/about.md b/book/src/about.md
new file mode 100644
index 0000000..6e63bf5
--- /dev/null
+++ b/book/src/about.md
@@ -0,0 +1 @@
+### Coming soon

From 6e043630ba6051c9e6c111e04897e8ee32a07bfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 18:49:15 +0000
Subject: [PATCH 839/2232] Rebuild site only if push touches book directory


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index c82d374..39a8e48 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -4,6 +4,8 @@ on:
   push:
     branches:
       - master
+    paths:
+      - book/**
 
 jobs:
   deploy:

From 37f36e92a6618221a723821a71f48915cd860a44 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 18:58:17 +0000
Subject: [PATCH 840/2232] Add readme for book directory


---

diff --git a/book/README.md b/book/README.md
new file mode 100644
index 0000000..e4916e0
--- /dev/null
+++ b/book/README.md
@@ -0,0 +1,9 @@
+Published automatically to https://cxx.rs from master branch.
+
+To build and view locally:
+
+- Install [mdBook]: `cargo install mdbook`.
+- Run `mdbook build` in this directory.
+- Open the generated *build/index.html*.
+
+[mdBook]: https://github.com/rust-lang/mdBook

From 99a95e66b6aa8fc8d6c7f62a30e99ddbcc542c85 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 22:15:07 +0000
Subject: [PATCH 841/2232] Fix missing unsafe_bitcopy_t definition when using Vec


 #277

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 20c63a9..b31a239 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -148,6 +148,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_vec = false;
     let mut needs_rust_fn = false;
     let mut needs_rust_isize = false;
+    let mut needs_unsafe_bitcopy = false;
     for ty in types {
         match ty {
             Type::RustBox(_) => {
@@ -160,6 +161,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 out.include.new = true;
                 out.include.type_traits = true;
                 needs_rust_vec = true;
+                needs_unsafe_bitcopy = true;
             }
             Type::Str(_) => {
                 out.include.cstdint = true;
@@ -187,7 +189,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     let mut needs_rust_error = false;
-    let mut needs_unsafe_bitcopy = false;
     let mut needs_manually_drop = false;
     let mut needs_maybe_uninit = false;
     let mut needs_trycatch = false;
@@ -248,7 +249,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    if needs_rust_string || needs_rust_vec {
+    if needs_rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
@@ -257,11 +258,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     include::write(out, needs_rust_str, "CXXBRIDGE04_RUST_STR");
     include::write(out, needs_rust_slice, "CXXBRIDGE04_RUST_SLICE");
     include::write(out, needs_rust_box, "CXXBRIDGE04_RUST_BOX");
+    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE04_RUST_BITCOPY");
     include::write(out, needs_rust_vec, "CXXBRIDGE04_RUST_VEC");
     include::write(out, needs_rust_fn, "CXXBRIDGE04_RUST_FN");
     include::write(out, needs_rust_error, "CXXBRIDGE04_RUST_ERROR");
     include::write(out, needs_rust_isize, "CXXBRIDGE04_RUST_ISIZE");
-    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE04_RUST_BITCOPY");
 
     if needs_manually_drop {
         out.next_section();

From 16ab1461832d5c7a2bbb3c1e3600bda9951b2f4a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 22:15:25 +0000
Subject: [PATCH 842/2232] Fix missing panic template when using Vec


 #277

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b31a239..4bc633f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -141,6 +141,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
+    let mut needs_panic = false;
     let mut needs_rust_string = false;
     let mut needs_rust_str = false;
     let mut needs_rust_slice = false;
@@ -160,6 +161,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 out.include.array = true;
                 out.include.new = true;
                 out.include.type_traits = true;
+                needs_panic = true;
                 needs_rust_vec = true;
                 needs_unsafe_bitcopy = true;
             }
@@ -233,7 +235,8 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge04");
 
-    if needs_rust_string
+    if needs_panic
+        || needs_rust_string
         || needs_rust_str
         || needs_rust_slice
         || needs_rust_box
@@ -249,6 +252,8 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
+    include::write(out, needs_panic, "CXXBRIDGE04_PANIC");
+
     if needs_rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
diff --git a/include/cxx.h b/include/cxx.h
index f050248..23e7959 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -283,8 +283,11 @@ using try_fn = TryFn<Signature>;
 ////////////////////////////////////////////////////////////////////////////////
 /// end public API, begin implementation details
 
+#ifndef CXXBRIDGE04_PANIC
+#define CXXBRIDGE04_PANIC
 template <typename Exception>
 void panic [[noreturn]] (const char *msg);
+#endif // CXXBRIDGE04_PANIC
 
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {

From c0e07dc63cb53d952a44141afb0c97de65c85f6d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 22:39:28 +0000
Subject: [PATCH 843/2232] Accept `-` to mean stdin in command line code generator


---

diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 89965ee..8f94f00 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -2,7 +2,7 @@
 
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
+use std::io::{self, Read};
 use std::path::{Path, PathBuf};
 
 pub(crate) type Result<T> = std::result::Result<T, Error>;
@@ -66,6 +66,14 @@ pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
     }
 }
 
+pub(crate) fn read_stdin() -> Result<Vec<u8>> {
+    let mut bytes = Vec::new();
+    match io::stdin().read_to_end(&mut bytes) {
+        Ok(_len) => Ok(bytes),
+        Err(e) => err!(e, "Failed to read input from stdin"),
+    }
+}
+
 pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
     let path = path.as_ref();
     match std::fs::remove_file(path) {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index f4d643d..9578fe8 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -80,7 +80,11 @@ pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
 }
 
 fn read_to_string(path: &Path) -> Result<String> {
-    let bytes = fs::read(path)?;
+    let bytes = if path == Path::new("-") {
+        fs::read_stdin()
+    } else {
+        fs::read(path)
+    }?;
     match String::from_utf8(bytes) {
         Ok(string) => Ok(string),
         Err(err) => Err(Error::Utf8(path.to_owned(), err.utf8_error())),

From ecdec70e490eb9ff0b1513a2d54e15005396fd47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 22:53:33 +0000
Subject: [PATCH 844/2232] Merge pull request #279 from dtolnay/stdin


Accept `-` to mean stdin in command line code generator
---

diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 89965ee..8f94f00 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -2,7 +2,7 @@
 
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
-use std::io;
+use std::io::{self, Read};
 use std::path::{Path, PathBuf};
 
 pub(crate) type Result<T> = std::result::Result<T, Error>;
@@ -66,6 +66,14 @@ pub(crate) fn read(path: impl AsRef<Path>) -> Result<Vec<u8>> {
     }
 }
 
+pub(crate) fn read_stdin() -> Result<Vec<u8>> {
+    let mut bytes = Vec::new();
+    match io::stdin().read_to_end(&mut bytes) {
+        Ok(_len) => Ok(bytes),
+        Err(e) => err!(e, "Failed to read input from stdin"),
+    }
+}
+
 pub(crate) fn remove_file(path: impl AsRef<Path>) -> Result<()> {
     let path = path.as_ref();
     match std::fs::remove_file(path) {
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index f4d643d..9578fe8 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -80,7 +80,11 @@ pub(super) fn generate_from_path(path: &Path, opt: &Opt) -> GeneratedCode {
 }
 
 fn read_to_string(path: &Path) -> Result<String> {
-    let bytes = fs::read(path)?;
+    let bytes = if path == Path::new("-") {
+        fs::read_stdin()
+    } else {
+        fs::read(path)
+    }?;
     match String::from_utf8(bytes) {
         Ok(string) => Ok(string),
         Err(err) => Err(Error::Utf8(path.to_owned(), err.utf8_error())),

From e0b6c735e8544cf1dc34e2bb6999a8af33f773b9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 02 2020 22:54:12 +0000
Subject: [PATCH 845/2232] Release 0.4.2


---

diff --git a/Cargo.toml b/Cargo.toml
index 0e69aac..9f23252 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.1" # remember to update html_root_url
+version = "0.4.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.1", path = "macro" }
+cxxbridge-macro = { version = "=0.4.2", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.1", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.2", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.1", path = "gen/build" }
+cxx-build = { version = "=0.4.2", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 5bab2bc..6499add 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.1"
+version = "0.4.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 6055066..f41ea6e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.1"
+version = "0.4.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index bc84b98..250fe6d 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.1"
+version = "0.4.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 531dbca..dae4c59 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.1"
+version = "0.4.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index ef5974d..8d874bd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.1")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.2")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4f1d809..db84aaa 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.1"
+version = "0.4.2"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.1"
+version = "0.4.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.1"
+version = "0.4.2"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.1"
+version = "0.4.2"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.1"
+version = "0.4.2"
 dependencies = [
  "cxx",
  "proc-macro2",

From 91489ec3137c48e9ada88a4b7a0a51fda8308b11 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 03 2020 19:48:49 +0000
Subject: [PATCH 846/2232] Avoid printing completely empty output


Running `cxxbridge` and having it exit 0 with nothing outputed is
confusing and can look to the caller like a bug.

---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index dbb1d73..d42ea74 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -57,13 +57,16 @@ impl OutFile {
     pub fn content(&self) -> Vec<u8> {
         let front = &self.front.bytes;
         let content = &self.content.borrow().bytes;
-        let len = front.len() + !front.is_empty() as usize + content.len();
+        let len = front.len() + content.len() + 1;
         let mut out = String::with_capacity(len);
         out.push_str(front);
-        if !front.is_empty() {
+        if !front.is_empty() && !content.is_empty() {
             out.push('\n');
         }
         out.push_str(content);
+        if out.is_empty() {
+            out.push_str("// empty\n");
+        }
         out.into_bytes()
     }
 }

From c5cd7a1325c27010e7d2934dc4dc3dda7e29f5a3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 03 2020 22:32:34 +0000
Subject: [PATCH 847/2232] Show cxx-build dependency in readme


---

diff --git a/README.md b/README.md
index 6a7581d..38fe682 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,9 @@ can be 100% safe.
 ```toml
 [dependencies]
 cxx = "0.4"
+
+[build-dependencies]
+cxx-build = "0.4"
 ```
 
 *Compiler support: requires rustc 1.42+ and c++11 or newer*<br>

From d7fef0a16265f01bcaf79bf3156190efca9cbf35 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 05 2020 06:28:56 +0000
Subject: [PATCH 848/2232] Update ui tests to nightly-2020-09-05


---

diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 366a8f4..9818e44 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -5,7 +5,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   |         -----^^^^^-
   |         |    |
   |         |    doesn't have a size known at compile-time
-  |         required by this bound in `ffi::_::__AssertSized`
+  |         required by this bound in `__AssertSized`
   |
-  = help: within `TypeR`, the trait `std::marker::Sized` is not implemented for `str`
+  = help: within `TypeR`, the trait `Sized` is not implemented for `str`
   = note: required because it appears within the type `TypeR`
diff --git a/tests/ui/wrong_type_id.stderr b/tests/ui/wrong_type_id.stderr
index e448a22..2d8e50a 100644
--- a/tests/ui/wrong_type_id.stderr
+++ b/tests/ui/wrong_type_id.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<here::StringPiece as cxx::ExternType>::Id == (cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
+error[E0271]: type mismatch resolving `<StringPiece as ExternType>::Id == (f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)`
    --> $DIR/wrong_type_id.rs:11:9
     |
 11  |         type ByteRange = crate::here::StringPiece;
@@ -7,7 +7,7 @@ error[E0271]: type mismatch resolving `<here::StringPiece as cxx::ExternType>::I
    ::: $WORKSPACE/src/extern_type.rs
     |
     | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
-    |                                         ------- required by this bound in `cxx::private::verify_extern_type`
+    |                                         ------- required by this bound in `verify_extern_type`
     |
-    = note: expected tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::B, cxx::y, cxx::t, cxx::e, cxx::R, cxx::a, cxx::n, cxx::g, cxx::e)`
-               found tuple `(cxx::f, cxx::o, cxx::l, cxx::l, cxx::y, (), cxx::S, cxx::t, cxx::r, cxx::i, cxx::n, cxx::g, cxx::P, cxx::i, cxx::e, cxx::c, cxx::e)`
+    = note: expected tuple `(f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)`
+               found tuple `(f, o, l, l, y, (), S, t, r, i, n, g, P, i, e, c, e)`

From d003628ffa199e7144da6d84025084cb7d6cde43 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 05 2020 23:15:04 +0000
Subject: [PATCH 849/2232] Don't mark trycatch since it is not from cxx.h


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4bc633f..68d8775 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -247,7 +247,6 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         || needs_unsafe_bitcopy
         || needs_manually_drop
         || needs_maybe_uninit
-        || needs_trycatch
     {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }

From 6c5ce84f0ca9d0d6a14130455b4a646098b4ff92 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 03:10:25 +0000
Subject: [PATCH 850/2232] Remove duplicated attr macro


This is already present in src/macros/concat.rs.

---

diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 5081ec3..163f7a9 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -7,13 +7,6 @@ pub(crate) struct RustVec<T> {
     repr: Vec<T>,
 }
 
-macro_rules! attr {
-    (#[$name:ident = $value:expr] $($rest:tt)*) => {
-        #[$name = $value]
-        $($rest)*
-    };
-}
-
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
         const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());

From 4d0bf3312adb56b8cbec8e457d267aac68cf99a2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 04:14:36 +0000
Subject: [PATCH 851/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 86e8e72..904b5c1 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -40,7 +40,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.20/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.39/src/**"]),
+    srcs = glob(["vendor/syn-1.0.40/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 7ceec9b..c9f3e0c 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -45,7 +45,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.19/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.20/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -69,7 +69,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.39/src/**"]),
+    srcs = glob(["vendor/syn-1.0.40/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index db84aaa..532ceff 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -186,9 +186,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.19"
+version = "1.0.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
+checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"
 dependencies = [
  "unicode-xid",
 ]
@@ -258,9 +258,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.39"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9"
+checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
 dependencies = [
  "proc-macro2",
  "quote",

From 83f71155f2a19237336d3ca03704b70d73e40fe9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 04:15:06 +0000
Subject: [PATCH 852/2232] Linearize cycle dependency between cxx crate and cxx.cc


---

diff --git a/BUCK b/BUCK
index 0dfa11b..5f2a65f 100644
--- a/BUCK
+++ b/BUCK
@@ -2,10 +2,10 @@ rust_library(
     name = "cxx",
     srcs = glob(["src/**"], exclude = ["src/symbols/**"]),
     visibility = ["PUBLIC"],
-    rustc_flags = ["--cfg", "no_export_symbols"],
     deps = [
         ":core",
         ":macro",
+        ":symbols",
     ],
 )
 
@@ -37,8 +37,7 @@ cxx_library(
 
 rust_library(
     name = "symbols",
-    srcs = glob(["src/macros/**", "src/symbols/**"]),
-    crate_root = "src/symbols/symbols.rs",
+    srcs = glob(["src/symbols/**"]),
 )
 
 rust_library(
diff --git a/BUILD b/BUILD
index 27c6931..197cef2 100644
--- a/BUILD
+++ b/BUILD
@@ -2,12 +2,18 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_library(
     name = "cxx",
-    srcs = glob(["src/**/*.rs"]),
+    srcs = glob(
+        ["src/**/*.rs"],
+        exclude = ["src/symbols/**/*.rs"],
+    ),
     proc_macro_deps = [
         ":cxxbridge-macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [":core-lib"],
+    deps = [
+        ":core-lib",
+        ":symbols",
+    ],
 )
 
 rust_binary(
@@ -39,6 +45,11 @@ cc_library(
 )
 
 rust_library(
+    name = "symbols",
+    srcs = glob(["src/symbols/**/*.rs"]),
+)
+
+rust_library(
     name = "cxxbridge-macro",
     srcs = glob(["macro/src/**"]),
     crate_type = "proc-macro",
diff --git a/Cargo.toml b/Cargo.toml
index 9f23252..6443475 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,6 +20,7 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
+cxx-symbols = { version = "=0.4.2", path = "src/symbols" }
 cxxbridge-macro = { version = "=0.4.2", path = "macro" }
 link-cplusplus = "1.0"
 
@@ -34,7 +35,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
+members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "src/symbols", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index 8d874bd..0fb7ad9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -369,9 +369,8 @@
 
 #[cfg(built_with_cargo)]
 extern crate link_cplusplus;
-
 #[macro_use]
-mod macros;
+extern crate symbols;
 
 mod cxx_string;
 mod cxx_vector;
@@ -387,9 +386,6 @@ mod rust_vec;
 mod unique_ptr;
 mod unwind;
 
-#[cfg(not(no_export_symbols))]
-mod symbols;
-
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
diff --git a/src/macros/assert.rs b/src/macros/assert.rs
deleted file mode 100644
index 738e5bb..0000000
--- a/src/macros/assert.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-macro_rules! const_assert_eq {
-    ($left:expr, $right:expr $(,)?) => {
-        const _: [(); $left] = [(); $right];
-    };
-}
diff --git a/src/macros/concat.rs b/src/macros/concat.rs
deleted file mode 100644
index e67e50d..0000000
--- a/src/macros/concat.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-macro_rules! attr {
-    (#[$name:ident = $value:expr] $($rest:tt)*) => {
-        #[$name = $value]
-        $($rest)*
-    };
-}
diff --git a/src/macros/mod.rs b/src/macros/mod.rs
deleted file mode 100644
index d12d96b..0000000
--- a/src/macros/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[macro_use]
-mod assert;
-#[macro_use]
-mod concat;
diff --git a/src/symbols/Cargo.toml b/src/symbols/Cargo.toml
new file mode 100644
index 0000000..80728d3
--- /dev/null
+++ b/src/symbols/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "cxx-symbols"
+version = "0.4.2"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+description = "Implementation detail of the `cxx` crate"
+repository = "https://github.com/dtolnay/cxx"
+documentation = "https://docs.rs/cxx"
+
+[lib]
+name = "symbols"
+path = "lib.rs"
diff --git a/src/symbols/lib.rs b/src/symbols/lib.rs
new file mode 100644
index 0000000..da0f223
--- /dev/null
+++ b/src/symbols/lib.rs
@@ -0,0 +1,9 @@
+//! *Implementation detail of the `cxx` crate.*
+
+#[macro_use]
+mod macros;
+
+mod exception;
+mod rust_str;
+mod rust_string;
+mod rust_vec;
diff --git a/src/symbols/macros/assert.rs b/src/symbols/macros/assert.rs
new file mode 100644
index 0000000..5d5ea9e
--- /dev/null
+++ b/src/symbols/macros/assert.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+#[doc(hidden)]
+macro_rules! const_assert_eq {
+    ($left:expr, $right:expr $(,)?) => {
+        const _: [(); $left] = [(); $right];
+    };
+}
diff --git a/src/symbols/macros/concat.rs b/src/symbols/macros/concat.rs
new file mode 100644
index 0000000..5ee77c5
--- /dev/null
+++ b/src/symbols/macros/concat.rs
@@ -0,0 +1,8 @@
+#[macro_export]
+#[doc(hidden)]
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
diff --git a/src/symbols/macros/mod.rs b/src/symbols/macros/mod.rs
new file mode 100644
index 0000000..d12d96b
--- /dev/null
+++ b/src/symbols/macros/mod.rs
@@ -0,0 +1,4 @@
+#[macro_use]
+mod assert;
+#[macro_use]
+mod concat;
diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs
deleted file mode 100644
index a9d158d..0000000
--- a/src/symbols/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-mod exception;
-mod rust_str;
-mod rust_string;
-mod rust_vec;
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 163f7a9..7789454 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,4 +1,4 @@
-use super::rust_string::RustString;
+use crate::rust_string::RustString;
 use std::mem;
 use std::ptr;
 
diff --git a/src/symbols/symbols.rs b/src/symbols/symbols.rs
deleted file mode 100644
index 2c052ec..0000000
--- a/src/symbols/symbols.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[path = "../macros/mod.rs"]
-#[macro_use]
-mod macros;
-
-include!("mod.rs");
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 532ceff..5c1350a 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -63,6 +63,7 @@ version = "0.4.2"
 dependencies = [
  "cc",
  "cxx-build",
+ "cxx-symbols",
  "cxx-test-suite",
  "cxxbridge-flags",
  "cxxbridge-macro",
@@ -95,6 +96,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "cxx-symbols"
+version = "0.4.2"
+
+[[package]]
 name = "cxx-test-suite"
 version = "0.0.0"
 dependencies = [

From 38c8764d821da198b3451cf9b5117ee0b638965a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 05:18:08 +0000
Subject: [PATCH 853/2232] Add rust::slice and rust::vec lowercase aliases


---

diff --git a/include/cxx.h b/include/cxx.h
index 23e7959..3744185 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -271,7 +271,11 @@ std::ostream &operator<<(std::ostream &, const Str &);
 using string = String;
 using str = Str;
 template <class T>
+using slice = Slice<T>;
+template <class T>
 using box = Box<T>;
+template <class T>
+using vec = Vec<T>;
 using error = Error;
 template <typename Signature, bool Throws = false>
 using fn = Fn<Signature, Throws>;

From dd26bd0d7990612be99967bf0685d3a2c132bdeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:00:27 +0000
Subject: [PATCH 854/2232] Move qualified path parsing to module


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index e2356e1..d6db7cb 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,6 +13,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
+mod qualified;
 pub mod report;
 pub mod set;
 pub mod symbol;
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index e2dce18..bdfb845 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,8 +1,9 @@
+use crate::syntax::qualified::QualifiedName;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
 use syn::parse::{Parse, ParseStream, Result};
-use syn::{Ident, Path, Token};
+use syn::{Ident, Token};
 
 mod kw {
     syn::custom_keyword!(namespace);
@@ -31,10 +32,7 @@ impl Parse for Namespace {
         if !input.is_empty() {
             input.parse::<kw::namespace>()?;
             input.parse::<Token![=]>()?;
-            let path = input.call(Path::parse_mod_style)?;
-            for segment in path.segments {
-                segments.push(segment.ident);
-            }
+            segments = input.call(QualifiedName::parse_unquoted)?.segments;
             input.parse::<Option<Token![,]>>()?;
         }
         Ok(Namespace { segments })
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
new file mode 100644
index 0000000..c876fa8
--- /dev/null
+++ b/syntax/qualified.rs
@@ -0,0 +1,17 @@
+use syn::parse::{ParseStream, Result};
+use syn::{Ident, Path};
+
+pub struct QualifiedName {
+    pub segments: Vec<Ident>,
+}
+
+impl QualifiedName {
+    pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
+        let path = input.call(Path::parse_mod_style)?;
+        let mut segments = Vec::with_capacity(path.segments.len());
+        for segment in path.segments {
+            segments.push(segment.ident);
+        }
+        Ok(QualifiedName { segments })
+    }
+}

From 6c9a622708a877257c030c679452b716c6a7a1e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:08:57 +0000
Subject: [PATCH 855/2232] Permit rust keywords in C++ qualified paths


---

diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index c876fa8..a340093 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -1,5 +1,6 @@
+use syn::ext::IdentExt;
 use syn::parse::{ParseStream, Result};
-use syn::{Ident, Path};
+use syn::{Ident, Token};
 
 pub struct QualifiedName {
     pub segments: Vec<Ident>,
@@ -7,10 +8,18 @@ pub struct QualifiedName {
 
 impl QualifiedName {
     pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
-        let path = input.call(Path::parse_mod_style)?;
-        let mut segments = Vec::with_capacity(path.segments.len());
-        for segment in path.segments {
-            segments.push(segment.ident);
+        let mut segments = Vec::new();
+        let mut trailing_punct = true;
+        while trailing_punct && input.peek(Ident::peek_any) {
+            let ident = Ident::parse_any(input)?;
+            segments.push(ident);
+            let colons: Option<Token![::]> = input.parse()?;
+            trailing_punct = colons.is_some();
+        }
+        if segments.is_empty() {
+            return Err(input.error("expected path"));
+        } else if trailing_punct {
+            return Err(input.error("expected path segment"));
         }
         Ok(QualifiedName { segments })
     }

From 6b65a58f567eff5c77a17be2f1f4ea0af7ef4d33 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:21:48 +0000
Subject: [PATCH 856/2232] Merge pull request #287 from dtolnay/qual


Permit rust keywords in C++ qualified paths
---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index e2356e1..d6db7cb 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,6 +13,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
+mod qualified;
 pub mod report;
 pub mod set;
 pub mod symbol;
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index e2dce18..bdfb845 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,8 +1,9 @@
+use crate::syntax::qualified::QualifiedName;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
 use syn::parse::{Parse, ParseStream, Result};
-use syn::{Ident, Path, Token};
+use syn::{Ident, Token};
 
 mod kw {
     syn::custom_keyword!(namespace);
@@ -31,10 +32,7 @@ impl Parse for Namespace {
         if !input.is_empty() {
             input.parse::<kw::namespace>()?;
             input.parse::<Token![=]>()?;
-            let path = input.call(Path::parse_mod_style)?;
-            for segment in path.segments {
-                segments.push(segment.ident);
-            }
+            segments = input.call(QualifiedName::parse_unquoted)?.segments;
             input.parse::<Option<Token![,]>>()?;
         }
         Ok(Namespace { segments })
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
new file mode 100644
index 0000000..a340093
--- /dev/null
+++ b/syntax/qualified.rs
@@ -0,0 +1,26 @@
+use syn::ext::IdentExt;
+use syn::parse::{ParseStream, Result};
+use syn::{Ident, Token};
+
+pub struct QualifiedName {
+    pub segments: Vec<Ident>,
+}
+
+impl QualifiedName {
+    pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
+        let mut segments = Vec::new();
+        let mut trailing_punct = true;
+        while trailing_punct && input.peek(Ident::peek_any) {
+            let ident = Ident::parse_any(input)?;
+            segments.push(ident);
+            let colons: Option<Token![::]> = input.parse()?;
+            trailing_punct = colons.is_some();
+        }
+        if segments.is_empty() {
+            return Err(input.error("expected path"));
+        } else if trailing_punct {
+            return Err(input.error("expected path segment"));
+        }
+        Ok(QualifiedName { segments })
+    }
+}

From bef9e6d783773b0435eae070cff4d94bb9b2e8d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:21:55 +0000
Subject: [PATCH 857/2232] Allow namespace to be given as a quoted string


---

diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index bdfb845..49b31d1 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -32,7 +32,9 @@ impl Parse for Namespace {
         if !input.is_empty() {
             input.parse::<kw::namespace>()?;
             input.parse::<Token![=]>()?;
-            segments = input.call(QualifiedName::parse_unquoted)?.segments;
+            segments = input
+                .call(QualifiedName::parse_quoted_or_unquoted)?
+                .segments;
             input.parse::<Option<Token![,]>>()?;
         }
         Ok(Namespace { segments })
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index a340093..be9bceb 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -1,6 +1,6 @@
 use syn::ext::IdentExt;
 use syn::parse::{ParseStream, Result};
-use syn::{Ident, Token};
+use syn::{Ident, LitStr, Token};
 
 pub struct QualifiedName {
     pub segments: Vec<Ident>,
@@ -23,4 +23,13 @@ impl QualifiedName {
         }
         Ok(QualifiedName { segments })
     }
+
+    pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> {
+        if input.peek(LitStr) {
+            let lit: LitStr = input.parse()?;
+            lit.parse_with(Self::parse_unquoted)
+        } else {
+            Self::parse_unquoted(input)
+        }
+    }
 }

From 3b4efdc62a614f22536532e63dd67eb6a6d8fd23 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:30:13 +0000
Subject: [PATCH 858/2232] Merge pull request #288 from dtolnay/quoted


Allow namespace to be given as a quoted string
---

diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index bdfb845..49b31d1 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -32,7 +32,9 @@ impl Parse for Namespace {
         if !input.is_empty() {
             input.parse::<kw::namespace>()?;
             input.parse::<Token![=]>()?;
-            segments = input.call(QualifiedName::parse_unquoted)?.segments;
+            segments = input
+                .call(QualifiedName::parse_quoted_or_unquoted)?
+                .segments;
             input.parse::<Option<Token![,]>>()?;
         }
         Ok(Namespace { segments })
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index a340093..be9bceb 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -1,6 +1,6 @@
 use syn::ext::IdentExt;
 use syn::parse::{ParseStream, Result};
-use syn::{Ident, Token};
+use syn::{Ident, LitStr, Token};
 
 pub struct QualifiedName {
     pub segments: Vec<Ident>,
@@ -23,4 +23,13 @@ impl QualifiedName {
         }
         Ok(QualifiedName { segments })
     }
+
+    pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> {
+        if input.peek(LitStr) {
+            let lit: LitStr = input.parse()?;
+            lit.parse_with(Self::parse_unquoted)
+        } else {
+            Self::parse_unquoted(input)
+        }
+    }
 }

From a8d94a110f467721606d5473a10fd9fdbe5c0054 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:30:24 +0000
Subject: [PATCH 859/2232] Accept unquoted path in type_id macro


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index c2ad38b..fae874a 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -15,8 +15,10 @@ mod type_id;
 
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
+use crate::syntax::qualified::QualifiedName;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, LitStr};
+use syn::parse::{Parse, ParseStream, Result};
+use syn::parse_macro_input;
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -50,6 +52,14 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
 
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
-    let arg = parse_macro_input!(input as LitStr);
-    type_id::expand(arg).into()
+    struct TypeId(QualifiedName);
+
+    impl Parse for TypeId {
+        fn parse(input: ParseStream) -> Result<Self> {
+            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
+        }
+    }
+
+    let arg = parse_macro_input!(input as TypeId);
+    type_id::expand(arg.0).into()
 }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 445da2b..5c5d9cc 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,16 +1,16 @@
+use crate::syntax::qualified::QualifiedName;
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use syn::LitStr;
 
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
-pub fn expand(arg: LitStr) -> TokenStream {
+pub fn expand(arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();
 
-    for word in arg.value().split("::") {
+    for word in arg.segments {
         if !ids.is_empty() {
             ids.push(quote!(()));
         }
-        for ch in word.chars() {
+        for ch in word.to_string().chars() {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index d6db7cb..03422d1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,7 +13,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
-mod qualified;
+pub mod qualified;
 pub mod report;
 pub mod set;
 pub mod symbol;

From c4f0ad9b5eed8bb9d9ca3f2887e0a1fd75c5cc67 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:38:26 +0000
Subject: [PATCH 860/2232] Merge pull request #289 from dtolnay/unquoted


Accept unquoted path in type_id macro
---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index c2ad38b..fae874a 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -15,8 +15,10 @@ mod type_id;
 
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
+use crate::syntax::qualified::QualifiedName;
 use proc_macro::TokenStream;
-use syn::{parse_macro_input, LitStr};
+use syn::parse::{Parse, ParseStream, Result};
+use syn::parse_macro_input;
 
 /// `#[cxx::bridge] mod ffi { ... }`
 ///
@@ -50,6 +52,14 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
 
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
-    let arg = parse_macro_input!(input as LitStr);
-    type_id::expand(arg).into()
+    struct TypeId(QualifiedName);
+
+    impl Parse for TypeId {
+        fn parse(input: ParseStream) -> Result<Self> {
+            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
+        }
+    }
+
+    let arg = parse_macro_input!(input as TypeId);
+    type_id::expand(arg.0).into()
 }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 445da2b..5c5d9cc 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,16 +1,16 @@
+use crate::syntax::qualified::QualifiedName;
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use syn::LitStr;
 
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
-pub fn expand(arg: LitStr) -> TokenStream {
+pub fn expand(arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();
 
-    for word in arg.value().split("::") {
+    for word in arg.segments {
         if !ids.is_empty() {
             ids.push(quote!(()));
         }
-        for ch in word.chars() {
+        for ch in word.to_string().chars() {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index d6db7cb..03422d1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,7 +13,7 @@ mod impls;
 pub mod mangle;
 pub mod namespace;
 mod parse;
-mod qualified;
+pub mod qualified;
 pub mod report;
 pub mod set;
 pub mod symbol;

From bdb576ca61c53c859a7fbd0892bba877533b2ec1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:45:55 +0000
Subject: [PATCH 861/2232] Parse unsafety on function signatures


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index c34e3e5..ebebb3e 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -149,6 +149,7 @@ impl Eq for Signature {}
 impl PartialEq for Signature {
     fn eq(&self, other: &Signature) -> bool {
         let Signature {
+            unsafety,
             fn_token: _,
             receiver,
             args,
@@ -158,6 +159,7 @@ impl PartialEq for Signature {
             throws_tokens: _,
         } = self;
         let Signature {
+            unsafety: unsafety2,
             fn_token: _,
             receiver: receiver2,
             args: args2,
@@ -166,7 +168,8 @@ impl PartialEq for Signature {
             paren_token: _,
             throws_tokens: _,
         } = other;
-        receiver == receiver2
+        unsafety.is_some() == unsafety2.is_some()
+            && receiver == receiver2
             && ret == ret2
             && throws == throws2
             && args.len() == args2.len()
@@ -177,6 +180,7 @@ impl PartialEq for Signature {
 impl Hash for Signature {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Signature {
+            unsafety,
             fn_token: _,
             receiver,
             args,
@@ -185,6 +189,7 @@ impl Hash for Signature {
             paren_token: _,
             throws_tokens: _,
         } = self;
+        unsafety.is_some().hash(state);
         receiver.hash(state);
         for arg in args {
             arg.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 03422d1..f52a582 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -87,6 +87,7 @@ pub struct TypeAlias {
 }
 
 pub struct Signature {
+    pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
     pub receiver: Option<Receiver>,
     pub args: Punctuated<Var, Token![,]>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 415b802..3ac5304 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -353,6 +353,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let doc = attrs::parse_doc(cx, &foreign_fn.attrs);
+    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = foreign_fn.sig.ident.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -367,6 +368,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
         doc,
         ident,
         sig: Signature {
+            unsafety,
             fn_token,
             receiver,
             args,
@@ -578,6 +580,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
     let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
+        unsafety: ty.unsafety,
         fn_token: ty.fn_token,
         receiver: None,
         args,

From e67bcf59fc6e1698ff7625bfda273d2e2b5ab00a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 06:50:44 +0000
Subject: [PATCH 862/2232] Expand unsafety on extern C++ functions


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2f797b0..879431e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -399,17 +399,19 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     }
     .unwrap_or(call);
+    let mut dispatch = quote!(#setup #expr);
+    let unsafety = &efn.sig.unsafety;
+    if unsafety.is_none() {
+        dispatch = quote!(unsafe { #dispatch });
+    }
     let function_shim = quote! {
         #doc
-        pub fn #ident(#(#all_args,)*) #ret {
+        pub #unsafety fn #ident(#(#all_args,)*) #ret {
             extern "C" {
                 #decl
             }
             #trampolines
-            unsafe {
-                #setup
-                #expr
-            }
+            #dispatch
         }
     };
     match &efn.receiver {

From 430b5de1ff6b4cc010823ae7a98535d7d241e8fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 07 2020 07:00:23 +0000
Subject: [PATCH 863/2232] Release 0.4.3


---

diff --git a/Cargo.toml b/Cargo.toml
index 6443475..a2aaf8a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.2" # remember to update html_root_url
+version = "0.4.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,16 +20,16 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxx-symbols = { version = "=0.4.2", path = "src/symbols" }
-cxxbridge-macro = { version = "=0.4.2", path = "macro" }
+cxx-symbols = { version = "=0.4.3", path = "src/symbols" }
+cxxbridge-macro = { version = "=0.4.3", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.2", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.3", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.2", path = "gen/build" }
+cxx-build = { version = "=0.4.3", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 6499add..afae446 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index f41ea6e..acd2c3a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 250fe6d..e0264a6 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index dae4c59..9086da6 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 0fb7ad9..8c7344b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.3")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/src/symbols/Cargo.toml b/src/symbols/Cargo.toml
index 80728d3..93283ad 100644
--- a/src/symbols/Cargo.toml
+++ b/src/symbols/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-symbols"
-version = "0.4.2"
+version = "0.4.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5c1350a..92ac6b3 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.2"
+version = "0.4.3"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.2"
+version = "0.4.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -97,7 +97,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-symbols"
-version = "0.4.2"
+version = "0.4.3"
 
 [[package]]
 name = "cxx-test-suite"
@@ -110,7 +110,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.2"
+version = "0.4.3"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -121,11 +121,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.2"
+version = "0.4.3"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.2"
+version = "0.4.3"
 dependencies = [
  "cxx",
  "proc-macro2",

From 7aa5e21ab799f689de0a94fd35a03e90e28d6745 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 08 2020 05:17:56 +0000
Subject: [PATCH 864/2232] Use lld for the buck link


---

diff --git a/.buckconfig b/.buckconfig
index 6a4626f..3e5092d 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -14,4 +14,7 @@
 
 [rust]
   default_edition = 2018
-  rustc_flags = -Crelocation-model=dynamic-no-pic --cap-lints=allow
+  rustc_flags = \
+      -Clink-arg=-fuse-ld=lld \
+      -Crelocation-model=dynamic-no-pic \
+      --cap-lints=allow
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 315bac2..b0b9d16 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,6 +61,8 @@ jobs:
           wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/v2019.10.17.01/buck-v2019.10.17.01.pex
           chmod +x bin/buck
           echo ::add-path::bin
+      - name: Install lld
+        run: sudo apt install lld
       - name: Vendor dependencies
         run: |
           cp third-party/Cargo.lock .

From 9f6c075e3ccadb38ed73b416c8eaf1122e16afde Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 08 2020 05:31:03 +0000
Subject: [PATCH 865/2232] Inline cxx-symbols crate into cxx


The separation is no longer needed for Buck when linking with lld.

---

diff --git a/BUCK b/BUCK
index 5f2a65f..695c079 100644
--- a/BUCK
+++ b/BUCK
@@ -1,11 +1,10 @@
 rust_library(
     name = "cxx",
-    srcs = glob(["src/**"], exclude = ["src/symbols/**"]),
+    srcs = glob(["src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":core",
         ":macro",
-        ":symbols",
     ],
 )
 
@@ -32,12 +31,6 @@ cxx_library(
         "cxx.h": "include/cxx.h",
     },
     exported_linker_flags = ["-lstdc++"],
-    deps = [":symbols"],
-)
-
-rust_library(
-    name = "symbols",
-    srcs = glob(["src/symbols/**"]),
 )
 
 rust_library(
diff --git a/BUILD b/BUILD
index 197cef2..27c6931 100644
--- a/BUILD
+++ b/BUILD
@@ -2,18 +2,12 @@ load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_library(
     name = "cxx",
-    srcs = glob(
-        ["src/**/*.rs"],
-        exclude = ["src/symbols/**/*.rs"],
-    ),
+    srcs = glob(["src/**/*.rs"]),
     proc_macro_deps = [
         ":cxxbridge-macro",
     ],
     visibility = ["//visibility:public"],
-    deps = [
-        ":core-lib",
-        ":symbols",
-    ],
+    deps = [":core-lib"],
 )
 
 rust_binary(
@@ -45,11 +39,6 @@ cc_library(
 )
 
 rust_library(
-    name = "symbols",
-    srcs = glob(["src/symbols/**/*.rs"]),
-)
-
-rust_library(
     name = "cxxbridge-macro",
     srcs = glob(["macro/src/**"]),
     crate_type = "proc-macro",
diff --git a/Cargo.toml b/Cargo.toml
index a2aaf8a..73539f7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,7 +20,6 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxx-symbols = { version = "=0.4.3", path = "src/symbols" }
 cxxbridge-macro = { version = "=0.4.3", path = "macro" }
 link-cplusplus = "1.0"
 
@@ -35,7 +34,7 @@ rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
 
 [workspace]
-members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "src/symbols", "tests/ffi"]
+members = ["demo", "flags", "gen/build", "gen/cmd", "gen/lib", "macro", "tests/ffi"]
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index 8c7344b..b0fe00d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -369,8 +369,9 @@
 
 #[cfg(built_with_cargo)]
 extern crate link_cplusplus;
+
 #[macro_use]
-extern crate symbols;
+mod macros;
 
 mod cxx_string;
 mod cxx_vector;
@@ -383,6 +384,7 @@ mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
+mod symbols;
 mod unique_ptr;
 mod unwind;
 
diff --git a/src/macros/assert.rs b/src/macros/assert.rs
new file mode 100644
index 0000000..5d5ea9e
--- /dev/null
+++ b/src/macros/assert.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+#[doc(hidden)]
+macro_rules! const_assert_eq {
+    ($left:expr, $right:expr $(,)?) => {
+        const _: [(); $left] = [(); $right];
+    };
+}
diff --git a/src/macros/concat.rs b/src/macros/concat.rs
new file mode 100644
index 0000000..5ee77c5
--- /dev/null
+++ b/src/macros/concat.rs
@@ -0,0 +1,8 @@
+#[macro_export]
+#[doc(hidden)]
+macro_rules! attr {
+    (#[$name:ident = $value:expr] $($rest:tt)*) => {
+        #[$name = $value]
+        $($rest)*
+    };
+}
diff --git a/src/macros/mod.rs b/src/macros/mod.rs
new file mode 100644
index 0000000..d12d96b
--- /dev/null
+++ b/src/macros/mod.rs
@@ -0,0 +1,4 @@
+#[macro_use]
+mod assert;
+#[macro_use]
+mod concat;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 5e7082a..6f1d567 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -3,7 +3,7 @@ use std::mem::ManuallyDrop;
 
 #[repr(C)]
 pub struct RustVec<T> {
-    repr: Vec<T>,
+    pub(crate) repr: Vec<T>,
 }
 
 impl<T> RustVec<T> {
diff --git a/src/symbols/Cargo.toml b/src/symbols/Cargo.toml
deleted file mode 100644
index 93283ad..0000000
--- a/src/symbols/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "cxx-symbols"
-version = "0.4.3"
-authors = ["David Tolnay <dtolnay@gmail.com>"]
-edition = "2018"
-license = "MIT OR Apache-2.0"
-description = "Implementation detail of the `cxx` crate"
-repository = "https://github.com/dtolnay/cxx"
-documentation = "https://docs.rs/cxx"
-
-[lib]
-name = "symbols"
-path = "lib.rs"
diff --git a/src/symbols/lib.rs b/src/symbols/lib.rs
deleted file mode 100644
index da0f223..0000000
--- a/src/symbols/lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//! *Implementation detail of the `cxx` crate.*
-
-#[macro_use]
-mod macros;
-
-mod exception;
-mod rust_str;
-mod rust_string;
-mod rust_vec;
diff --git a/src/symbols/macros/assert.rs b/src/symbols/macros/assert.rs
deleted file mode 100644
index 5d5ea9e..0000000
--- a/src/symbols/macros/assert.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#[macro_export]
-#[doc(hidden)]
-macro_rules! const_assert_eq {
-    ($left:expr, $right:expr $(,)?) => {
-        const _: [(); $left] = [(); $right];
-    };
-}
diff --git a/src/symbols/macros/concat.rs b/src/symbols/macros/concat.rs
deleted file mode 100644
index 5ee77c5..0000000
--- a/src/symbols/macros/concat.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#[macro_export]
-#[doc(hidden)]
-macro_rules! attr {
-    (#[$name:ident = $value:expr] $($rest:tt)*) => {
-        #[$name = $value]
-        $($rest)*
-    };
-}
diff --git a/src/symbols/macros/mod.rs b/src/symbols/macros/mod.rs
deleted file mode 100644
index d12d96b..0000000
--- a/src/symbols/macros/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[macro_use]
-mod assert;
-#[macro_use]
-mod concat;
diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs
new file mode 100644
index 0000000..a9d158d
--- /dev/null
+++ b/src/symbols/mod.rs
@@ -0,0 +1,4 @@
+mod exception;
+mod rust_str;
+mod rust_string;
+mod rust_vec;
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 94b2110..5c2982d 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -3,11 +3,6 @@ use std::ptr;
 use std::slice;
 use std::str;
 
-#[repr(C)]
-pub(crate) struct RustString {
-    repr: String,
-}
-
 #[export_name = "cxxbridge04$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 7789454..fb49b40 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,12 +1,8 @@
 use crate::rust_string::RustString;
+use crate::rust_vec::RustVec;
 use std::mem;
 use std::ptr;
 
-#[repr(C)]
-pub(crate) struct RustVec<T> {
-    repr: Vec<T>,
-}
-
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
         const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 92ac6b3..8a2ee25 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -63,7 +63,6 @@ version = "0.4.3"
 dependencies = [
  "cc",
  "cxx-build",
- "cxx-symbols",
  "cxx-test-suite",
  "cxxbridge-flags",
  "cxxbridge-macro",
@@ -96,10 +95,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "cxx-symbols"
-version = "0.4.3"
-
-[[package]]
 name = "cxx-test-suite"
 version = "0.0.0"
 dependencies = [

From e4fa873f5f034341b400091cd04132990fbd6738 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 08 2020 22:04:56 +0000
Subject: [PATCH 866/2232] Allow rust::Error to be caught as std::exception&


---

diff --git a/include/cxx.h b/include/cxx.h
index 3744185..3995924 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -242,7 +242,7 @@ using TryFn = Fn<Signature, true>;
 
 #ifndef CXXBRIDGE04_RUST_ERROR
 #define CXXBRIDGE04_RUST_ERROR
-class Error final : std::exception {
+class Error final : public std::exception {
 public:
   Error(const Error &);
   Error(Error &&) noexcept;

From c4ff07b964844bc081d3b630a15fcb3fcaa519d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 08 2020 22:11:17 +0000
Subject: [PATCH 867/2232] Release 0.4.4


---

diff --git a/Cargo.toml b/Cargo.toml
index 73539f7..6613014 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.3" # remember to update html_root_url
+version = "0.4.4" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.3", path = "macro" }
+cxxbridge-macro = { version = "=0.4.4", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.3", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.4", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.3", path = "gen/build" }
+cxx-build = { version = "=0.4.4", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index afae446..fa4b95f 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.3"
+version = "0.4.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index acd2c3a..ce9b206 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.3"
+version = "0.4.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e0264a6..376c9cd 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.3"
+version = "0.4.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9086da6..e5a52e4 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.3"
+version = "0.4.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index b0fe00d..8c828a3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,7 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.3")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8a2ee25..1310d03 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.3"
+version = "0.4.4"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.3"
+version = "0.4.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.3"
+version = "0.4.4"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.3"
+version = "0.4.4"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.3"
+version = "0.4.4"
 dependencies = [
  "cxx",
  "proc-macro2",

From c8870b82954fd5535fbecf4cde6a0f279fd25eae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 09 2020 15:44:39 +0000
Subject: [PATCH 868/2232] Add missing dependencies of Error


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 68d8775..8cc1b1b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -214,6 +214,8 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
             Api::RustFunction(efn) if !out.header => {
                 if efn.throws {
                     out.include.exception = true;
+                    out.include.string = true;
+                    needs_rust_str = true;
                     needs_rust_error = true;
                 }
                 for arg in &efn.args {

From 2599f88134d351da6d95ae82316f0436313ac193 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 09 2020 19:51:40 +0000
Subject: [PATCH 869/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 904b5c1..1dd5a24 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -40,7 +40,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.20/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.21/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
diff --git a/third-party/BUILD b/third-party/BUILD
index c9f3e0c..a95bbcb 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -45,7 +45,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.20/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.21/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1310d03..1c9da28 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -186,9 +186,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.20"
+version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"
+checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c"
 dependencies = [
  "unicode-xid",
 ]

From 32574467aadde0eebd01c9a52e592694c111e2be Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 11 2020 02:35:03 +0000
Subject: [PATCH 870/2232] Ignore target and Cargo.lock in any directory


---

diff --git a/.gitignore b/.gitignore
index e7499e5..b036b6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,7 @@
 /bazel-out
 /bazel-testlogs
 /buck-out
-/Cargo.lock
 /expand.cc
 /expand.rs
-/target
+Cargo.lock
+target

From cc7ced4268283e5b16c322effc9aca5c9b9372fa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 11 2020 17:39:55 +0000
Subject: [PATCH 871/2232] Detect when symlink not enabled


---

diff --git a/gen/build/build.rs b/gen/build/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/build/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/gen/cmd/build.rs b/gen/cmd/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/cmd/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/gen/lib/build.rs b/gen/lib/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/lib/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/macro/build.rs b/macro/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/macro/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}

From d4b1ceeb01a6853c860c6f1601d7a5fdd7f57e82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 11 2020 17:45:50 +0000
Subject: [PATCH 872/2232] Build script not needed for published crate


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ce9b206..0eb9874 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 376c9cd..2c548e6 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 48a4b72..db6de83 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into higher level tools."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e5a52e4..301a750 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
-exclude = ["README.md"]
+exclude = ["build.rs", "README.md"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 

From c6f5d77bba3f76438a43ed1a19cf27266de962c7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 11 2020 17:57:03 +0000
Subject: [PATCH 873/2232] Merge pull request #295 from dtolnay/detect


Detect when symlink not enabled
---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ce9b206..0eb9874 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/gen/build/build.rs b/gen/build/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/build/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 376c9cd..2c548e6 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/gen/cmd/build.rs b/gen/cmd/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/cmd/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 48a4b72..db6de83 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into higher level tools."
 repository = "https://github.com/dtolnay/cxx"
+exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/gen/lib/build.rs b/gen/lib/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/gen/lib/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e5a52e4..301a750 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
-exclude = ["README.md"]
+exclude = ["build.rs", "README.md"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
diff --git a/macro/build.rs b/macro/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/macro/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}

From e32c5027e93f57beeb3c260592e2684cadeeca02 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 03:03:05 +0000
Subject: [PATCH 874/2232] Show header name in help text same as it appears in #include


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 1092dcd..dce7a5a 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -13,7 +13,7 @@ type Arg = clap::Arg<'static, 'static>;
 const USAGE: &str = "\
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout
     cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout\
+    cxxbridge --header                Emit \"rust/cxx.h\" header to stdout\
 ";
 
 const TEMPLATE: &str = "\
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index f119189..110e319 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -6,7 +6,7 @@ https://github.com/dtolnay/cxx
 USAGE:
     cxxbridge <input>.rs              Emit .cc file for bridge to stdout
     cxxbridge <input>.rs --header     Emit .h file for bridge to stdout
-    cxxbridge --header                Emit rust/cxx.h header to stdout
+    cxxbridge --header                Emit \"rust/cxx.h\" header to stdout
 
 ARGS:
     <input>

From 9ef74ce98f2bb1f26bf2f7c76458832fdb8eab57 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 03:57:43 +0000
Subject: [PATCH 875/2232] Add -o flag to set output file for cli


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index dce7a5a..caab254 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -2,7 +2,7 @@
 #[path = "test.rs"]
 mod test;
 
-use super::Opt;
+use super::{Opt, Output};
 use clap::AppSettings;
 use std::ffi::{OsStr, OsString};
 use std::path::PathBuf;
@@ -39,6 +39,7 @@ fn app() -> App {
         .arg(arg_cxx_impl_annotations())
         .arg(arg_header())
         .arg(arg_include())
+        .arg(arg_output())
         .help_message("Print help information.")
         .version_message("Print version information.");
     if let Some(version) = option_env!("CARGO_PKG_VERSION") {
@@ -51,6 +52,7 @@ const INPUT: &str = "input";
 const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
 const HEADER: &str = "header";
 const INCLUDE: &str = "include";
+const OUTPUT: &str = "output";
 
 pub(super) fn from_args() -> Opt {
     let matches = app().get_matches();
@@ -61,6 +63,11 @@ pub(super) fn from_args() -> Opt {
         include: matches
             .values_of(INCLUDE)
             .map_or_else(Vec::new, |v| v.map(str::to_owned).collect()),
+        output: match matches.value_of_os(OUTPUT) {
+            None => Output::Stdout,
+            Some(path) if path == "-" => Output::Stdout,
+            Some(path) => Output::File(PathBuf::from(path)),
+        },
     }
 }
 
@@ -114,3 +121,16 @@ into the generated C++ code as #include lines.
         .validator_os(validate_utf8)
         .help(HELP)
 }
+
+fn arg_output() -> Arg {
+    const HELP: &str = "\
+Path of file to write as output. Output goes to stdout if -o is
+not specified.
+    ";
+    Arg::with_name(OUTPUT)
+        .long(OUTPUT)
+        .short("o")
+        .takes_value(true)
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 14b75e6..834b738 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -11,9 +11,11 @@ mod app;
 mod gen;
 mod syntax;
 
-use gen::include;
+use gen::error::{report, Result};
+use gen::{fs, include};
 use std::io::{self, Write};
 use std::path::PathBuf;
+use std::process;
 
 #[derive(Debug)]
 struct Opt {
@@ -21,13 +23,23 @@ struct Opt {
     header: bool,
     cxx_impl_annotations: Option<String>,
     include: Vec<String>,
+    output: Output,
 }
 
-fn write(content: impl AsRef<[u8]>) {
-    let _ = io::stdout().lock().write_all(content.as_ref());
+#[derive(Debug)]
+enum Output {
+    Stdout,
+    File(PathBuf),
 }
 
 fn main() {
+    if let Err(err) = try_main() {
+        let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
+        process::exit(1);
+    }
+}
+
+fn try_main() -> Result<()> {
     let opt = app::from_args();
 
     let gen = gen::Opt {
@@ -37,10 +49,24 @@ fn main() {
         gen_implementation: !opt.header,
     };
 
-    match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::generate_from_path(&input, &gen).header),
-        (Some(input), false) => write(gen::generate_from_path(&input, &gen).implementation),
-        (None, true) => write(include::HEADER),
+    let content;
+    let content = match (opt.input, opt.header) {
+        (Some(input), true) => {
+            content = gen::generate_from_path(&input, &gen).header;
+            content.as_slice()
+        }
+        (Some(input), false) => {
+            content = gen::generate_from_path(&input, &gen).implementation;
+            content.as_slice()
+        }
+        (None, true) => include::HEADER.as_bytes(),
         (None, false) => unreachable!(), // enforced by required_unless
+    };
+
+    match opt.output {
+        Output::Stdout => drop(io::stdout().write_all(content)),
+        Output::File(path) => fs::write(path, content)?,
     }
+
+    Ok(())
 }
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 110e319..76101d9 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -31,6 +31,10 @@ OPTIONS:
             parse or even require the given paths to exist; they simply go
             into the generated C++ code as #include lines.
                \x20
+    -o, --output <output>
+            Path of file to write as output. Output goes to stdout if -o is
+            not specified.
+               \x20
     -V, --version
             Print version information.
 ";

From 3dacde91e1537fce54ccce74000fd2a647464668 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 04:13:06 +0000
Subject: [PATCH 876/2232] Merge pull request #299 from dtolnay/output


Add -o flag to set output file for cli
---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index dce7a5a..caab254 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -2,7 +2,7 @@
 #[path = "test.rs"]
 mod test;
 
-use super::Opt;
+use super::{Opt, Output};
 use clap::AppSettings;
 use std::ffi::{OsStr, OsString};
 use std::path::PathBuf;
@@ -39,6 +39,7 @@ fn app() -> App {
         .arg(arg_cxx_impl_annotations())
         .arg(arg_header())
         .arg(arg_include())
+        .arg(arg_output())
         .help_message("Print help information.")
         .version_message("Print version information.");
     if let Some(version) = option_env!("CARGO_PKG_VERSION") {
@@ -51,6 +52,7 @@ const INPUT: &str = "input";
 const CXX_IMPL_ANNOTATIONS: &str = "cxx-impl-annotations";
 const HEADER: &str = "header";
 const INCLUDE: &str = "include";
+const OUTPUT: &str = "output";
 
 pub(super) fn from_args() -> Opt {
     let matches = app().get_matches();
@@ -61,6 +63,11 @@ pub(super) fn from_args() -> Opt {
         include: matches
             .values_of(INCLUDE)
             .map_or_else(Vec::new, |v| v.map(str::to_owned).collect()),
+        output: match matches.value_of_os(OUTPUT) {
+            None => Output::Stdout,
+            Some(path) if path == "-" => Output::Stdout,
+            Some(path) => Output::File(PathBuf::from(path)),
+        },
     }
 }
 
@@ -114,3 +121,16 @@ into the generated C++ code as #include lines.
         .validator_os(validate_utf8)
         .help(HELP)
 }
+
+fn arg_output() -> Arg {
+    const HELP: &str = "\
+Path of file to write as output. Output goes to stdout if -o is
+not specified.
+    ";
+    Arg::with_name(OUTPUT)
+        .long(OUTPUT)
+        .short("o")
+        .takes_value(true)
+        .validator_os(validate_utf8)
+        .help(HELP)
+}
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 14b75e6..834b738 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -11,9 +11,11 @@ mod app;
 mod gen;
 mod syntax;
 
-use gen::include;
+use gen::error::{report, Result};
+use gen::{fs, include};
 use std::io::{self, Write};
 use std::path::PathBuf;
+use std::process;
 
 #[derive(Debug)]
 struct Opt {
@@ -21,13 +23,23 @@ struct Opt {
     header: bool,
     cxx_impl_annotations: Option<String>,
     include: Vec<String>,
+    output: Output,
 }
 
-fn write(content: impl AsRef<[u8]>) {
-    let _ = io::stdout().lock().write_all(content.as_ref());
+#[derive(Debug)]
+enum Output {
+    Stdout,
+    File(PathBuf),
 }
 
 fn main() {
+    if let Err(err) = try_main() {
+        let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
+        process::exit(1);
+    }
+}
+
+fn try_main() -> Result<()> {
     let opt = app::from_args();
 
     let gen = gen::Opt {
@@ -37,10 +49,24 @@ fn main() {
         gen_implementation: !opt.header,
     };
 
-    match (opt.input, opt.header) {
-        (Some(input), true) => write(gen::generate_from_path(&input, &gen).header),
-        (Some(input), false) => write(gen::generate_from_path(&input, &gen).implementation),
-        (None, true) => write(include::HEADER),
+    let content;
+    let content = match (opt.input, opt.header) {
+        (Some(input), true) => {
+            content = gen::generate_from_path(&input, &gen).header;
+            content.as_slice()
+        }
+        (Some(input), false) => {
+            content = gen::generate_from_path(&input, &gen).implementation;
+            content.as_slice()
+        }
+        (None, true) => include::HEADER.as_bytes(),
         (None, false) => unreachable!(), // enforced by required_unless
+    };
+
+    match opt.output {
+        Output::Stdout => drop(io::stdout().write_all(content)),
+        Output::File(path) => fs::write(path, content)?,
     }
+
+    Ok(())
 }
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 110e319..76101d9 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -31,6 +31,10 @@ OPTIONS:
             parse or even require the given paths to exist; they simply go
             into the generated C++ code as #include lines.
                \x20
+    -o, --output <output>
+            Path of file to write as output. Output goes to stdout if -o is
+            not specified.
+               \x20
     -V, --version
             Print version information.
 ";

From 3384c14eedb4c21793336ab5c80931ce27abfc43 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 04:26:56 +0000
Subject: [PATCH 877/2232] Import from libcore where possible


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 95d560e..5780e3e 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,7 +1,7 @@
-use std::borrow::Cow;
-use std::fmt::{self, Debug, Display};
-use std::slice;
-use std::str::{self, Utf8Error};
+use alloc::borrow::Cow;
+use core::fmt::{self, Debug, Display};
+use core::slice;
+use core::str::{self, Utf8Error};
 
 extern "C" {
     #[link_name = "cxxbridge04$cxx_string$data"]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index a7d3f2f..78b8f20 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,9 +1,9 @@
 use crate::cxx_string::CxxString;
-use std::ffi::c_void;
-use std::fmt::{self, Display};
-use std::marker::PhantomData;
-use std::mem;
-use std::ptr;
+use core::ffi::c_void;
+use core::fmt::{self, Display};
+use core::marker::PhantomData;
+use core::mem;
+use core::ptr;
 
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
diff --git a/src/exception.rs b/src/exception.rs
index 125e484..e85bf61 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,4 +1,4 @@
-use std::fmt::{self, Debug, Display};
+use core::fmt::{self, Debug, Display};
 
 /// Exception thrown from an `extern "C"` function.
 #[derive(Debug)]
diff --git a/src/lib.rs b/src/lib.rs
index 8c828a3..fd623e8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -370,6 +370,8 @@
 #[cfg(built_with_cargo)]
 extern crate link_cplusplus;
 
+extern crate alloc;
+
 #[macro_use]
 mod macros;
 
diff --git a/src/opaque.rs b/src/opaque.rs
index 0ff6bb9..bad57e7 100644
--- a/src/opaque.rs
+++ b/src/opaque.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use core::mem;
 
 // . size = 0
 // . align = 1
diff --git a/src/result.rs b/src/result.rs
index 72c4959..8b4bb75 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,10 +1,10 @@
 use crate::exception::Exception;
 use crate::rust_str::RustStr;
-use std::fmt::Display;
-use std::ptr;
-use std::result::Result as StdResult;
-use std::slice;
-use std::str;
+use core::fmt::Display;
+use core::ptr;
+use core::result::Result as StdResult;
+use core::slice;
+use core::str;
 
 #[repr(C)]
 pub union Result {
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index f509c7f..32f8798 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -1,6 +1,6 @@
-use std::mem;
-use std::ptr::NonNull;
-use std::slice;
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
 
 // Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
 #[repr(C)]
diff --git a/src/rust_str.rs b/src/rust_str.rs
index b944ede..38e5cab 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -1,7 +1,7 @@
-use std::mem;
-use std::ptr::NonNull;
-use std::slice;
-use std::str;
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
+use core::str;
 
 // Not necessarily ABI compatible with &str. Codegen performs the translation.
 #[repr(C)]
diff --git a/src/rust_string.rs b/src/rust_string.rs
index f0d1df1..d10714b 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use core::mem;
 
 #[repr(C)]
 pub struct RustString {
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 6f1d567..3ae5d5e 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,5 +1,5 @@
 use crate::rust_string::RustString;
-use std::mem::ManuallyDrop;
+use core::mem::ManuallyDrop;
 
 #[repr(C)]
 pub struct RustVec<T> {
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index 7484d1c..7449f14 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -1,4 +1,4 @@
-use std::slice;
+use core::slice;
 
 #[export_name = "cxxbridge04$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 5111c6a..823173a 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,5 +1,5 @@
-use std::slice;
-use std::str;
+use core::slice;
+use core::str;
 
 #[export_name = "cxxbridge04$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 5c2982d..67c53e1 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -1,7 +1,7 @@
-use std::mem::{ManuallyDrop, MaybeUninit};
-use std::ptr;
-use std::slice;
-use std::str;
+use core::mem::{ManuallyDrop, MaybeUninit};
+use core::ptr;
+use core::slice;
+use core::str;
 
 #[export_name = "cxxbridge04$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index fb49b40..667296f 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,7 +1,7 @@
 use crate::rust_string::RustString;
 use crate::rust_vec::RustVec;
-use std::mem;
-use std::ptr;
+use core::mem;
+use core::ptr;
 
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 0428b5f..2a731d7 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,11 +1,11 @@
 use crate::cxx_string::CxxString;
 use crate::cxx_vector::{self, CxxVector, VectorElement};
-use std::ffi::c_void;
-use std::fmt::{self, Debug, Display};
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Deref, DerefMut};
-use std::ptr;
+use core::ffi::c_void;
+use core::fmt::{self, Debug, Display};
+use core::marker::PhantomData;
+use core::mem;
+use core::ops::{Deref, DerefMut};
+use core::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
 #[repr(C)]

From c5a52f97048e93f2d66b5ae4fe0666d27acf5096 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 04:43:29 +0000
Subject: [PATCH 878/2232] Import prelude types explicitly from alloc


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 5780e3e..2c712f1 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,4 +1,5 @@
 use alloc::borrow::Cow;
+use alloc::string::String;
 use core::fmt::{self, Debug, Display};
 use core::slice;
 use core::str::{self, Utf8Error};
diff --git a/src/exception.rs b/src/exception.rs
index e85bf61..0ffca66 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,3 +1,4 @@
+use alloc::boxed::Box;
 use core::fmt::{self, Debug, Display};
 
 /// Exception thrown from an `extern "C"` function.
diff --git a/src/lib.rs b/src/lib.rs
index fd623e8..028800b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,6 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
+#![no_std]
 #![doc(html_root_url = "https://docs.rs/cxx/0.4.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
@@ -371,6 +372,7 @@
 extern crate link_cplusplus;
 
 extern crate alloc;
+extern crate std;
 
 #[macro_use]
 mod macros;
diff --git a/src/result.rs b/src/result.rs
index 8b4bb75..296d4a2 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,5 +1,7 @@
 use crate::exception::Exception;
 use crate::rust_str::RustStr;
+use alloc::boxed::Box;
+use alloc::string::{String, ToString};
 use core::fmt::Display;
 use core::ptr;
 use core::result::Result as StdResult;
diff --git a/src/rust_string.rs b/src/rust_string.rs
index d10714b..a5fa3f4 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -1,3 +1,4 @@
+use alloc::string::String;
 use core::mem;
 
 #[repr(C)]
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 3ae5d5e..f1a7741 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,4 +1,6 @@
 use crate::rust_string::RustString;
+use alloc::string::String;
+use alloc::vec::Vec;
 use core::mem::ManuallyDrop;
 
 #[repr(C)]
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index 7449f14..da1c3f9 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -1,3 +1,5 @@
+use alloc::boxed::Box;
+use alloc::string::String;
 use core::slice;
 
 #[export_name = "cxxbridge04$exception"]
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 67c53e1..774b824 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -1,3 +1,5 @@
+use alloc::borrow::ToOwned;
+use alloc::string::String;
 use core::mem::{ManuallyDrop, MaybeUninit};
 use core::ptr;
 use core::slice;
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 667296f..2304abf 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,5 +1,6 @@
 use crate::rust_string::RustString;
 use crate::rust_vec::RustVec;
+use alloc::vec::Vec;
 use core::mem;
 use core::ptr;
 

From ca7b8d6bb748b72685a0220fdd483fa52e448184 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 14 2020 04:51:53 +0000
Subject: [PATCH 879/2232] Merge pull request #300 from dtolnay/core


Import from libcore/liballoc where possible
---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 95d560e..2c712f1 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,7 +1,8 @@
-use std::borrow::Cow;
-use std::fmt::{self, Debug, Display};
-use std::slice;
-use std::str::{self, Utf8Error};
+use alloc::borrow::Cow;
+use alloc::string::String;
+use core::fmt::{self, Debug, Display};
+use core::slice;
+use core::str::{self, Utf8Error};
 
 extern "C" {
     #[link_name = "cxxbridge04$cxx_string$data"]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index a7d3f2f..78b8f20 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,9 +1,9 @@
 use crate::cxx_string::CxxString;
-use std::ffi::c_void;
-use std::fmt::{self, Display};
-use std::marker::PhantomData;
-use std::mem;
-use std::ptr;
+use core::ffi::c_void;
+use core::fmt::{self, Display};
+use core::marker::PhantomData;
+use core::mem;
+use core::ptr;
 
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
diff --git a/src/exception.rs b/src/exception.rs
index 125e484..0ffca66 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,4 +1,5 @@
-use std::fmt::{self, Debug, Display};
+use alloc::boxed::Box;
+use core::fmt::{self, Debug, Display};
 
 /// Exception thrown from an `extern "C"` function.
 #[derive(Debug)]
diff --git a/src/lib.rs b/src/lib.rs
index 8c828a3..028800b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -348,6 +348,7 @@
 //!
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
+#![no_std]
 #![doc(html_root_url = "https://docs.rs/cxx/0.4.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
@@ -370,6 +371,9 @@
 #[cfg(built_with_cargo)]
 extern crate link_cplusplus;
 
+extern crate alloc;
+extern crate std;
+
 #[macro_use]
 mod macros;
 
diff --git a/src/opaque.rs b/src/opaque.rs
index 0ff6bb9..bad57e7 100644
--- a/src/opaque.rs
+++ b/src/opaque.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use core::mem;
 
 // . size = 0
 // . align = 1
diff --git a/src/result.rs b/src/result.rs
index 72c4959..296d4a2 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,10 +1,12 @@
 use crate::exception::Exception;
 use crate::rust_str::RustStr;
-use std::fmt::Display;
-use std::ptr;
-use std::result::Result as StdResult;
-use std::slice;
-use std::str;
+use alloc::boxed::Box;
+use alloc::string::{String, ToString};
+use core::fmt::Display;
+use core::ptr;
+use core::result::Result as StdResult;
+use core::slice;
+use core::str;
 
 #[repr(C)]
 pub union Result {
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index f509c7f..32f8798 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -1,6 +1,6 @@
-use std::mem;
-use std::ptr::NonNull;
-use std::slice;
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
 
 // Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
 #[repr(C)]
diff --git a/src/rust_str.rs b/src/rust_str.rs
index b944ede..38e5cab 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -1,7 +1,7 @@
-use std::mem;
-use std::ptr::NonNull;
-use std::slice;
-use std::str;
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
+use core::str;
 
 // Not necessarily ABI compatible with &str. Codegen performs the translation.
 #[repr(C)]
diff --git a/src/rust_string.rs b/src/rust_string.rs
index f0d1df1..a5fa3f4 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -1,4 +1,5 @@
-use std::mem;
+use alloc::string::String;
+use core::mem;
 
 #[repr(C)]
 pub struct RustString {
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 6f1d567..f1a7741 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,5 +1,7 @@
 use crate::rust_string::RustString;
-use std::mem::ManuallyDrop;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::mem::ManuallyDrop;
 
 #[repr(C)]
 pub struct RustVec<T> {
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index 7484d1c..da1c3f9 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -1,4 +1,6 @@
-use std::slice;
+use alloc::boxed::Box;
+use alloc::string::String;
+use core::slice;
 
 #[export_name = "cxxbridge04$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 5111c6a..823173a 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,5 +1,5 @@
-use std::slice;
-use std::str;
+use core::slice;
+use core::str;
 
 #[export_name = "cxxbridge04$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 5c2982d..774b824 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -1,7 +1,9 @@
-use std::mem::{ManuallyDrop, MaybeUninit};
-use std::ptr;
-use std::slice;
-use std::str;
+use alloc::borrow::ToOwned;
+use alloc::string::String;
+use core::mem::{ManuallyDrop, MaybeUninit};
+use core::ptr;
+use core::slice;
+use core::str;
 
 #[export_name = "cxxbridge04$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index fb49b40..2304abf 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,7 +1,8 @@
 use crate::rust_string::RustString;
 use crate::rust_vec::RustVec;
-use std::mem;
-use std::ptr;
+use alloc::vec::Vec;
+use core::mem;
+use core::ptr;
 
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 0428b5f..2a731d7 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,11 +1,11 @@
 use crate::cxx_string::CxxString;
 use crate::cxx_vector::{self, CxxVector, VectorElement};
-use std::ffi::c_void;
-use std::fmt::{self, Debug, Display};
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Deref, DerefMut};
-use std::ptr;
+use core::ffi::c_void;
+use core::fmt::{self, Debug, Display};
+use core::marker::PhantomData;
+use core::mem;
+use core::ops::{Deref, DerefMut};
+use core::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
 #[repr(C)]

From ffef6bc1ef173e64cf69162c780786cdb22b95d1 Mon Sep 17 00:00:00 2001
From: Nehliin <oskar.d.nehlin@gmail.com>
Date: Sep 16 2020 11:28:26 +0000
Subject: [PATCH 880/2232] Make sure MaybeUninit is part of generated code for fn returning Result


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8cc1b1b..a6f6c3e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -217,6 +217,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                     out.include.string = true;
                     needs_rust_str = true;
                     needs_rust_error = true;
+                    needs_maybe_uninit = true;
                 }
                 for arg in &efn.args {
                     if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {

From a76da172115b8a9e82e9ea6b011d16ef9bf6e2a4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 16 2020 15:55:14 +0000
Subject: [PATCH 881/2232] Merge pull request #301 from Nehliin/add-maybeuninit


Make sure MaybeUninit is part of generated code for Rust functions returning Result
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8cc1b1b..a6f6c3e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -217,6 +217,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                     out.include.string = true;
                     needs_rust_str = true;
                     needs_rust_error = true;
+                    needs_maybe_uninit = true;
                 }
                 for arg in &efn.args {
                     if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {

From da38b7c2a5ae54acbd643b1e343d094749b892f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 16 2020 15:55:24 +0000
Subject: [PATCH 882/2232] Update case of basetsd.h import to support cross compilation


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 54a359f..1688a4e 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -61,7 +61,7 @@ pub struct Includes {
     pub type_traits: bool,
     pub utility: bool,
     pub vector: bool,
-    pub base_tsd: bool,
+    pub basetsd: bool,
 }
 
 impl Includes {
@@ -122,9 +122,9 @@ impl Display for Includes {
         if self.vector {
             writeln!(f, "#include <vector>")?;
         }
-        if self.base_tsd {
+        if self.basetsd {
             writeln!(f, "#if defined(_WIN32)")?;
-            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#include <basetsd.h>")?;
             writeln!(f, "#endif")?;
         }
         Ok(())
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a6f6c3e..862be81 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -177,7 +177,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_slice = true;
             }
             ty if ty == Isize => {
-                out.include.base_tsd = true;
+                out.include.basetsd = true;
                 needs_rust_isize = true;
             }
             ty if ty == RustString => {
diff --git a/include/cxx.h b/include/cxx.h
index 3995924..b2e0eee 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -11,7 +11,7 @@
 #include <utility>
 #include <vector>
 #if defined(_WIN32)
-#include <BaseTsd.h>
+#include <basetsd.h>
 #endif
 
 namespace rust {

From f3a518e70e49e8759cad39690719c050324c295e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 16 2020 16:07:46 +0000
Subject: [PATCH 883/2232] Merge pull request #303 from dtolnay/basetsd.h


Update case of basetsd.h import to support cross compilation
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 54a359f..1688a4e 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -61,7 +61,7 @@ pub struct Includes {
     pub type_traits: bool,
     pub utility: bool,
     pub vector: bool,
-    pub base_tsd: bool,
+    pub basetsd: bool,
 }
 
 impl Includes {
@@ -122,9 +122,9 @@ impl Display for Includes {
         if self.vector {
             writeln!(f, "#include <vector>")?;
         }
-        if self.base_tsd {
+        if self.basetsd {
             writeln!(f, "#if defined(_WIN32)")?;
-            writeln!(f, "#include <BaseTsd.h>")?;
+            writeln!(f, "#include <basetsd.h>")?;
             writeln!(f, "#endif")?;
         }
         Ok(())
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a6f6c3e..862be81 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -177,7 +177,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                 needs_rust_slice = true;
             }
             ty if ty == Isize => {
-                out.include.base_tsd = true;
+                out.include.basetsd = true;
                 needs_rust_isize = true;
             }
             ty if ty == RustString => {
diff --git a/include/cxx.h b/include/cxx.h
index 3995924..b2e0eee 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -11,7 +11,7 @@
 #include <utility>
 #include <vector>
 #if defined(_WIN32)
-#include <BaseTsd.h>
+#include <basetsd.h>
 #endif
 
 namespace rust {

From e1834e6b86ba8ab3b6251d25e5c287f2b7c44b26 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 16 2020 16:10:13 +0000
Subject: [PATCH 884/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 1dd5a24..d4c77b9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.59/src/**"]),
+    srcs = glob(["vendor/cc-1.0.60/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.40/src/**"]),
+    srcs = glob(["vendor/syn-1.0.41/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index a95bbcb..e5cb808 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -12,7 +12,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.59/src/**"]),
+    srcs = glob(["vendor/cc-1.0.60/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -69,7 +69,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.40/src/**"]),
+    srcs = glob(["vendor/syn-1.0.41/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1c9da28..f6ae89d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
+checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
 
 [[package]]
 name = "clap"
@@ -171,9 +171,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.76"
+version = "0.2.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
+checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
 
 [[package]]
 name = "link-cplusplus"
@@ -221,18 +221,18 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
 
 [[package]]
 name = "serde"
-version = "1.0.115"
+version = "1.0.116"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
+checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.115"
+version = "1.0.116"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
+checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -258,9 +258,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.40"
+version = "1.0.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
+checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -296,9 +296,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.33"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48105a4deaf74163c017939b45ef7322fba46e8b17281528039b0beb04235e92"
+checksum = "b7d30fe369fd650072b352b1a9cb9587669de6b89be3b8225544012c1c45292d"
 dependencies = [
  "dissimilar",
  "glob",

From 7ff80c44e85a827fbeba4f8911000b65f2e3061e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 16 2020 16:12:02 +0000
Subject: [PATCH 885/2232] Release 0.4.5


---

diff --git a/Cargo.toml b/Cargo.toml
index 6613014..95fe14a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.4" # remember to update html_root_url
+version = "0.4.5" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.4", path = "macro" }
+cxxbridge-macro = { version = "=0.4.5", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.4", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.5", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.4", path = "gen/build" }
+cxx-build = { version = "=0.4.5", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index fa4b95f..6c58f78 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.4"
+version = "0.4.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 0eb9874..05cdc08 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.4"
+version = "0.4.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 2c548e6..e19092c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.4"
+version = "0.4.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 301a750..781cb66 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.4"
+version = "0.4.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 028800b..9efac51 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.4")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.5")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f6ae89d..8aa5a1f 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.4"
+version = "0.4.5"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.4"
+version = "0.4.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.4"
+version = "0.4.5"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.4"
+version = "0.4.5"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.4"
+version = "0.4.5"
 dependencies = [
  "cxx",
  "proc-macro2",

From ca2d3e73804b83b459c8a944fb608961b69148c9 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@google.com>
Date: Sep 19 2020 14:54:20 +0000
Subject: [PATCH 886/2232] Bump gen/lib version to match cxx.


We need to stay roughly correlated such that cargo users do not
get mismatches between `cxxbridge04$` (generated by the main cxx
crate) and `cxxbridge03$` (which is what they get when they fetch
cxx-gen 0.1 from cargo).

In other words, even if the goal is to rev this library on a
different cadence, that cadence needs to be at least as fast
as breaking changes in `cxx` itself.

---

diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index db6de83..6731d12 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.0.1"
+version = "0.4.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"

From 4b845d64885ae8170a96623c357b2fba7e05ac48 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 19 2020 15:33:12 +0000
Subject: [PATCH 887/2232] Merge pull request #306 from adetaylor/bump-gen-lib-version


Bump gen/lib version to match cxx.
---

diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index db6de83..6731d12 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.0.1"
+version = "0.4.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"

From ae3026245c8cb0255094be082fe12601c6da9ea5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 19 2020 15:34:32 +0000
Subject: [PATCH 888/2232] Raise cxx-build's dev dependency on cxx-gen


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 05cdc08..cfc1b5e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -18,7 +18,7 @@ quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
-cxx-gen = { version = "=0.0.1", path = "../lib" }
+cxx-gen = { version = "0.4", path = "../lib" }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]

From d22babaeb43d3329c6ad64d85e792792248f82ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 19 2020 15:35:20 +0000
Subject: [PATCH 889/2232] Update third-party lockfile's cxx-gen to the repo version


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8aa5a1f..199064b 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -85,7 +85,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.0.1"
+version = "0.4.0"
 dependencies = [
  "cc",
  "codespan-reporting",

From 22602b43a8156b6838511e116566daf2b32fb3a5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 21 2020 22:22:37 +0000
Subject: [PATCH 890/2232] Fix return Result<Box<T>> from Rust to C++


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 862be81..2e2b81f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -775,9 +775,11 @@ fn write_rust_function_shim_impl(
         write!(out, "extern$");
     }
     write!(out, ")");
-    if let Some(ret) = &sig.ret {
-        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-            write!(out, ")");
+    if !indirect_return {
+        if let Some(ret) = &sig.ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+                write!(out, ")");
+            }
         }
     }
     writeln!(out, ";");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 879431e..1c21770 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -580,42 +580,42 @@ fn expand_rust_function_shim_impl(
     };
     call.extend(quote! { (#(#vars),*) });
 
-    let mut expr = sig
-        .ret
-        .as_ref()
-        .and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => {
-                Some(quote!(::cxx::private::RustString::from(#call)))
-            }
-            Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
-                } else {
-                    Some(quote!(::cxx::private::RustVec::from(#call)))
-                }
+    let conversion = sig.ret.as_ref().and_then(|ret| match ret {
+        Type::Ident(ident) if ident == RustString => Some(quote!(::cxx::private::RustString::from)),
+        Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw)),
+        Type::RustVec(vec) => {
+            if vec.inner == RustString {
+                Some(quote!(::cxx::private::RustVec::from_vec_string))
+            } else {
+                Some(quote!(::cxx::private::RustVec::from))
             }
-            Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
-                },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
-                },
-                _ => None,
+        }
+        Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
+        Type::Ref(ty) => match &ty.inner {
+            Type::Ident(ident) if ident == RustString => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustString::from_ref)),
+                Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
+            },
+            Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string)),
+                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string)),
+            },
+            Type::RustVec(_) => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustVec::from_ref)),
+                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
             },
-            Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
-            Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))),
             _ => None,
-        })
-        .unwrap_or(call);
+        },
+        Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
+        Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
+        _ => None,
+    });
+
+    let mut expr = match conversion {
+        None => call,
+        Some(conversion) if !sig.throws => quote!(#conversion(#call)),
+        Some(conversion) => quote!(::std::result::Result::map(#call, #conversion)),
+    };
 
     let mut outparam = None;
     let indirect_return = indirect_return(sig, types);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d6724f5..2829fef 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -152,6 +152,7 @@ pub mod ffi {
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
+        fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
 
         fn r_return_r2(n: usize) -> Box<R2>;
@@ -334,6 +335,10 @@ fn r_try_return_primitive() -> Result<usize, Error> {
     Ok(2020)
 }
 
+fn r_try_return_box() -> Result<Box<R>, Error> {
+    Ok(Box::new(2020))
+}
+
 fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }

From 07c4832b431b5a4d04e02d3383f25f320091a55a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 21 2020 22:34:15 +0000
Subject: [PATCH 891/2232] Merge pull request #311 from dtolnay/result-box


Fix return Result<Box<T>> from Rust to C++ [v2]
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 862be81..2e2b81f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -775,9 +775,11 @@ fn write_rust_function_shim_impl(
         write!(out, "extern$");
     }
     write!(out, ")");
-    if let Some(ret) = &sig.ret {
-        if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-            write!(out, ")");
+    if !indirect_return {
+        if let Some(ret) = &sig.ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+                write!(out, ")");
+            }
         }
     }
     writeln!(out, ";");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 879431e..1c21770 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -580,42 +580,42 @@ fn expand_rust_function_shim_impl(
     };
     call.extend(quote! { (#(#vars),*) });
 
-    let mut expr = sig
-        .ret
-        .as_ref()
-        .and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => {
-                Some(quote!(::cxx::private::RustString::from(#call)))
-            }
-            Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
-                } else {
-                    Some(quote!(::cxx::private::RustVec::from(#call)))
-                }
+    let conversion = sig.ret.as_ref().and_then(|ret| match ret {
+        Type::Ident(ident) if ident == RustString => Some(quote!(::cxx::private::RustString::from)),
+        Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw)),
+        Type::RustVec(vec) => {
+            if vec.inner == RustString {
+                Some(quote!(::cxx::private::RustVec::from_vec_string))
+            } else {
+                Some(quote!(::cxx::private::RustVec::from))
             }
-            Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
-                },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
-                    Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
-                },
-                _ => None,
+        }
+        Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
+        Type::Ref(ty) => match &ty.inner {
+            Type::Ident(ident) if ident == RustString => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustString::from_ref)),
+                Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
+            },
+            Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string)),
+                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string)),
+            },
+            Type::RustVec(_) => match ty.mutability {
+                None => Some(quote!(::cxx::private::RustVec::from_ref)),
+                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
             },
-            Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
-            Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))),
             _ => None,
-        })
-        .unwrap_or(call);
+        },
+        Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
+        Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
+        _ => None,
+    });
+
+    let mut expr = match conversion {
+        None => call,
+        Some(conversion) if !sig.throws => quote!(#conversion(#call)),
+        Some(conversion) => quote!(::std::result::Result::map(#call, #conversion)),
+    };
 
     let mut outparam = None;
     let indirect_return = indirect_return(sig, types);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d6724f5..2829fef 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -152,6 +152,7 @@ pub mod ffi {
 
         fn r_try_return_void() -> Result<()>;
         fn r_try_return_primitive() -> Result<usize>;
+        fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
 
         fn r_return_r2(n: usize) -> Box<R2>;
@@ -334,6 +335,10 @@ fn r_try_return_primitive() -> Result<usize, Error> {
     Ok(2020)
 }
 
+fn r_try_return_box() -> Result<Box<R>, Error> {
+    Ok(Box::new(2020))
+}
+
 fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }

From 01894f0432d0cd943c94ad4570ab0f5c472fb0ad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 21 2020 22:35:23 +0000
Subject: [PATCH 892/2232] Update lockfile


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 199064b..50eb94c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -150,9 +150,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
+checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
 dependencies = [
  "libc",
 ]

From 71912c3f11c9a5928b6bbfd1d26bad82a1bed3f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 21 2020 22:36:26 +0000
Subject: [PATCH 893/2232] Release 0.4.6


---

diff --git a/Cargo.toml b/Cargo.toml
index 95fe14a..cab9814 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.5" # remember to update html_root_url
+version = "0.4.6" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.5", path = "macro" }
+cxxbridge-macro = { version = "=0.4.6", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.5", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.6", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.5", path = "gen/build" }
+cxx-build = { version = "=0.4.6", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 6c58f78..98cf047 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.5"
+version = "0.4.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index cfc1b5e..cfe094c 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.5"
+version = "0.4.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e19092c..ba6d28a 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.5"
+version = "0.4.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 6731d12..faa82c2 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.4.0"
+version = "0.4.1"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 781cb66..4d17d6c 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.5"
+version = "0.4.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 9efac51..8990f5b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.5")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.6")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 50eb94c..c90ed81 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.5"
+version = "0.4.6"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.5"
+version = "0.4.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -85,7 +85,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.4.0"
+version = "0.4.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.5"
+version = "0.4.6"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.5"
+version = "0.4.6"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.5"
+version = "0.4.6"
 dependencies = [
  "cxx",
  "proc-macro2",

From 3421599ff63fb13ecef493b65d606698468172ee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 22 2020 03:46:31 +0000
Subject: [PATCH 894/2232] Update to dev branch of Buck


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b0b9d16..420b7af 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -58,7 +58,8 @@ jobs:
       - name: Install Buck
         run: |
           mkdir bin
-          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/v2019.10.17.01/buck-v2019.10.17.01.pex
+          # TODO: unfork back to facebook/buck after https://github.com/facebook/buck/pull/2545 has landed
+          wget -q -O bin/buck https://jitpack.io/com/github/dtolnay/buck/3fedc3867c/buck-3fedc3867c.pex
           chmod +x bin/buck
           echo ::add-path::bin
       - name: Install lld

From a8e0534d4f96bc7f7d6347ecdfbb30448773926f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 22 2020 03:46:31 +0000
Subject: [PATCH 895/2232] Use java 11 for Buck


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 420b7af..18589f1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -53,13 +53,13 @@ jobs:
       - uses: dtolnay/rust-toolchain@stable
       - uses: actions/setup-java@v1
         with:
-          java-version: 8
+          java-version: 11
           java-package: jre
       - name: Install Buck
         run: |
           mkdir bin
           # TODO: unfork back to facebook/buck after https://github.com/facebook/buck/pull/2545 has landed
-          wget -q -O bin/buck https://jitpack.io/com/github/dtolnay/buck/3fedc3867c/buck-3fedc3867c.pex
+          wget -q -O bin/buck https://jitpack.io/com/github/dtolnay/buck/3fedc3867c/buck-3fedc3867c-java11.pex
           chmod +x bin/buck
           echo ::add-path::bin
       - name: Install lld

From 9ec5ca4d68ead93438faf66eefcce75ce1833da3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 22 2020 05:14:31 +0000
Subject: [PATCH 896/2232] Unfork Buck repo


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 18589f1..4b42fe3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -58,8 +58,7 @@ jobs:
       - name: Install Buck
         run: |
           mkdir bin
-          # TODO: unfork back to facebook/buck after https://github.com/facebook/buck/pull/2545 has landed
-          wget -q -O bin/buck https://jitpack.io/com/github/dtolnay/buck/3fedc3867c/buck-3fedc3867c-java11.pex
+          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex # dev branch from 2020.09.21
           chmod +x bin/buck
           echo ::add-path::bin
       - name: Install lld

From e4d30f2257473f375b48535cce139734502e9f60 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 12:57:22 +0000
Subject: [PATCH 897/2232] Set test size of //tests:test Bazel test


Without this:

    INFO: Analyzed 33 targets (1 packages loaded, 12 targets configured).
    INFO: Found 32 targets and 1 test target...
    INFO: Elapsed time: 0.905s, Critical Path: 0.66s
    INFO: 3 processes: 3 linux-sandbox.
    INFO: Build completed successfully, 3 total actions
    //tests:test                                                             PASSED in 0.1s
      WARNING: //tests:test: Test execution time (0.1s excluding execution overhead) outside of range for MODERATE tests. Consider setting timeout="short" or size="small".

---

diff --git a/tests/BUILD b/tests/BUILD
index 29cc79c..d35bbf7 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -2,6 +2,7 @@ load("//tools/bazel:rust.bzl", "rust_library", "rust_test")
 
 rust_test(
     name = "test",
+    size = "small",
     srcs = ["test.rs"],
     deps = [":cxx_test_suite"],
 )

From e02c8b3b982a63d116533ddbd5fcef5ebe12da7b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 12:58:09 +0000
Subject: [PATCH 898/2232] Load cc_library from @rules_cc


Buildifier warns about this now.

    Function "cc_library" is not global anymore and needs to be loaded
    from "@rules_cc//cc:defs.bzl".buildifier(native-cc)

---

diff --git a/BUILD b/BUILD
index 27c6931..4700e06 100644
--- a/BUILD
+++ b/BUILD
@@ -1,3 +1,4 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_library(
diff --git a/demo/BUILD b/demo/BUILD
index 1edc65c..03a6535 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -1,3 +1,4 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
 
 rust_binary(
diff --git a/tests/BUILD b/tests/BUILD
index d35bbf7..ba763e0 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -1,3 +1,4 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_library", "rust_test")
 
 rust_test(

From a827ef7d991268630564f65b70fd406febd0910f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:42 +0000
Subject: [PATCH 899/2232] GitHub Codespaces dev container


---

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000..e69c7fc
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,12 @@
+FROM mcr.microsoft.com/vscode/devcontainers/rust:1
+
+RUN apt-get update \
+    && export DEBIAN_FRONTEND=noninteractive \
+    && apt-get -y install --no-install-recommends openjdk-11-jdk \
+    && rustup default nightly 2>&1 \
+    && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
+    && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
+    && chmod +x bin/install-bazel bin/buck bin/buildifier \
+    && bin/install-bazel
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..bc5e979
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,19 @@
+{
+	"name": "Rust",
+	"build": {
+		"dockerfile": "Dockerfile"
+	},
+	"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
+	"settings": {
+		"terminal.integrated.shell.linux": "/bin/bash",
+		"lldb.executable": "/usr/bin/lldb",
+		"files.watcherExclude": {
+			"**/target/**": true
+		}
+	},
+	"extensions": [
+        "BazelBuild.vscode-bazel",
+		"matklad.rust-analyzer",
+        "vadimcn.vscode-lldb"
+	]
+}

From 3627f8c767b2eded3c0eaab6ea54036b9947f8f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:42 +0000
Subject: [PATCH 900/2232] Launch configuration


---

diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..244f5c4
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Run cxx demo",
+            "type": "lldb",
+            "request": "launch",
+            "cargo": {
+                "args": ["build", "--manifest-path", "demo/Cargo.toml"],
+                "filter": {
+                    "name": "demo",
+                    "kind": "bin"
+                }
+            }
+        }
+    ]
+}

From 6f511055d2c80ba82948480a7236455373fd9341 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:42 +0000
Subject: [PATCH 901/2232] Exclude target dir from search


---

diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..8a1c2c1
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+    "search.exclude": {
+        "**/target": true
+    }
+}

From 1cef990a2d2c95d2af439b67305f4b3dc9f00bce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:42 +0000
Subject: [PATCH 902/2232] Install lld in devcontainer


---

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index e69c7fc..b938bda 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -2,7 +2,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/rust:1
 
 RUN apt-get update \
     && export DEBIAN_FRONTEND=noninteractive \
-    && apt-get -y install --no-install-recommends openjdk-11-jdk \
+    && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
     && rustup default nightly 2>&1 \
     && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
     && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \

From 0638d09ddb7231bcb3ae59c10579b08d5d883ab5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:42 +0000
Subject: [PATCH 903/2232] Install watchman in devcontainer


---

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index b938bda..d4ab609 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -8,5 +8,11 @@ RUN apt-get update \
     && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
     && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
     && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
+    && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
     && chmod +x bin/install-bazel bin/buck bin/buildifier \
-    && bin/install-bazel
+    && bin/install-bazel \
+    && unzip tmp/watchman.zip -d tmp \
+    && mv tmp/watchman-v2020.09.21.00-linux/bin/watchman bin \
+    && mv tmp/watchman-v2020.09.21.00-linux/lib/* /usr/local/lib \
+    && mkdir -p /usr/local/var/run/watchman \
+    && rm tmp/watchman.zip

From da37e50cff7774aa10be715886aac7735aed31cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:43 +0000
Subject: [PATCH 904/2232] Add test tasks


---

diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..44a2ab7
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,30 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "Cargo test",
+            "type": "shell",
+            "command": "cargo test",
+            "group": "test"
+        },
+        {
+            "label": "Bazel test",
+            "type": "shell",
+            "command": "bazel test ...",
+            "group": "test",
+            "dependsOn": ["Vendor"]
+        },
+        {
+            "label": "Buck test",
+            "type": "shell",
+            "command": "buck test ...",
+            "group": "test",
+            "dependsOn": ["Vendor"]
+        },
+        {
+            "label": "Vendor",
+            "type": "shell",
+            "command": "cp third-party/Cargo.lock . && cargo vendor --versioned-dirs --locked third-party/vendor"
+        }
+    ]
+}

From a9a83ab96d4e38d8c5222e1366b5f6623530d22c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:04:43 +0000
Subject: [PATCH 905/2232] Push container to Docker Hub


---

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index d4ab609..93cfc05 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,18 +1 @@
-FROM mcr.microsoft.com/vscode/devcontainers/rust:1
-
-RUN apt-get update \
-    && export DEBIAN_FRONTEND=noninteractive \
-    && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
-    && rustup default nightly 2>&1 \
-    && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
-    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
-    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
-    && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
-    && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
-    && chmod +x bin/install-bazel bin/buck bin/buildifier \
-    && bin/install-bazel \
-    && unzip tmp/watchman.zip -d tmp \
-    && mv tmp/watchman-v2020.09.21.00-linux/bin/watchman bin \
-    && mv tmp/watchman-v2020.09.21.00-linux/lib/* /usr/local/lib \
-    && mkdir -p /usr/local/var/run/watchman \
-    && rm tmp/watchman.zip
+FROM dtolnay/devcontainer:latest
diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
new file mode 100644
index 0000000..d4ab609
--- /dev/null
+++ b/.devcontainer/build.Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/vscode/devcontainers/rust:1
+
+RUN apt-get update \
+    && export DEBIAN_FRONTEND=noninteractive \
+    && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
+    && rustup default nightly 2>&1 \
+    && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
+    && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
+    && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
+    && chmod +x bin/install-bazel bin/buck bin/buildifier \
+    && bin/install-bazel \
+    && unzip tmp/watchman.zip -d tmp \
+    && mv tmp/watchman-v2020.09.21.00-linux/bin/watchman bin \
+    && mv tmp/watchman-v2020.09.21.00-linux/lib/* /usr/local/lib \
+    && mkdir -p /usr/local/var/run/watchman \
+    && rm tmp/watchman.zip

From 55a7774ffc018c7c5717040600c67fb0f35f596f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:10:52 +0000
Subject: [PATCH 906/2232] Merge pull request #314 from dtolnay/devcontainer


Create devcontainer configuration to use with GitHub Codespaces
---

diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000..93cfc05
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1 @@
+FROM dtolnay/devcontainer:latest
diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
new file mode 100644
index 0000000..d4ab609
--- /dev/null
+++ b/.devcontainer/build.Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/vscode/devcontainers/rust:1
+
+RUN apt-get update \
+    && export DEBIAN_FRONTEND=noninteractive \
+    && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
+    && rustup default nightly 2>&1 \
+    && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
+    && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
+    && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
+    && chmod +x bin/install-bazel bin/buck bin/buildifier \
+    && bin/install-bazel \
+    && unzip tmp/watchman.zip -d tmp \
+    && mv tmp/watchman-v2020.09.21.00-linux/bin/watchman bin \
+    && mv tmp/watchman-v2020.09.21.00-linux/lib/* /usr/local/lib \
+    && mkdir -p /usr/local/var/run/watchman \
+    && rm tmp/watchman.zip
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..bc5e979
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,19 @@
+{
+	"name": "Rust",
+	"build": {
+		"dockerfile": "Dockerfile"
+	},
+	"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
+	"settings": {
+		"terminal.integrated.shell.linux": "/bin/bash",
+		"lldb.executable": "/usr/bin/lldb",
+		"files.watcherExclude": {
+			"**/target/**": true
+		}
+	},
+	"extensions": [
+        "BazelBuild.vscode-bazel",
+		"matklad.rust-analyzer",
+        "vadimcn.vscode-lldb"
+	]
+}
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..244f5c4
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "Run cxx demo",
+            "type": "lldb",
+            "request": "launch",
+            "cargo": {
+                "args": ["build", "--manifest-path", "demo/Cargo.toml"],
+                "filter": {
+                    "name": "demo",
+                    "kind": "bin"
+                }
+            }
+        }
+    ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..8a1c2c1
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,5 @@
+{
+    "search.exclude": {
+        "**/target": true
+    }
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..44a2ab7
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,30 @@
+{
+    "version": "2.0.0",
+    "tasks": [
+        {
+            "label": "Cargo test",
+            "type": "shell",
+            "command": "cargo test",
+            "group": "test"
+        },
+        {
+            "label": "Bazel test",
+            "type": "shell",
+            "command": "bazel test ...",
+            "group": "test",
+            "dependsOn": ["Vendor"]
+        },
+        {
+            "label": "Buck test",
+            "type": "shell",
+            "command": "buck test ...",
+            "group": "test",
+            "dependsOn": ["Vendor"]
+        },
+        {
+            "label": "Vendor",
+            "type": "shell",
+            "command": "cp third-party/Cargo.lock . && cargo vendor --versioned-dirs --locked third-party/vendor"
+        }
+    ]
+}

From 18df6f8589bcdff6045a5479bceb9939b5048bb1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:13:29 +0000
Subject: [PATCH 907/2232] Format devcontainer json


---

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index bc5e979..fef25d4 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,19 +1,19 @@
 {
-	"name": "Rust",
-	"build": {
-		"dockerfile": "Dockerfile"
-	},
-	"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
-	"settings": {
-		"terminal.integrated.shell.linux": "/bin/bash",
-		"lldb.executable": "/usr/bin/lldb",
-		"files.watcherExclude": {
-			"**/target/**": true
-		}
-	},
-	"extensions": [
+    "name": "Rust",
+    "build": {
+        "dockerfile": "Dockerfile"
+    },
+    "runArgs": ["--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
+    "settings": {
+        "terminal.integrated.shell.linux": "/bin/bash",
+        "lldb.executable": "/usr/bin/lldb",
+        "files.watcherExclude": {
+            "**/target/**": true
+        }
+    },
+    "extensions": [
         "BazelBuild.vscode-bazel",
-		"matklad.rust-analyzer",
+        "matklad.rust-analyzer",
         "vadimcn.vscode-lldb"
-	]
+    ]
 }

From 5f6cffad4a5cf1f17762dd8d552f1c0f9a85883c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:40:08 +0000
Subject: [PATCH 908/2232] Remove unused import from demo/BUILD


---

diff --git a/demo/BUILD b/demo/BUILD
index 03a6535..9a46fa2 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -1,5 +1,5 @@
 load("@rules_cc//cc:defs.bzl", "cc_library")
-load("//tools/bazel:rust.bzl", "rust_binary", "rust_library")
+load("//tools/bazel:rust.bzl", "rust_binary")
 
 rust_binary(
     name = "demo",

From 0cd342913ac460a36db921590bd9a3c93a5f43d9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:40:27 +0000
Subject: [PATCH 909/2232] Make buck/bazel generated filepaths match source path with extension


---

diff --git a/demo/BUCK b/demo/BUCK
index eebe5c2..0640a53 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -22,7 +22,7 @@ cxx_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    out = "generated.h",
+    out = "src/main.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
     type = "cxxbridge",
 )
@@ -30,16 +30,14 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
-    out = "generated.cc",
+    out = "src/main.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     type = "cxxbridge",
 )
 
 cxx_library(
     name = "include",
-    exported_headers = {
-        "src/main.rs.h": ":gen-header",
-    },
+    exported_headers = [":gen-header"],
 )
 
 cxx_library(
diff --git a/demo/BUILD b/demo/BUILD
index 9a46fa2..c1fb429 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -23,7 +23,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    outs = ["main.rs.h"],
+    outs = ["src/main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
@@ -31,7 +31,7 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
-    outs = ["generated.cc"],
+    outs = ["src/main.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
@@ -39,7 +39,6 @@ genrule(
 cc_library(
     name = "include",
     hdrs = [":gen-header"],
-    include_prefix = "demo/src",
 )
 
 cc_library(
diff --git a/tests/BUCK b/tests/BUCK
index 79ae790..4a14f2a 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -37,20 +37,20 @@ cxx_library(
 genrule(
     name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
-    out = "lib.rs.h",
+    out = "ffi/lib.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    out = "lib.rs.cc",
+    out = "ffi/lib.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-module-source",
     srcs = ["ffi/module.rs"],
-    out = "module.rs.cc",
+    out = "ffi/module.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
diff --git a/tests/BUILD b/tests/BUILD
index ba763e0..c690994 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -39,7 +39,7 @@ cc_library(
 genrule(
     name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs.h"],
+    outs = ["ffi/lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
@@ -47,7 +47,7 @@ genrule(
 genrule(
     name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs.cc"],
+    outs = ["ffi/lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
@@ -56,12 +56,13 @@ cc_library(
     name = "lib-include",
     hdrs = [":gen-lib-header"],
     include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
 )
 
 genrule(
     name = "gen-module-source",
     srcs = ["ffi/module.rs"],
-    outs = ["module.rs.cc"],
+    outs = ["ffi/module.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )

From 55151b4575a39bf4f43457014e2444a24bc7866c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 13:40:27 +0000
Subject: [PATCH 910/2232] Match bazel's semantics for genrule cmd


---

diff --git a/demo/BUCK b/demo/BUCK
index 78e75e6..eebe5c2 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -1,3 +1,5 @@
+load("//tools/buck:genrule.bzl", "genrule")
+
 rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
diff --git a/tests/BUCK b/tests/BUCK
index a96bfb8..79ae790 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -1,3 +1,5 @@
+load("//tools/buck:genrule.bzl", "genrule")
+
 rust_test(
     name = "test",
     srcs = ["test.rs"],
diff --git a/tools/buck/genrule.bzl b/tools/buck/genrule.bzl
new file mode 100644
index 0000000..b5364b7
--- /dev/null
+++ b/tools/buck/genrule.bzl
@@ -0,0 +1,8 @@
+def genrule(cmd, **kwargs):
+    # Resolve a distracting inconsistency between Buck and Bazel.
+    # Bazel creates the directory for your output file, while Buck expects the
+    # cmd to create it.
+    #
+    # TODO: send this as a PR to Buck, because Bazel's behavior here is better.
+    cmd = "mkdir -p `dirname ${OUT}`; " + cmd
+    native.genrule(cmd = cmd, **kwargs)

From dbfdbd70f2e8fe9124ce3e88d6851a166c7a1bb8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:00:40 +0000
Subject: [PATCH 911/2232] Merge pull request #315 from dtolnay/build


Make buck/bazel generated filepaths match source path with extension
---

diff --git a/demo/BUCK b/demo/BUCK
index eebe5c2..0640a53 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -22,7 +22,7 @@ cxx_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    out = "generated.h",
+    out = "src/main.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
     type = "cxxbridge",
 )
@@ -30,16 +30,14 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
-    out = "generated.cc",
+    out = "src/main.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
     type = "cxxbridge",
 )
 
 cxx_library(
     name = "include",
-    exported_headers = {
-        "src/main.rs.h": ":gen-header",
-    },
+    exported_headers = [":gen-header"],
 )
 
 cxx_library(
diff --git a/demo/BUILD b/demo/BUILD
index 9a46fa2..c1fb429 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -23,7 +23,7 @@ cc_library(
 genrule(
     name = "gen-header",
     srcs = ["src/main.rs"],
-    outs = ["main.rs.h"],
+    outs = ["src/main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
@@ -31,7 +31,7 @@ genrule(
 genrule(
     name = "gen-source",
     srcs = ["src/main.rs"],
-    outs = ["generated.cc"],
+    outs = ["src/main.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
@@ -39,7 +39,6 @@ genrule(
 cc_library(
     name = "include",
     hdrs = [":gen-header"],
-    include_prefix = "demo/src",
 )
 
 cc_library(
diff --git a/tests/BUCK b/tests/BUCK
index 79ae790..4a14f2a 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -37,20 +37,20 @@ cxx_library(
 genrule(
     name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
-    out = "lib.rs.h",
+    out = "ffi/lib.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    out = "lib.rs.cc",
+    out = "ffi/lib.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
 
 genrule(
     name = "gen-module-source",
     srcs = ["ffi/module.rs"],
-    out = "module.rs.cc",
+    out = "ffi/module.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
diff --git a/tests/BUILD b/tests/BUILD
index ba763e0..c690994 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -39,7 +39,7 @@ cc_library(
 genrule(
     name = "gen-lib-header",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs.h"],
+    outs = ["ffi/lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
     tools = ["//:codegen"],
 )
@@ -47,7 +47,7 @@ genrule(
 genrule(
     name = "gen-lib-source",
     srcs = ["ffi/lib.rs"],
-    outs = ["lib.rs.cc"],
+    outs = ["ffi/lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )
@@ -56,12 +56,13 @@ cc_library(
     name = "lib-include",
     hdrs = [":gen-lib-header"],
     include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
 )
 
 genrule(
     name = "gen-module-source",
     srcs = ["ffi/module.rs"],
-    outs = ["module.rs.cc"],
+    outs = ["ffi/module.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
     tools = ["//:codegen"],
 )

From dc57990e22c65744b8587b5eccaac30ba256c0d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:00:50 +0000
Subject: [PATCH 912/2232] Use more systematic naming for generated code targets


---

diff --git a/demo/BUCK b/demo/BUCK
index 0640a53..7b476a5 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -4,23 +4,23 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":bridge",
         ":demo-sys",
-        ":gen",
         "//:cxx",
     ],
 )
 
 cxx_library(
-    name = "gen",
-    srcs = [":gen-source"],
+    name = "bridge",
+    srcs = [":bridge/source"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "bridge/header",
     srcs = ["src/main.rs"],
     out = "src/main.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
@@ -28,7 +28,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "bridge/source",
     srcs = ["src/main.rs"],
     out = "src/main.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
@@ -36,8 +36,8 @@ genrule(
 )
 
 cxx_library(
-    name = "include",
-    exported_headers = [":gen-header"],
+    name = "bridge/include",
+    exported_headers = [":bridge/header"],
 )
 
 cxx_library(
@@ -45,8 +45,8 @@ cxx_library(
     srcs = ["src/demo.cc"],
     compiler_flags = ["-std=c++14"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
diff --git a/demo/BUILD b/demo/BUILD
index c1fb429..6e07e5e 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -5,23 +5,23 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":bridge",
         ":demo-sys",
-        ":gen",
         "//:cxx",
     ],
 )
 
 cc_library(
-    name = "gen",
-    srcs = [":gen-source"],
+    name = "bridge",
+    srcs = [":bridge/source"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "bridge/header",
     srcs = ["src/main.rs"],
     outs = ["src/main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -29,7 +29,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "bridge/source",
     srcs = ["src/main.rs"],
     outs = ["src/main.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
@@ -37,8 +37,8 @@ genrule(
 )
 
 cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
+    name = "bridge/include",
+    hdrs = [":bridge/header"],
 )
 
 cc_library(
@@ -46,8 +46,8 @@ cc_library(
     srcs = ["src/demo.cc"],
     copts = ["-std=c++14"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
diff --git a/tests/BUCK b/tests/BUCK
index 4a14f2a..a5bd044 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -23,33 +23,33 @@ cxx_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-lib-source",
-        ":gen-module-source",
+        ":bridge/source",
+        ":module/source",
     ],
     header_namespace = "cxx-test-suite",
     headers = {
-        "lib.rs.h": ":gen-lib-header",
+        "lib.rs.h": ":bridge/header",
         "tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
 
 genrule(
-    name = "gen-lib-header",
+    name = "bridge/header",
     srcs = ["ffi/lib.rs"],
     out = "ffi/lib.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
 )
 
 genrule(
-    name = "gen-lib-source",
+    name = "bridge/source",
     srcs = ["ffi/lib.rs"],
     out = "ffi/lib.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
 
 genrule(
-    name = "gen-module-source",
+    name = "module/source",
     srcs = ["ffi/module.rs"],
     out = "ffi/module.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
diff --git a/tests/BUILD b/tests/BUILD
index c690994..586affc 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -24,20 +24,20 @@ cc_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-lib-source",
-        ":gen-module-source",
+        ":bridge/source",
+        ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
     deps = [
-        ":lib-include",
+        ":bridge/include",
         "//:core",
     ],
 )
 
 genrule(
-    name = "gen-lib-header",
+    name = "bridge/header",
     srcs = ["ffi/lib.rs"],
     outs = ["ffi/lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -45,7 +45,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-lib-source",
+    name = "bridge/source",
     srcs = ["ffi/lib.rs"],
     outs = ["ffi/lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
@@ -53,14 +53,14 @@ genrule(
 )
 
 cc_library(
-    name = "lib-include",
-    hdrs = [":gen-lib-header"],
+    name = "bridge/include",
+    hdrs = [":bridge/header"],
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
 )
 
 genrule(
-    name = "gen-module-source",
+    name = "module/source",
     srcs = ["ffi/module.rs"],
     outs = ["ffi/module.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",

From f337a209c35ff64212fbb97e474a2fbfe702e9d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:08:01 +0000
Subject: [PATCH 913/2232] Merge pull request #316 from dtolnay/build


Use more systematic naming for generated code targets
---

diff --git a/demo/BUCK b/demo/BUCK
index 0640a53..7b476a5 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -4,23 +4,23 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":bridge",
         ":demo-sys",
-        ":gen",
         "//:cxx",
     ],
 )
 
 cxx_library(
-    name = "gen",
-    srcs = [":gen-source"],
+    name = "bridge",
+    srcs = [":bridge/source"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "bridge/header",
     srcs = ["src/main.rs"],
     out = "src/main.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
@@ -28,7 +28,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "bridge/source",
     srcs = ["src/main.rs"],
     out = "src/main.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
@@ -36,8 +36,8 @@ genrule(
 )
 
 cxx_library(
-    name = "include",
-    exported_headers = [":gen-header"],
+    name = "bridge/include",
+    exported_headers = [":bridge/header"],
 )
 
 cxx_library(
@@ -45,8 +45,8 @@ cxx_library(
     srcs = ["src/demo.cc"],
     compiler_flags = ["-std=c++14"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
diff --git a/demo/BUILD b/demo/BUILD
index c1fb429..6e07e5e 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -5,23 +5,23 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":bridge",
         ":demo-sys",
-        ":gen",
         "//:cxx",
     ],
 )
 
 cc_library(
-    name = "gen",
-    srcs = [":gen-source"],
+    name = "bridge",
+    srcs = [":bridge/source"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
 genrule(
-    name = "gen-header",
+    name = "bridge/header",
     srcs = ["src/main.rs"],
     outs = ["src/main.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -29,7 +29,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-source",
+    name = "bridge/source",
     srcs = ["src/main.rs"],
     outs = ["src/main.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
@@ -37,8 +37,8 @@ genrule(
 )
 
 cc_library(
-    name = "include",
-    hdrs = [":gen-header"],
+    name = "bridge/include",
+    hdrs = [":bridge/header"],
 )
 
 cc_library(
@@ -46,8 +46,8 @@ cc_library(
     srcs = ["src/demo.cc"],
     copts = ["-std=c++14"],
     deps = [
+        ":bridge/include",
         ":demo-include",
-        ":include",
     ],
 )
 
diff --git a/tests/BUCK b/tests/BUCK
index 4a14f2a..a5bd044 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -23,33 +23,33 @@ cxx_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-lib-source",
-        ":gen-module-source",
+        ":bridge/source",
+        ":module/source",
     ],
     header_namespace = "cxx-test-suite",
     headers = {
-        "lib.rs.h": ":gen-lib-header",
+        "lib.rs.h": ":bridge/header",
         "tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
 
 genrule(
-    name = "gen-lib-header",
+    name = "bridge/header",
     srcs = ["ffi/lib.rs"],
     out = "ffi/lib.rs.h",
     cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
 )
 
 genrule(
-    name = "gen-lib-source",
+    name = "bridge/source",
     srcs = ["ffi/lib.rs"],
     out = "ffi/lib.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
 )
 
 genrule(
-    name = "gen-module-source",
+    name = "module/source",
     srcs = ["ffi/module.rs"],
     out = "ffi/module.rs.cc",
     cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
diff --git a/tests/BUILD b/tests/BUILD
index c690994..586affc 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -24,20 +24,20 @@ cc_library(
     name = "impl",
     srcs = [
         "ffi/tests.cc",
-        ":gen-lib-source",
-        ":gen-module-source",
+        ":bridge/source",
+        ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
     deps = [
-        ":lib-include",
+        ":bridge/include",
         "//:core",
     ],
 )
 
 genrule(
-    name = "gen-lib-header",
+    name = "bridge/header",
     srcs = ["ffi/lib.rs"],
     outs = ["ffi/lib.rs.h"],
     cmd = "$(location //:codegen) --header $< > $@",
@@ -45,7 +45,7 @@ genrule(
 )
 
 genrule(
-    name = "gen-lib-source",
+    name = "bridge/source",
     srcs = ["ffi/lib.rs"],
     outs = ["ffi/lib.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",
@@ -53,14 +53,14 @@ genrule(
 )
 
 cc_library(
-    name = "lib-include",
-    hdrs = [":gen-lib-header"],
+    name = "bridge/include",
+    hdrs = [":bridge/header"],
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
 )
 
 genrule(
-    name = "gen-module-source",
+    name = "module/source",
     srcs = ["ffi/module.rs"],
     outs = ["ffi/module.rs.cc"],
     cmd = "$(location //:codegen) $< > $@",

From 717c7e6aa862883cbb5049d77e5099de9261b74b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:08:10 +0000
Subject: [PATCH 914/2232] Factor out genrules to rust_cxx_bridge.bzl


---

diff --git a/demo/BUCK b/demo/BUCK
index 7b476a5..846c149 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -1,4 +1,4 @@
-load("//tools/buck:genrule.bzl", "genrule")
+load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_binary(
     name = "demo",
@@ -10,34 +10,10 @@ rust_binary(
     ],
 )
 
-cxx_library(
+rust_cxx_bridge(
     name = "bridge",
-    srcs = [":bridge/source"],
-    deps = [
-        ":bridge/include",
-        ":demo-include",
-    ],
-)
-
-genrule(
-    name = "bridge/header",
-    srcs = ["src/main.rs"],
-    out = "src/main.rs.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["src/main.rs"],
-    out = "src/main.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-cxx_library(
-    name = "bridge/include",
-    exported_headers = [":bridge/header"],
+    src = "src/main.rs",
+    deps = [":demo-include"],
 )
 
 cxx_library(
diff --git a/demo/BUILD b/demo/BUILD
index 6e07e5e..5bc8c77 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -1,5 +1,6 @@
 load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_binary")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_binary(
     name = "demo",
@@ -11,34 +12,10 @@ rust_binary(
     ],
 )
 
-cc_library(
+rust_cxx_bridge(
     name = "bridge",
-    srcs = [":bridge/source"],
-    deps = [
-        ":bridge/include",
-        ":demo-include",
-    ],
-)
-
-genrule(
-    name = "bridge/header",
-    srcs = ["src/main.rs"],
-    outs = ["src/main.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["src/main.rs"],
-    outs = ["src/main.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "bridge/include",
-    hdrs = [":bridge/header"],
+    src = "src/main.rs",
+    deps = [":demo-include"],
 )
 
 cc_library(
diff --git a/tests/BUCK b/tests/BUCK
index a5bd044..47fc557 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -1,4 +1,4 @@
-load("//tools/buck:genrule.bzl", "genrule")
+load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_test(
     name = "test",
@@ -34,23 +34,12 @@ cxx_library(
     deps = ["//:core"],
 )
 
-genrule(
-    name = "bridge/header",
-    srcs = ["ffi/lib.rs"],
-    out = "ffi/lib.rs.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+rust_cxx_bridge(
+    name = "bridge",
+    src = "ffi/lib.rs",
 )
 
-genrule(
-    name = "bridge/source",
-    srcs = ["ffi/lib.rs"],
-    out = "ffi/lib.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-)
-
-genrule(
-    name = "module/source",
-    srcs = ["ffi/module.rs"],
-    out = "ffi/module.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+rust_cxx_bridge(
+    name = "module",
+    src = "ffi/module.rs",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 586affc..68e7be3 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -1,5 +1,6 @@
 load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_library", "rust_test")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_test(
     name = "test",
@@ -36,33 +37,18 @@ cc_library(
     ],
 )
 
-genrule(
-    name = "bridge/header",
-    srcs = ["ffi/lib.rs"],
-    outs = ["ffi/lib.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["ffi/lib.rs"],
-    outs = ["ffi/lib.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "bridge/include",
-    hdrs = [":bridge/header"],
+rust_cxx_bridge(
+    name = "bridge",
+    src = "ffi/lib.rs",
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
+    deps = [":impl"],
 )
 
-genrule(
-    name = "module/source",
-    srcs = ["ffi/module.rs"],
-    outs = ["ffi/module.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
+rust_cxx_bridge(
+    name = "module",
+    src = "ffi/module.rs",
+    include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
+    deps = [":impl"],
 )
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
new file mode 100644
index 0000000..7f3f958
--- /dev/null
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -0,0 +1,36 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+def rust_cxx_bridge(
+        name,
+        src,
+        include_prefix = None,
+        strip_include_prefix = None,
+        deps = []):
+    native.genrule(
+        name = "%s/header" % name,
+        srcs = [src],
+        outs = [src + ".h"],
+        cmd = "$(location //:codegen) --header $< > $@",
+        tools = ["//:codegen"],
+    )
+
+    native.genrule(
+        name = "%s/source" % name,
+        srcs = [src],
+        outs = [src + ".cc"],
+        cmd = "$(location //:codegen) $< > $@",
+        tools = ["//:codegen"],
+    )
+
+    cc_library(
+        name = name,
+        srcs = [":%s/source" % name],
+        deps = deps + [":%s/include" % name],
+    )
+
+    cc_library(
+        name = "%s/include" % name,
+        hdrs = [":%s/header" % name],
+        include_prefix = include_prefix,
+        strip_include_prefix = strip_include_prefix,
+    )
diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl
new file mode 100644
index 0000000..5fa530b
--- /dev/null
+++ b/tools/buck/rust_cxx_bridge.bzl
@@ -0,0 +1,30 @@
+load("//tools/buck:genrule.bzl", "genrule")
+
+def rust_cxx_bridge(name, src, deps = []):
+    genrule(
+        name = "%s/header" % name,
+        srcs = [src],
+        out = src + ".h",
+        cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+        type = "cxxbridge",
+    )
+
+    genrule(
+        name = "%s/source" % name,
+        srcs = [src],
+        out = src + ".cc",
+        cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+        type = "cxxbridge",
+    )
+
+    cxx_library(
+        name = name,
+        srcs = [":%s/source" % name],
+        preferred_linkage = "static",
+        deps = deps + [":%s/include" % name],
+    )
+
+    cxx_library(
+        name = "%s/include" % name,
+        exported_headers = [":%s/header" % name],
+    )

From 6140a3f61db9ca51c25e187773a3a555a7ce53ac Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:14:56 +0000
Subject: [PATCH 915/2232] Merge pull request #317 from dtolnay/build


Factor out genrules to rust_cxx_bridge.bzl
---

diff --git a/demo/BUCK b/demo/BUCK
index 7b476a5..846c149 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -1,4 +1,4 @@
-load("//tools/buck:genrule.bzl", "genrule")
+load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_binary(
     name = "demo",
@@ -10,34 +10,10 @@ rust_binary(
     ],
 )
 
-cxx_library(
+rust_cxx_bridge(
     name = "bridge",
-    srcs = [":bridge/source"],
-    deps = [
-        ":bridge/include",
-        ":demo-include",
-    ],
-)
-
-genrule(
-    name = "bridge/header",
-    srcs = ["src/main.rs"],
-    out = "src/main.rs.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["src/main.rs"],
-    out = "src/main.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-    type = "cxxbridge",
-)
-
-cxx_library(
-    name = "bridge/include",
-    exported_headers = [":bridge/header"],
+    src = "src/main.rs",
+    deps = [":demo-include"],
 )
 
 cxx_library(
diff --git a/demo/BUILD b/demo/BUILD
index 6e07e5e..5bc8c77 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -1,5 +1,6 @@
 load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_binary")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_binary(
     name = "demo",
@@ -11,34 +12,10 @@ rust_binary(
     ],
 )
 
-cc_library(
+rust_cxx_bridge(
     name = "bridge",
-    srcs = [":bridge/source"],
-    deps = [
-        ":bridge/include",
-        ":demo-include",
-    ],
-)
-
-genrule(
-    name = "bridge/header",
-    srcs = ["src/main.rs"],
-    outs = ["src/main.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["src/main.rs"],
-    outs = ["src/main.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "bridge/include",
-    hdrs = [":bridge/header"],
+    src = "src/main.rs",
+    deps = [":demo-include"],
 )
 
 cc_library(
diff --git a/tests/BUCK b/tests/BUCK
index a5bd044..47fc557 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -1,4 +1,4 @@
-load("//tools/buck:genrule.bzl", "genrule")
+load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_test(
     name = "test",
@@ -34,23 +34,12 @@ cxx_library(
     deps = ["//:core"],
 )
 
-genrule(
-    name = "bridge/header",
-    srcs = ["ffi/lib.rs"],
-    out = "ffi/lib.rs.h",
-    cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+rust_cxx_bridge(
+    name = "bridge",
+    src = "ffi/lib.rs",
 )
 
-genrule(
-    name = "bridge/source",
-    srcs = ["ffi/lib.rs"],
-    out = "ffi/lib.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
-)
-
-genrule(
-    name = "module/source",
-    srcs = ["ffi/module.rs"],
-    out = "ffi/module.rs.cc",
-    cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+rust_cxx_bridge(
+    name = "module",
+    src = "ffi/module.rs",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 586affc..68e7be3 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -1,5 +1,6 @@
 load("@rules_cc//cc:defs.bzl", "cc_library")
 load("//tools/bazel:rust.bzl", "rust_library", "rust_test")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 
 rust_test(
     name = "test",
@@ -36,33 +37,18 @@ cc_library(
     ],
 )
 
-genrule(
-    name = "bridge/header",
-    srcs = ["ffi/lib.rs"],
-    outs = ["ffi/lib.rs.h"],
-    cmd = "$(location //:codegen) --header $< > $@",
-    tools = ["//:codegen"],
-)
-
-genrule(
-    name = "bridge/source",
-    srcs = ["ffi/lib.rs"],
-    outs = ["ffi/lib.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
-)
-
-cc_library(
-    name = "bridge/include",
-    hdrs = [":bridge/header"],
+rust_cxx_bridge(
+    name = "bridge",
+    src = "ffi/lib.rs",
     include_prefix = "cxx-test-suite",
     strip_include_prefix = "ffi",
+    deps = [":impl"],
 )
 
-genrule(
-    name = "module/source",
-    srcs = ["ffi/module.rs"],
-    outs = ["ffi/module.rs.cc"],
-    cmd = "$(location //:codegen) $< > $@",
-    tools = ["//:codegen"],
+rust_cxx_bridge(
+    name = "module",
+    src = "ffi/module.rs",
+    include_prefix = "cxx-test-suite",
+    strip_include_prefix = "ffi",
+    deps = [":impl"],
 )
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
new file mode 100644
index 0000000..7f3f958
--- /dev/null
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -0,0 +1,36 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+def rust_cxx_bridge(
+        name,
+        src,
+        include_prefix = None,
+        strip_include_prefix = None,
+        deps = []):
+    native.genrule(
+        name = "%s/header" % name,
+        srcs = [src],
+        outs = [src + ".h"],
+        cmd = "$(location //:codegen) --header $< > $@",
+        tools = ["//:codegen"],
+    )
+
+    native.genrule(
+        name = "%s/source" % name,
+        srcs = [src],
+        outs = [src + ".cc"],
+        cmd = "$(location //:codegen) $< > $@",
+        tools = ["//:codegen"],
+    )
+
+    cc_library(
+        name = name,
+        srcs = [":%s/source" % name],
+        deps = deps + [":%s/include" % name],
+    )
+
+    cc_library(
+        name = "%s/include" % name,
+        hdrs = [":%s/header" % name],
+        include_prefix = include_prefix,
+        strip_include_prefix = strip_include_prefix,
+    )
diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl
new file mode 100644
index 0000000..5fa530b
--- /dev/null
+++ b/tools/buck/rust_cxx_bridge.bzl
@@ -0,0 +1,30 @@
+load("//tools/buck:genrule.bzl", "genrule")
+
+def rust_cxx_bridge(name, src, deps = []):
+    genrule(
+        name = "%s/header" % name,
+        srcs = [src],
+        out = src + ".h",
+        cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+        type = "cxxbridge",
+    )
+
+    genrule(
+        name = "%s/source" % name,
+        srcs = [src],
+        out = src + ".cc",
+        cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+        type = "cxxbridge",
+    )
+
+    cxx_library(
+        name = name,
+        srcs = [":%s/source" % name],
+        preferred_linkage = "static",
+        deps = deps + [":%s/include" % name],
+    )
+
+    cxx_library(
+        name = "%s/include" % name,
+        exported_headers = [":%s/header" % name],
+    )

From e2e47a39a67645e541aada758553a93ef1a76181 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:30:24 +0000
Subject: [PATCH 916/2232] Assume header output for paths ending in .h


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index caab254..44e30bb 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -102,9 +102,11 @@ these C++ functions in another.
 }
 
 fn arg_header() -> Arg {
-    Arg::with_name(HEADER)
-        .long(HEADER)
-        .help("Emit header with declarations only.")
+    const HELP: &str = "\
+Emit header with declarations only. Optional if using `-o` with
+a path ending in `.h`.
+    ";
+    Arg::with_name(HEADER).long(HEADER).help(HELP)
 }
 
 fn arg_include() -> Arg {
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 834b738..12e173e 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -9,10 +9,12 @@
 
 mod app;
 mod gen;
+mod output;
 mod syntax;
 
-use gen::error::{report, Result};
-use gen::{fs, include};
+use crate::gen::error::{report, Result};
+use crate::gen::{fs, include};
+use crate::output::Output;
 use std::io::{self, Write};
 use std::path::PathBuf;
 use std::process;
@@ -26,12 +28,6 @@ struct Opt {
     output: Output,
 }
 
-#[derive(Debug)]
-enum Output {
-    Stdout,
-    File(PathBuf),
-}
-
 fn main() {
     if let Err(err) = try_main() {
         let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
@@ -42,15 +38,17 @@ fn main() {
 fn try_main() -> Result<()> {
     let opt = app::from_args();
 
+    let gen_header = opt.header || opt.output.ends_with(".h");
+
     let gen = gen::Opt {
         include: opt.include,
         cxx_impl_annotations: opt.cxx_impl_annotations,
-        gen_header: opt.header,
-        gen_implementation: !opt.header,
+        gen_header,
+        gen_implementation: !gen_header,
     };
 
     let content;
-    let content = match (opt.input, opt.header) {
+    let content = match (opt.input, gen_header) {
         (Some(input), true) => {
             content = gen::generate_from_path(&input, &gen).header;
             content.as_slice()
diff --git a/gen/cmd/src/output.rs b/gen/cmd/src/output.rs
new file mode 100644
index 0000000..a46581b
--- /dev/null
+++ b/gen/cmd/src/output.rs
@@ -0,0 +1,16 @@
+use std::path::PathBuf;
+
+#[derive(Debug)]
+pub(crate) enum Output {
+    Stdout,
+    File(PathBuf),
+}
+
+impl Output {
+    pub(crate) fn ends_with(&self, suffix: &str) -> bool {
+        match self {
+            Output::Stdout => false,
+            Output::File(path) => path.to_string_lossy().ends_with(suffix),
+        }
+    }
+}

From cf641edb27d7cd9d047ab6d43e9474db71aec3c5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:44:21 +0000
Subject: [PATCH 917/2232] Update help text test


---

diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 76101d9..2e85fac 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -24,8 +24,9 @@ OPTIONS:
             Print help information.
 
         --header
-            Emit header with declarations only.
-
+            Emit header with declarations only. Optional if using `-o` with
+            a path ending in `.h`.
+               \x20
     -i, --include <include>...
             Any additional headers to #include. The cxxbridge tool does not
             parse or even require the given paths to exist; they simply go

From a5cd6c8133be4a84583b97f6e72929b0bfbdf3bc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:51:16 +0000
Subject: [PATCH 918/2232] Merge pull request #318 from dtolnay/_h


Assume header output for paths ending in .h
---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index caab254..44e30bb 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -102,9 +102,11 @@ these C++ functions in another.
 }
 
 fn arg_header() -> Arg {
-    Arg::with_name(HEADER)
-        .long(HEADER)
-        .help("Emit header with declarations only.")
+    const HELP: &str = "\
+Emit header with declarations only. Optional if using `-o` with
+a path ending in `.h`.
+    ";
+    Arg::with_name(HEADER).long(HEADER).help(HELP)
 }
 
 fn arg_include() -> Arg {
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 834b738..12e173e 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -9,10 +9,12 @@
 
 mod app;
 mod gen;
+mod output;
 mod syntax;
 
-use gen::error::{report, Result};
-use gen::{fs, include};
+use crate::gen::error::{report, Result};
+use crate::gen::{fs, include};
+use crate::output::Output;
 use std::io::{self, Write};
 use std::path::PathBuf;
 use std::process;
@@ -26,12 +28,6 @@ struct Opt {
     output: Output,
 }
 
-#[derive(Debug)]
-enum Output {
-    Stdout,
-    File(PathBuf),
-}
-
 fn main() {
     if let Err(err) = try_main() {
         let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
@@ -42,15 +38,17 @@ fn main() {
 fn try_main() -> Result<()> {
     let opt = app::from_args();
 
+    let gen_header = opt.header || opt.output.ends_with(".h");
+
     let gen = gen::Opt {
         include: opt.include,
         cxx_impl_annotations: opt.cxx_impl_annotations,
-        gen_header: opt.header,
-        gen_implementation: !opt.header,
+        gen_header,
+        gen_implementation: !gen_header,
     };
 
     let content;
-    let content = match (opt.input, opt.header) {
+    let content = match (opt.input, gen_header) {
         (Some(input), true) => {
             content = gen::generate_from_path(&input, &gen).header;
             content.as_slice()
diff --git a/gen/cmd/src/output.rs b/gen/cmd/src/output.rs
new file mode 100644
index 0000000..a46581b
--- /dev/null
+++ b/gen/cmd/src/output.rs
@@ -0,0 +1,16 @@
+use std::path::PathBuf;
+
+#[derive(Debug)]
+pub(crate) enum Output {
+    Stdout,
+    File(PathBuf),
+}
+
+impl Output {
+    pub(crate) fn ends_with(&self, suffix: &str) -> bool {
+        match self {
+            Output::Stdout => false,
+            Output::File(path) => path.to_string_lossy().ends_with(suffix),
+        }
+    }
+}
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 76101d9..2e85fac 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -24,8 +24,9 @@ OPTIONS:
             Print help information.
 
         --header
-            Emit header with declarations only.
-
+            Emit header with declarations only. Optional if using `-o` with
+            a path ending in `.h`.
+               \x20
     -i, --include <include>...
             Any additional headers to #include. The cxxbridge tool does not
             parse or even require the given paths to exist; they simply go

From 6427614d945ffd605d7483ba5cc13e681e6f464f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:51:27 +0000
Subject: [PATCH 919/2232] Move arg parsing out of big struct literal


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 44e30bb..7532668 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -56,18 +56,25 @@ const OUTPUT: &str = "output";
 
 pub(super) fn from_args() -> Opt {
     let matches = app().get_matches();
+
+    let input = matches.value_of_os(INPUT).map(PathBuf::from);
+    let cxx_impl_annotations = matches.value_of(CXX_IMPL_ANNOTATIONS).map(str::to_owned);
+    let header = matches.is_present(HEADER);
+    let include = matches
+        .values_of(INCLUDE)
+        .map_or_else(Vec::new, |v| v.map(str::to_owned).collect());
+    let output = match matches.value_of_os(OUTPUT) {
+        None => Output::Stdout,
+        Some(path) if path == "-" => Output::Stdout,
+        Some(path) => Output::File(PathBuf::from(path)),
+    };
+
     Opt {
-        input: matches.value_of_os(INPUT).map(PathBuf::from),
-        cxx_impl_annotations: matches.value_of(CXX_IMPL_ANNOTATIONS).map(str::to_owned),
-        header: matches.is_present(HEADER),
-        include: matches
-            .values_of(INCLUDE)
-            .map_or_else(Vec::new, |v| v.map(str::to_owned).collect()),
-        output: match matches.value_of_os(OUTPUT) {
-            None => Output::Stdout,
-            Some(path) if path == "-" => Output::Stdout,
-            Some(path) => Output::File(PathBuf::from(path)),
-        },
+        input,
+        cxx_impl_annotations,
+        header,
+        include,
+        output,
     }
 }
 

From 13213b7a85cc1b5dcac0848bb664f34d463ac7e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 14:51:27 +0000
Subject: [PATCH 920/2232] Simplify parsing of include flags


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 7532668..939bb44 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -62,7 +62,9 @@ pub(super) fn from_args() -> Opt {
     let header = matches.is_present(HEADER);
     let include = matches
         .values_of(INCLUDE)
-        .map_or_else(Vec::new, |v| v.map(str::to_owned).collect());
+        .unwrap_or_default()
+        .map(str::to_owned)
+        .collect();
     let output = match matches.value_of_os(OUTPUT) {
         None => Output::Stdout,
         Some(path) if path == "-" => Output::Stdout,

From f027756ba7f6494cde572d3573c999c47e0bdc93 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 15:38:22 +0000
Subject: [PATCH 921/2232] Handle multiple outputs from the same cxxbridge invocation


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 939bb44..152f11a 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -65,18 +65,25 @@ pub(super) fn from_args() -> Opt {
         .unwrap_or_default()
         .map(str::to_owned)
         .collect();
-    let output = match matches.value_of_os(OUTPUT) {
-        None => Output::Stdout,
-        Some(path) if path == "-" => Output::Stdout,
-        Some(path) => Output::File(PathBuf::from(path)),
-    };
+
+    let mut outputs = Vec::new();
+    for path in matches.values_of_os(OUTPUT).unwrap_or_default() {
+        outputs.push(if path == "-" {
+            Output::Stdout
+        } else {
+            Output::File(PathBuf::from(path))
+        });
+    }
+    if outputs.is_empty() {
+        outputs.push(Output::Stdout);
+    }
 
     Opt {
         input,
         cxx_impl_annotations,
         header,
         include,
-        output,
+        outputs,
     }
 }
 
@@ -142,6 +149,7 @@ not specified.
         .long(OUTPUT)
         .short("o")
         .takes_value(true)
+        .multiple(true)
         .validator_os(validate_utf8)
         .help(HELP)
 }
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 12e173e..f0fd9b4 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -25,7 +25,7 @@ struct Opt {
     header: bool,
     cxx_impl_annotations: Option<String>,
     include: Vec<String>,
-    output: Output,
+    outputs: Vec<Output>,
 }
 
 fn main() {
@@ -35,35 +35,54 @@ fn main() {
     }
 }
 
+enum Kind {
+    GeneratedHeader,
+    GeneratedImplementation,
+    Header,
+}
+
 fn try_main() -> Result<()> {
     let opt = app::from_args();
 
-    let gen_header = opt.header || opt.output.ends_with(".h");
+    let mut outputs = Vec::new();
+    let mut gen_header = false;
+    let mut gen_implementation = false;
+    for output in opt.outputs {
+        let kind = if opt.input.is_none() {
+            Kind::Header
+        } else if opt.header || output.ends_with(".h") {
+            gen_header = true;
+            Kind::GeneratedHeader
+        } else {
+            gen_implementation = true;
+            Kind::GeneratedImplementation
+        };
+        outputs.push((output, kind));
+    }
 
     let gen = gen::Opt {
         include: opt.include,
         cxx_impl_annotations: opt.cxx_impl_annotations,
         gen_header,
-        gen_implementation: !gen_header,
+        gen_implementation,
     };
 
-    let content;
-    let content = match (opt.input, gen_header) {
-        (Some(input), true) => {
-            content = gen::generate_from_path(&input, &gen).header;
-            content.as_slice()
-        }
-        (Some(input), false) => {
-            content = gen::generate_from_path(&input, &gen).implementation;
-            content.as_slice()
-        }
-        (None, true) => include::HEADER.as_bytes(),
-        (None, false) => unreachable!(), // enforced by required_unless
+    let generated_code = if let Some(input) = opt.input {
+        gen::generate_from_path(&input, &gen)
+    } else {
+        Default::default()
     };
 
-    match opt.output {
-        Output::Stdout => drop(io::stdout().write_all(content)),
-        Output::File(path) => fs::write(path, content)?,
+    for (output, kind) in outputs {
+        let content = match kind {
+            Kind::GeneratedHeader => &generated_code.header,
+            Kind::GeneratedImplementation => &generated_code.implementation,
+            Kind::Header => include::HEADER.as_bytes(),
+        };
+        match output {
+            Output::Stdout => drop(io::stdout().write_all(content)),
+            Output::File(path) => fs::write(path, content)?,
+        }
     }
 
     Ok(())
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 2e85fac..17023e4 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -32,7 +32,7 @@ OPTIONS:
             parse or even require the given paths to exist; they simply go
             into the generated C++ code as #include lines.
                \x20
-    -o, --output <output>
+    -o, --output <output>...
             Path of file to write as output. Output goes to stdout if -o is
             not specified.
                \x20
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 9578fe8..8522715 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -50,6 +50,7 @@ pub struct Opt {
 }
 
 /// Results of code generation.
+#[derive(Default)]
 pub struct GeneratedCode {
     /// The bytes of a C++ header file.
     pub header: Vec<u8>,

From 950fb211a80de163a8b19990a9d3f3ba221455a2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 15:46:40 +0000
Subject: [PATCH 922/2232] Merge pull request #319 from dtolnay/multiple


Handle multiple outputs from the same cxxbridge invocation
---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 939bb44..152f11a 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -65,18 +65,25 @@ pub(super) fn from_args() -> Opt {
         .unwrap_or_default()
         .map(str::to_owned)
         .collect();
-    let output = match matches.value_of_os(OUTPUT) {
-        None => Output::Stdout,
-        Some(path) if path == "-" => Output::Stdout,
-        Some(path) => Output::File(PathBuf::from(path)),
-    };
+
+    let mut outputs = Vec::new();
+    for path in matches.values_of_os(OUTPUT).unwrap_or_default() {
+        outputs.push(if path == "-" {
+            Output::Stdout
+        } else {
+            Output::File(PathBuf::from(path))
+        });
+    }
+    if outputs.is_empty() {
+        outputs.push(Output::Stdout);
+    }
 
     Opt {
         input,
         cxx_impl_annotations,
         header,
         include,
-        output,
+        outputs,
     }
 }
 
@@ -142,6 +149,7 @@ not specified.
         .long(OUTPUT)
         .short("o")
         .takes_value(true)
+        .multiple(true)
         .validator_os(validate_utf8)
         .help(HELP)
 }
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 12e173e..f0fd9b4 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -25,7 +25,7 @@ struct Opt {
     header: bool,
     cxx_impl_annotations: Option<String>,
     include: Vec<String>,
-    output: Output,
+    outputs: Vec<Output>,
 }
 
 fn main() {
@@ -35,35 +35,54 @@ fn main() {
     }
 }
 
+enum Kind {
+    GeneratedHeader,
+    GeneratedImplementation,
+    Header,
+}
+
 fn try_main() -> Result<()> {
     let opt = app::from_args();
 
-    let gen_header = opt.header || opt.output.ends_with(".h");
+    let mut outputs = Vec::new();
+    let mut gen_header = false;
+    let mut gen_implementation = false;
+    for output in opt.outputs {
+        let kind = if opt.input.is_none() {
+            Kind::Header
+        } else if opt.header || output.ends_with(".h") {
+            gen_header = true;
+            Kind::GeneratedHeader
+        } else {
+            gen_implementation = true;
+            Kind::GeneratedImplementation
+        };
+        outputs.push((output, kind));
+    }
 
     let gen = gen::Opt {
         include: opt.include,
         cxx_impl_annotations: opt.cxx_impl_annotations,
         gen_header,
-        gen_implementation: !gen_header,
+        gen_implementation,
     };
 
-    let content;
-    let content = match (opt.input, gen_header) {
-        (Some(input), true) => {
-            content = gen::generate_from_path(&input, &gen).header;
-            content.as_slice()
-        }
-        (Some(input), false) => {
-            content = gen::generate_from_path(&input, &gen).implementation;
-            content.as_slice()
-        }
-        (None, true) => include::HEADER.as_bytes(),
-        (None, false) => unreachable!(), // enforced by required_unless
+    let generated_code = if let Some(input) = opt.input {
+        gen::generate_from_path(&input, &gen)
+    } else {
+        Default::default()
     };
 
-    match opt.output {
-        Output::Stdout => drop(io::stdout().write_all(content)),
-        Output::File(path) => fs::write(path, content)?,
+    for (output, kind) in outputs {
+        let content = match kind {
+            Kind::GeneratedHeader => &generated_code.header,
+            Kind::GeneratedImplementation => &generated_code.implementation,
+            Kind::Header => include::HEADER.as_bytes(),
+        };
+        match output {
+            Output::Stdout => drop(io::stdout().write_all(content)),
+            Output::File(path) => fs::write(path, content)?,
+        }
     }
 
     Ok(())
diff --git a/gen/cmd/src/test.rs b/gen/cmd/src/test.rs
index 2e85fac..17023e4 100644
--- a/gen/cmd/src/test.rs
+++ b/gen/cmd/src/test.rs
@@ -32,7 +32,7 @@ OPTIONS:
             parse or even require the given paths to exist; they simply go
             into the generated C++ code as #include lines.
                \x20
-    -o, --output <output>
+    -o, --output <output>...
             Path of file to write as output. Output goes to stdout if -o is
             not specified.
                \x20
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 9578fe8..8522715 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -50,6 +50,7 @@ pub struct Opt {
 }
 
 /// Results of code generation.
+#[derive(Default)]
 pub struct GeneratedCode {
     /// The bytes of a C++ header file.
     pub header: Vec<u8>,

From 93637cac19ea63a4594b2ffeadf9c0f341f66523 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 19:58:58 +0000
Subject: [PATCH 923/2232] Add CxxVector::as_slice -> &[T]


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1c21770..955ad5f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -859,12 +859,12 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> &Self {
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
                 }
-                &*__get_unchecked(v, pos)
+                __get_unchecked(v, pos)
             }
             fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
                 extern "C" {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 78b8f20..3ab3193 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -4,6 +4,7 @@ use core::fmt::{self, Display};
 use core::marker::PhantomData;
 use core::mem;
 use core::ptr;
+use core::slice;
 
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
@@ -44,7 +45,7 @@ where
     /// out of bounds.
     pub fn get(&self, pos: usize) -> Option<&T> {
         if pos < self.len() {
-            Some(unsafe { T::__get_unchecked(self, pos) })
+            Some(unsafe { self.get_unchecked(pos) })
         } else {
             None
         }
@@ -61,7 +62,18 @@ where
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
-        T::__get_unchecked(self, pos)
+        &*T::__get_unchecked(self, pos)
+    }
+
+    /// Returns a slice to the underlying contiguous array of elements.
+    pub fn as_slice(&self) -> &[T] {
+        let len = self.len();
+        if len == 0 {
+            <&[T]>::default()
+        } else {
+            let ptr = unsafe { T::__get_unchecked(self, 0) };
+            unsafe { slice::from_raw_parts(ptr, len) }
+        }
     }
 }
 
@@ -122,7 +134,7 @@ where
 pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
-    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
+    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> *const Self;
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -145,14 +157,14 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
+            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
                 extern "C" {
                     attr! {
                         #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
-                &*__get_unchecked(v, pos)
+                __get_unchecked(v, pos)
             }
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {

From 5df0a71dcf5a989bfc578bc9a6718b609b6062b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 19:58:58 +0000
Subject: [PATCH 924/2232] Add test for CxxVector::as_slice


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2829fef..73d6376 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -6,7 +6,7 @@
 
 pub mod module;
 
-use cxx::{CxxString, UniquePtr};
+use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
@@ -144,6 +144,7 @@ pub mod ffi {
         fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn r_take_ref_vector(v: &CxxVector<u8>);
         fn r_take_rust_vec(v: Vec<u8>);
         fn r_take_rust_vec_string(v: Vec<String>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
@@ -307,6 +308,11 @@ fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
 
+fn r_take_ref_vector(v: &CxxVector<u8>) {
+    let slice = v.as_slice();
+    assert_eq!(slice, [20, 2, 0]);
+}
+
 fn r_take_rust_vec(v: Vec<u8>) {
     let _ = v;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8dd16e8..a107c48 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -399,6 +399,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
+  r_take_ref_vector(std::vector<uint8_t>{20, 2, 0});
   r_take_enum(Enum::AVal);
 
   ASSERT(r_try_return_primitive() == 2020);

From a5a14ce1583d0c31019d16511cfdf485666a1a95 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 20:02:40 +0000
Subject: [PATCH 925/2232] Add explanation of as_slice implementation


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 3ab3193..9d04cb5 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -69,6 +69,12 @@ where
     pub fn as_slice(&self) -> &[T] {
         let len = self.len();
         if len == 0 {
+            // The slice::from_raw_parts in the other branch requires a nonnull
+            // and properly aligned data ptr. C++ standard does not guarantee
+            // that data() on a vector with size 0 would return a nonnull
+            // pointer or sufficiently aligned pointer, so using it would be
+            // undefined behavior. Create our own empty slice in Rust instead
+            // which upholds the invariants.
             <&[T]>::default()
         } else {
             let ptr = unsafe { T::__get_unchecked(self, 0) };

From 80631e93ef59f4db2394e0478ecdb0154fd75f0b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 20:07:30 +0000
Subject: [PATCH 926/2232] Add test involving empty vector


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 73d6376..9ace1f2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -145,6 +145,7 @@ pub mod ffi {
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_ref_vector(v: &CxxVector<u8>);
+        fn r_take_ref_empty_vector(v: &CxxVector<u64>);
         fn r_take_rust_vec(v: Vec<u8>);
         fn r_take_rust_vec_string(v: Vec<String>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
@@ -313,6 +314,11 @@ fn r_take_ref_vector(v: &CxxVector<u8>) {
     assert_eq!(slice, [20, 2, 0]);
 }
 
+fn r_take_ref_empty_vector(v: &CxxVector<u64>) {
+    assert!(v.as_slice().is_empty());
+    assert!(v.is_empty());
+}
+
 fn r_take_rust_vec(v: Vec<u8>) {
     let _ = v;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a107c48..1f88d8b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -400,6 +400,10 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
   r_take_ref_vector(std::vector<uint8_t>{20, 2, 0});
+  std::vector<uint64_t> empty_vector;
+  r_take_ref_empty_vector(empty_vector);
+  empty_vector.reserve(10);
+  r_take_ref_empty_vector(empty_vector);
   r_take_enum(Enum::AVal);
 
   ASSERT(r_try_return_primitive() == 2020);

From 4cbd8f4e13767d66244630ac6b78e3d067c59280 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 20:13:27 +0000
Subject: [PATCH 927/2232] Merge pull request #322 from dtolnay/as_slice


Add API to get slice from CxxVector
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1c21770..955ad5f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -859,12 +859,12 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> &Self {
+            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
                     fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
                 }
-                &*__get_unchecked(v, pos)
+                __get_unchecked(v, pos)
             }
             fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
                 extern "C" {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 78b8f20..9d04cb5 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -4,6 +4,7 @@ use core::fmt::{self, Display};
 use core::marker::PhantomData;
 use core::mem;
 use core::ptr;
+use core::slice;
 
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
@@ -44,7 +45,7 @@ where
     /// out of bounds.
     pub fn get(&self, pos: usize) -> Option<&T> {
         if pos < self.len() {
-            Some(unsafe { T::__get_unchecked(self, pos) })
+            Some(unsafe { self.get_unchecked(pos) })
         } else {
             None
         }
@@ -61,7 +62,24 @@ where
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
-        T::__get_unchecked(self, pos)
+        &*T::__get_unchecked(self, pos)
+    }
+
+    /// Returns a slice to the underlying contiguous array of elements.
+    pub fn as_slice(&self) -> &[T] {
+        let len = self.len();
+        if len == 0 {
+            // The slice::from_raw_parts in the other branch requires a nonnull
+            // and properly aligned data ptr. C++ standard does not guarantee
+            // that data() on a vector with size 0 would return a nonnull
+            // pointer or sufficiently aligned pointer, so using it would be
+            // undefined behavior. Create our own empty slice in Rust instead
+            // which upholds the invariants.
+            <&[T]>::default()
+        } else {
+            let ptr = unsafe { T::__get_unchecked(self, 0) };
+            unsafe { slice::from_raw_parts(ptr, len) }
+        }
     }
 }
 
@@ -122,7 +140,7 @@ where
 pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
-    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> &Self;
+    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> *const Self;
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -145,14 +163,14 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
+            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
                 extern "C" {
                     attr! {
                         #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
-                &*__get_unchecked(v, pos)
+                __get_unchecked(v, pos)
             }
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2829fef..9ace1f2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -6,7 +6,7 @@
 
 pub mod module;
 
-use cxx::{CxxString, UniquePtr};
+use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
 #[cxx::bridge(namespace = tests)]
@@ -144,6 +144,8 @@ pub mod ffi {
         fn r_take_sliceu8(s: &[u8]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
+        fn r_take_ref_vector(v: &CxxVector<u8>);
+        fn r_take_ref_empty_vector(v: &CxxVector<u64>);
         fn r_take_rust_vec(v: Vec<u8>);
         fn r_take_rust_vec_string(v: Vec<String>);
         fn r_take_ref_rust_vec(v: &Vec<u8>);
@@ -307,6 +309,16 @@ fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
     assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
 }
 
+fn r_take_ref_vector(v: &CxxVector<u8>) {
+    let slice = v.as_slice();
+    assert_eq!(slice, [20, 2, 0]);
+}
+
+fn r_take_ref_empty_vector(v: &CxxVector<u64>) {
+    assert!(v.as_slice().is_empty());
+    assert!(v.is_empty());
+}
+
 fn r_take_rust_vec(v: Vec<u8>) {
     let _ = v;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8dd16e8..1f88d8b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -399,6 +399,11 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
+  r_take_ref_vector(std::vector<uint8_t>{20, 2, 0});
+  std::vector<uint64_t> empty_vector;
+  r_take_ref_empty_vector(empty_vector);
+  empty_vector.reserve(10);
+  r_take_ref_empty_vector(empty_vector);
   r_take_enum(Enum::AVal);
 
   ASSERT(r_try_return_primitive() == 2020);

From b312bb15e3d5bdd094c193591324b84f447f5888 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 20:17:02 +0000
Subject: [PATCH 928/2232] Release 0.4.7


---

diff --git a/Cargo.toml b/Cargo.toml
index cab9814..57b4320 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.6" # remember to update html_root_url
+version = "0.4.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge04"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.6", path = "macro" }
+cxxbridge-macro = { version = "=0.4.7", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.6", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.4.7", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.6", path = "gen/build" }
+cxx-build = { version = "=0.4.7", path = "gen/build" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 98cf047..5b4f666 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.6"
+version = "0.4.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index cfe094c..675261e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.6"
+version = "0.4.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index ba6d28a..684642c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.6"
+version = "0.4.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 4d17d6c..9c151b8 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.6"
+version = "0.4.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 8990f5b..5f52f49 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.4.7")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index c90ed81..1c43f70 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.6"
+version = "0.4.7"
 dependencies = [
  "cc",
  "cxx-build",
@@ -73,7 +73,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.6"
+version = "0.4.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -105,7 +105,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.6"
+version = "0.4.7"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -116,11 +116,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.6"
+version = "0.4.7"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.6"
+version = "0.4.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From acc7fb05f9bbf07e7d6e1accce9cdbdf26b91411 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 24 2020 22:10:09 +0000
Subject: [PATCH 929/2232] Simpler expression for making an empty slice


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 9d04cb5..a5fe536 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -75,7 +75,7 @@ where
             // pointer or sufficiently aligned pointer, so using it would be
             // undefined behavior. Create our own empty slice in Rust instead
             // which upholds the invariants.
-            <&[T]>::default()
+            &[]
         } else {
             let ptr = unsafe { T::__get_unchecked(self, 0) };
             unsafe { slice::from_raw_parts(ptr, len) }

From e53ec043970b5f2a3607ed7f916e061fd7a28333 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 25 2020 03:36:00 +0000
Subject: [PATCH 930/2232] Bypass compiletest on Windows push and pull_request builds


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4b42fe3..8ec4224 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,6 +34,14 @@ jobs:
       - uses: dtolnay/rust-toolchain@master
         with:
           toolchain: ${{matrix.rust}}
+      - name: Determine test suite subset
+        # Our Windows jobs are the longest running, so exclude the relatively
+        # slow compiletest from them to speed up end-to-end CI time, except
+        # during cron builds when no human is presumably waiting on the build.
+        # The extra coverage is not particularly valuable and we can still
+        # ensure the test is kept passing on the basis of the scheduled builds.
+        if: matrix.os == 'windows' && github.event_name != 'schedule'
+        run: echo '::set-env name=RUSTFLAGS::--cfg skip_ui_tests'
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
 
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index f9aea23..d2b516f 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -1,4 +1,5 @@
 #[rustversion::attr(not(nightly), ignore)]
+#[cfg_attr(skip_ui_tests, ignore)]
 #[test]
 fn ui() {
     let t = trybuild::TestCases::new();

From 5a3ddf1f0e82bab3a3013b7f0a574e3598c0014c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 26 2020 00:26:14 +0000
Subject: [PATCH 931/2232] Switch from genrule to run_binary for Bazel


---

diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 7f3f958..6b31b15 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,3 +1,4 @@
+load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 def rust_cxx_bridge(
@@ -6,20 +7,20 @@ def rust_cxx_bridge(
         include_prefix = None,
         strip_include_prefix = None,
         deps = []):
-    native.genrule(
+    run_binary(
         name = "%s/header" % name,
         srcs = [src],
         outs = [src + ".h"],
-        cmd = "$(location //:codegen) --header $< > $@",
-        tools = ["//:codegen"],
+        args = ["$(location %s)" % src, "-o", "$(location %s.h)" % src, "--header"],
+        tool = "//:codegen",
     )
 
-    native.genrule(
+    run_binary(
         name = "%s/source" % name,
         srcs = [src],
         outs = [src + ".cc"],
-        cmd = "$(location //:codegen) $< > $@",
-        tools = ["//:codegen"],
+        args = ["$(location %s)" % src, "-o", "$(location %s.cc)" % src],
+        tool = "//:codegen",
     )
 
     cc_library(

From 73d129dfd983c31e86dde30282bdc76e15b06b9c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 26 2020 00:26:25 +0000
Subject: [PATCH 932/2232] Wrap run_binary args


---

diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 6b31b15..497061d 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -11,7 +11,12 @@ def rust_cxx_bridge(
         name = "%s/header" % name,
         srcs = [src],
         outs = [src + ".h"],
-        args = ["$(location %s)" % src, "-o", "$(location %s.h)" % src, "--header"],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.h)" % src,
+            "--header",
+        ],
         tool = "//:codegen",
     )
 
@@ -19,7 +24,11 @@ def rust_cxx_bridge(
         name = "%s/source" % name,
         srcs = [src],
         outs = [src + ".cc"],
-        args = ["$(location %s)" % src, "-o", "$(location %s.cc)" % src],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.cc)" % src,
+        ],
         tool = "//:codegen",
     )
 

From f0bd14d97f905c4ac666218362aa22addefac5a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 26 2020 00:39:42 +0000
Subject: [PATCH 933/2232] Merge pull request #326 from dtolnay/run_binary


Switch Bazel rules from genrule to run_binary
---

diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 7f3f958..497061d 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,3 +1,4 @@
+load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 def rust_cxx_bridge(
@@ -6,20 +7,29 @@ def rust_cxx_bridge(
         include_prefix = None,
         strip_include_prefix = None,
         deps = []):
-    native.genrule(
+    run_binary(
         name = "%s/header" % name,
         srcs = [src],
         outs = [src + ".h"],
-        cmd = "$(location //:codegen) --header $< > $@",
-        tools = ["//:codegen"],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.h)" % src,
+            "--header",
+        ],
+        tool = "//:codegen",
     )
 
-    native.genrule(
+    run_binary(
         name = "%s/source" % name,
         srcs = [src],
         outs = [src + ".cc"],
-        cmd = "$(location //:codegen) $< > $@",
-        tools = ["//:codegen"],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.cc)" % src,
+        ],
+        tool = "//:codegen",
     )
 
     cc_library(

From 8b7878ccff292116749be38b8fe0b4f9d8106d20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 27 2020 21:16:36 +0000
Subject: [PATCH 934/2232] Combine bazel codegen steps into one run of cxxbridge


---

diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 497061d..d4111c6 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -7,26 +7,28 @@ def rust_cxx_bridge(
         include_prefix = None,
         strip_include_prefix = None,
         deps = []):
-    run_binary(
+    native.alias(
         name = "%s/header" % name,
-        srcs = [src],
-        outs = [src + ".h"],
-        args = [
-            "$(location %s)" % src,
-            "-o",
-            "$(location %s.h)" % src,
-            "--header",
-        ],
-        tool = "//:codegen",
+        actual = src + ".h",
     )
 
-    run_binary(
+    native.alias(
         name = "%s/source" % name,
+        actual = src + ".cc",
+    )
+
+    run_binary(
+        name = "%s/generated" % name,
         srcs = [src],
-        outs = [src + ".cc"],
+        outs = [
+            src + ".h",
+            src + ".cc",
+        ],
         args = [
             "$(location %s)" % src,
             "-o",
+            "$(location %s.h)" % src,
+            "-o",
             "$(location %s.cc)" % src,
         ],
         tool = "//:codegen",
@@ -34,13 +36,13 @@ def rust_cxx_bridge(
 
     cc_library(
         name = name,
-        srcs = [":%s/source" % name],
+        srcs = [src + ".cc"],
         deps = deps + [":%s/include" % name],
     )
 
     cc_library(
         name = "%s/include" % name,
-        hdrs = [":%s/header" % name],
+        hdrs = [src + ".h"],
         include_prefix = include_prefix,
         strip_include_prefix = strip_include_prefix,
     )

From 61dbb45c48fdb03dfca3bb6952b405e67a502813 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 27 2020 21:39:14 +0000
Subject: [PATCH 935/2232] Merge pull request #327 from dtolnay/bazel


Combine bazel codegen steps into one run of cxxbridge
---

diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 497061d..d4111c6 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -7,26 +7,28 @@ def rust_cxx_bridge(
         include_prefix = None,
         strip_include_prefix = None,
         deps = []):
-    run_binary(
+    native.alias(
         name = "%s/header" % name,
-        srcs = [src],
-        outs = [src + ".h"],
-        args = [
-            "$(location %s)" % src,
-            "-o",
-            "$(location %s.h)" % src,
-            "--header",
-        ],
-        tool = "//:codegen",
+        actual = src + ".h",
     )
 
-    run_binary(
+    native.alias(
         name = "%s/source" % name,
+        actual = src + ".cc",
+    )
+
+    run_binary(
+        name = "%s/generated" % name,
         srcs = [src],
-        outs = [src + ".cc"],
+        outs = [
+            src + ".h",
+            src + ".cc",
+        ],
         args = [
             "$(location %s)" % src,
             "-o",
+            "$(location %s.h)" % src,
+            "-o",
             "$(location %s.cc)" % src,
         ],
         tool = "//:codegen",
@@ -34,13 +36,13 @@ def rust_cxx_bridge(
 
     cc_library(
         name = name,
-        srcs = [":%s/source" % name],
+        srcs = [src + ".cc"],
         deps = deps + [":%s/include" % name],
     )
 
     cc_library(
         name = "%s/include" % name,
-        hdrs = [":%s/header" % name],
+        hdrs = [src + ".h"],
         include_prefix = include_prefix,
         strip_include_prefix = strip_include_prefix,
     )

From d1ca05aa1cf403c1cb33a327ca6a2af075ad188e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 27 2020 21:41:08 +0000
Subject: [PATCH 936/2232] Implement buck genrule using -o instead of redirection


---

diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl
index 5fa530b..ba9d8f1 100644
--- a/tools/buck/rust_cxx_bridge.bzl
+++ b/tools/buck/rust_cxx_bridge.bzl
@@ -5,7 +5,7 @@ def rust_cxx_bridge(name, src, deps = []):
         name = "%s/header" % name,
         srcs = [src],
         out = src + ".h",
-        cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
+        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}",
         type = "cxxbridge",
     )
 
@@ -13,7 +13,7 @@ def rust_cxx_bridge(name, src, deps = []):
         name = "%s/source" % name,
         srcs = [src],
         out = src + ".cc",
-        cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}",
         type = "cxxbridge",
     )
 

From 0489527aece22c4819072ce2cecdcbfbdf587839 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 27 2020 21:41:42 +0000
Subject: [PATCH 937/2232] Combine buck codegen steps into one run of cxxbridge


---

diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl
index ba9d8f1..4acc7c6 100644
--- a/tools/buck/rust_cxx_bridge.bzl
+++ b/tools/buck/rust_cxx_bridge.bzl
@@ -3,17 +3,21 @@ load("//tools/buck:genrule.bzl", "genrule")
 def rust_cxx_bridge(name, src, deps = []):
     genrule(
         name = "%s/header" % name,
-        srcs = [src],
         out = src + ".h",
-        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}",
-        type = "cxxbridge",
+        cmd = "cp $(location :%s/generated)/generated.h ${OUT}" % name,
     )
 
     genrule(
         name = "%s/source" % name,
-        srcs = [src],
         out = src + ".cc",
-        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}",
+        cmd = "cp $(location :%s/generated)/generated.cc ${OUT}" % name,
+    )
+
+    genrule(
+        name = "%s/generated" % name,
+        srcs = [src],
+        out = ".",
+        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}/generated.h -o ${OUT}/generated.cc",
         type = "cxxbridge",
     )
 

From f2fbac79ab6d2880929a3cdc8e021e53b01ee7e1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sep 27 2020 21:47:55 +0000
Subject: [PATCH 938/2232] Merge pull request #328 from dtolnay/buck


Combine buck codegen steps into one run of cxxbridge
---

diff --git a/tools/buck/rust_cxx_bridge.bzl b/tools/buck/rust_cxx_bridge.bzl
index 5fa530b..4acc7c6 100644
--- a/tools/buck/rust_cxx_bridge.bzl
+++ b/tools/buck/rust_cxx_bridge.bzl
@@ -3,17 +3,21 @@ load("//tools/buck:genrule.bzl", "genrule")
 def rust_cxx_bridge(name, src, deps = []):
     genrule(
         name = "%s/header" % name,
-        srcs = [src],
         out = src + ".h",
-        cmd = "$(exe //:codegen) --header ${SRCS} > ${OUT}",
-        type = "cxxbridge",
+        cmd = "cp $(location :%s/generated)/generated.h ${OUT}" % name,
     )
 
     genrule(
         name = "%s/source" % name,
-        srcs = [src],
         out = src + ".cc",
-        cmd = "$(exe //:codegen) ${SRCS} > ${OUT}",
+        cmd = "cp $(location :%s/generated)/generated.cc ${OUT}" % name,
+    )
+
+    genrule(
+        name = "%s/generated" % name,
+        srcs = [src],
+        out = ".",
+        cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}/generated.h -o ${OUT}/generated.cc",
         type = "cxxbridge",
     )
 

From c704329d3b9a222b4503218bfa237b36091dfbca Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Sep 30 2020 23:38:06 +0000
Subject: [PATCH 939/2232] Allow aliases and C++ opaque types to be trivial.


This change allows aliases:
  type Foo = bindgen::Bar;
and C++ opaque types:
  type Foo;
to declare that they're 'trivial' in the sense that:

* They have trivial move constructors
* They have no destructors

and therefore may be passed and owned by value in Rust.

A subsequent commit will add C++ static assertions.

This commit is a BREAKING CHANGE as it requires existing
ExternTypes to gain a new associated type

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 879431e..fc7c692 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -57,6 +57,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
                 hidden.extend(expand_type_alias_verify(namespace, alias));
+                let ident = &alias.ident;
+                if types.required_trivial_aliases.contains(ident) {
+                    hidden.extend(expand_type_alias_kind_trivial_verify(alias));
+                }
             }
         }
     }
@@ -179,6 +183,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
+            type Kind = ::cxx::Opaque;
         }
     }
 }
@@ -677,6 +682,18 @@ fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenSt
     }
 }
 
+fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream {
+    let ident = &type_alias.ident;
+    let begin_span = type_alias.type_token.span;
+    let end_span = type_alias.semi_token.span;
+    let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
+    let end = quote_spanned!(end_span=> >);
+
+    quote! {
+        const _: fn() = #begin #ident, ::cxx::Trivial #end;
+    }
+}
+
 fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let mut path = String::new();
     for name in namespace {
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 6701ef5..951bc6c 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -104,7 +104,28 @@ pub unsafe trait ExternType {
     /// # }
     /// ```
     type Id;
+
+    /// Either `kind::Opaque` or `kind::Trivial`. If in doubt, use
+    /// `kind::Opaque`.
+    type Kind;
+}
+
+pub(crate) mod kind {
+
+    /// An opaque type which can't be passed or held by value within Rust.
+    /// For example, a C++ type with a destructor, or a non-trivial move
+    /// constructor. Rust's strict move semantics mean that we can't own
+    /// these by value in Rust, but they can still be owned by a
+    /// `UniquePtr`...
+    pub struct Opaque;
+
+    /// A type with trivial move constructors and no destructor, which
+    /// can therefore be owned and moved around in Rust code directly.
+    pub struct Trivial;
 }
 
 #[doc(hidden)]
 pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+
+#[doc(hidden)]
+pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
diff --git a/src/lib.rs b/src/lib.rs
index 9efac51..2f21de9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -395,6 +395,8 @@ mod unwind;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
+pub use crate::extern_type::kind::Opaque;
+pub use crate::extern_type::kind::Trivial;
 pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
@@ -422,6 +424,7 @@ pub type Vector<T> = CxxVector<T>;
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
+    pub use crate::extern_type::verify_extern_kind;
     pub use crate::extern_type::verify_extern_type;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
diff --git a/syntax/check.rs b/syntax/check.rs
index 147984e..cfac236 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -338,6 +338,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         || cx.types.cxx.contains(ident)
             && !cx.types.structs.contains_key(ident)
             && !cx.types.enums.contains_key(ident)
+            && !cx.types.required_trivial_aliases.contains(ident)
         || cx.types.rust.contains(ident)
 }
 
@@ -376,7 +377,11 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
             } else if cx.types.enums.contains_key(ident) {
                 "enum".to_owned()
             } else if cx.types.cxx.contains(ident) {
-                "C++ type".to_owned()
+                if cx.types.required_trivial_aliases.contains(ident) {
+                    "trivial C++ type".to_owned()
+                } else {
+                    "non-trivial C++ type".to_owned()
+                }
             } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
diff --git a/syntax/types.rs b/syntax/types.rs
index 8a86a46..ff78268 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,6 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
+    pub required_trivial_aliases: Set<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -135,6 +136,55 @@ impl<'a> Types<'a> {
             }
         }
 
+        // All these APIs may contain types passed by value. We need to ensure
+        // we check that this is permissible. We do this _after_ scanning all
+        // the APIs above, in case some function or struct references a type
+        // which is declared subsequently.
+        let mut required_trivial_aliases = Set::new();
+
+        fn insist_alias_types_are_trivial<'c>(
+            required_trivial_aliases: &mut Set<&'c Ident>,
+            aliases: &Map<&'c Ident, &'c TypeAlias>,
+            ty: &'c Type,
+        ) {
+            if let Type::Ident(ident) = ty {
+                if aliases.contains_key(ident) {
+                    required_trivial_aliases.insert(ident);
+                }
+            }
+        }
+
+        for api in apis {
+            match api {
+                Api::Struct(strct) => {
+                    for field in &strct.fields {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &field.ty,
+                        );
+                    }
+                }
+                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    for arg in &efn.args {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &arg.ty,
+                        );
+                    }
+                    if let Some(ret) = &efn.ret {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &ret,
+                        );
+                    }
+                }
+                _ => {}
+            }
+        }
+
         Types {
             all,
             structs,
@@ -143,6 +193,7 @@ impl<'a> Types<'a> {
             rust,
             aliases,
             untrusted,
+            required_trivial_aliases,
         }
     }
 

From 405e8740a44110f59d720b0dab5847ab6db1b075 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Sep 30 2020 23:38:06 +0000
Subject: [PATCH 940/2232] Add C++ checks for triviality of Trivial types.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 862be81..5ea84fc 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -80,6 +80,11 @@ pub(super) fn gen(
                     write_struct_with_methods(out, ety, methods);
                 }
             }
+            Api::TypeAlias(ety) => {
+                if types.required_trivial_aliases.contains(&ety.ident) {
+                    check_trivial_extern_type(out, &ety.ident)
+                }
+            }
             _ => {}
         }
     }
@@ -124,13 +129,18 @@ pub(super) fn gen(
 fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
-                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
-                | Some(I64) => out.include.cstdint = true,
-                Some(Usize) => out.include.cstddef = true,
-                Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
-            },
+            Type::Ident(ident) => {
+                match Atom::from(ident) {
+                    Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16)
+                    | Some(I32) | Some(I64) => out.include.cstdint = true,
+                    Some(Usize) => out.include.cstddef = true,
+                    Some(CxxString) => out.include.string = true,
+                    Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+                };
+                if types.required_trivial_aliases.contains(&ident) {
+                    out.include.type_traits = true;
+                };
+            }
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
             Type::CxxVector(_) => out.include.vector = true,
@@ -401,6 +411,11 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
     }
 }
 
+fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+    writeln!(out, "static_assert(std::is_trivially_move_constructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially move constructible in C++\");", id, id);
+    writeln!(out, "static_assert(std::is_trivially_destructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially destructible in C++\");", id, id);
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {

From d7f5bb902bf593c956f0f12922080be5fe3b50c8 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Sep 30 2020 23:38:06 +0000
Subject: [PATCH 941/2232] Documenting ExternType::Kind.


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 951bc6c..9bc5947 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -54,7 +54,7 @@
 /// ## Integrating with bindgen-generated types
 ///
 /// Handwritten `ExternType` impls make it possible to plug in a data structure
-/// emitted by bindgen as the definition of an opaque C++ type emitted by CXX.
+/// emitted by bindgen as the definition of a C++ type emitted by CXX.
 ///
 /// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
 /// namespace and type name given in the type id refers to a C++ type that is
@@ -69,10 +69,11 @@
 /// #     pub struct StringPiece([usize; 2]);
 /// # }
 ///
-/// use cxx::{type_id, ExternType};
+/// use cxx::{type_id, ExternType, Opaque};
 ///
 /// unsafe impl ExternType for folly_sys::StringPiece {
 ///     type Id = type_id!("folly::StringPiece");
+///     type Kind = Opaque;
 /// }
 ///
 /// #[cxx::bridge(namespace = folly)]
@@ -92,6 +93,29 @@
 /// #
 /// # fn main() {}
 /// ```
+///
+/// ## Opaque and Trivial types
+///
+/// Some C++ types are safe to hold and pass around in Rust, by value.
+/// Those C++ types must have a trivial move constructor, and must
+/// have no destructor.
+///
+/// If you believe your C++ type is indeed trivial, you can specify
+/// ```
+/// # struct TypeName;
+/// # unsafe impl cxx::ExternType for TypeName {
+/// type Id = cxx::type_id!("name::space::of::TypeName");
+/// type Kind = cxx::Trivial;
+/// # }
+/// ```
+/// which will enable you to pass it into C++ functions by value,
+/// return it by value from such functions, and include it in
+/// `struct`s that you have declared to `cxx::bridge`. Your promises
+/// about the triviality of the C++ type will be checked using
+/// `static_assert`s in the generated C++.
+///
+/// Opaque types can't be passed by value, but can still be held
+/// in `UniquePtr`.
 pub unsafe trait ExternType {
     /// A type-level representation of the type's C++ namespace and type name.
     ///
@@ -101,12 +125,13 @@ pub unsafe trait ExternType {
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
     /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// type Kind = cxx::Opaque;
     /// # }
     /// ```
     type Id;
 
-    /// Either `kind::Opaque` or `kind::Trivial`. If in doubt, use
-    /// `kind::Opaque`.
+    /// Either `cxx::Opaque` or `cxx::Trivial`. If in doubt, use
+    /// `cxx::Opaque`.
     type Kind;
 }
 

From feb0dc104c186887c3ded8778026bc0c61b2dec4 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Sep 30 2020 23:51:31 +0000
Subject: [PATCH 942/2232] Fix expected error messages.


---

diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 1ff8dbf..e61ce84 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -1,4 +1,4 @@
-error: using C++ type by value is not supported
+error: using non-trivial C++ type by value is not supported
  --> $DIR/by_value_not_supported.rs:4:9
   |
 4 |         c: C,
@@ -16,13 +16,13 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: passing C++ type by value is not supported
+error: passing non-trivial C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
 16 |         fn f(c: C) -> C;
    |              ^^^^
 
-error: returning C++ type by value is not supported
+error: returning non-trivial C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:23
    |
 16 |         fn f(c: C) -> C;

From 890083d64fc0ee2ccf298be549827e9c0a975628 Mon Sep 17 00:00:00 2001
From: Bryan Henry <bryanhenry@google.com>
Date: Oct 02 2020 18:36:33 +0000
Subject: [PATCH 943/2232] Preserve docs on aliases


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 955ad5f..c35044b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -657,9 +657,11 @@ fn expand_rust_function_shim_impl(
 }
 
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
+    let doc = &alias.doc;
     let ident = &alias.ident;
     let ty = &alias.ty;
     quote! {
+        #doc
         pub type #ident = #ty;
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f52a582..8ef3c8b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -79,6 +79,7 @@ pub struct ExternFn {
 }
 
 pub struct TypeAlias {
+    pub doc: Doc,
     pub type_token: Token![type],
     pub ident: Ident,
     pub eq_token: Token![=],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3ac5304..c1c565f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -396,9 +396,10 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        attrs::parse_doc(cx, &attrs);
+        let doc = attrs::parse_doc(cx, &attrs);
 
         Ok(TypeAlias {
+            doc,
             type_token,
             ident,
             eq_token,

From 4954ca171f57be0ddf0842e68ca0ce16cd03203d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 03 2020 23:38:22 +0000
Subject: [PATCH 944/2232] Merge pull request #332 from dtolnay/doc


Preserve docs on aliases
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 955ad5f..c35044b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -657,9 +657,11 @@ fn expand_rust_function_shim_impl(
 }
 
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
+    let doc = &alias.doc;
     let ident = &alias.ident;
     let ty = &alias.ty;
     quote! {
+        #doc
         pub type #ident = #ty;
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f52a582..8ef3c8b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -79,6 +79,7 @@ pub struct ExternFn {
 }
 
 pub struct TypeAlias {
+    pub doc: Doc,
     pub type_token: Token![type],
     pub ident: Ident,
     pub eq_token: Token![=],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3ac5304..c1c565f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -396,9 +396,10 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        attrs::parse_doc(cx, &attrs);
+        let doc = attrs::parse_doc(cx, &attrs);
 
         Ok(TypeAlias {
+            doc,
             type_token,
             ident,
             eq_token,

From 9f69230783487f5bc2c6b9d9f44de2ddc2dc1146 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:53:30 +0000
Subject: [PATCH 945/2232] Merge pull request #325 from adetaylor/with-trivial-2


Allow type aliases to be marked as Trivial.
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2e2b81f..e0b1b30 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -80,6 +80,11 @@ pub(super) fn gen(
                     write_struct_with_methods(out, ety, methods);
                 }
             }
+            Api::TypeAlias(ety) => {
+                if types.required_trivial_aliases.contains(&ety.ident) {
+                    check_trivial_extern_type(out, &ety.ident)
+                }
+            }
             _ => {}
         }
     }
@@ -124,13 +129,18 @@ pub(super) fn gen(
 fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
-                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
-                | Some(I64) => out.include.cstdint = true,
-                Some(Usize) => out.include.cstddef = true,
-                Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
-            },
+            Type::Ident(ident) => {
+                match Atom::from(ident) {
+                    Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16)
+                    | Some(I32) | Some(I64) => out.include.cstdint = true,
+                    Some(Usize) => out.include.cstddef = true,
+                    Some(CxxString) => out.include.string = true,
+                    Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+                };
+                if types.required_trivial_aliases.contains(&ident) {
+                    out.include.type_traits = true;
+                };
+            }
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
             Type::CxxVector(_) => out.include.vector = true,
@@ -401,6 +411,11 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
     }
 }
 
+fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+    writeln!(out, "static_assert(std::is_trivially_move_constructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially move constructible in C++\");", id, id);
+    writeln!(out, "static_assert(std::is_trivially_destructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially destructible in C++\");", id, id);
+}
+
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c35044b..9c8a117 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -57,6 +57,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
                 hidden.extend(expand_type_alias_verify(namespace, alias));
+                let ident = &alias.ident;
+                if types.required_trivial_aliases.contains(ident) {
+                    hidden.extend(expand_type_alias_kind_trivial_verify(alias));
+                }
             }
         }
     }
@@ -179,6 +183,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
+            type Kind = ::cxx::Opaque;
         }
     }
 }
@@ -679,6 +684,18 @@ fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenSt
     }
 }
 
+fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream {
+    let ident = &type_alias.ident;
+    let begin_span = type_alias.type_token.span;
+    let end_span = type_alias.semi_token.span;
+    let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
+    let end = quote_spanned!(end_span=> >);
+
+    quote! {
+        const _: fn() = #begin #ident, ::cxx::Trivial #end;
+    }
+}
+
 fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let mut path = String::new();
     for name in namespace {
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 6701ef5..9bc5947 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -54,7 +54,7 @@
 /// ## Integrating with bindgen-generated types
 ///
 /// Handwritten `ExternType` impls make it possible to plug in a data structure
-/// emitted by bindgen as the definition of an opaque C++ type emitted by CXX.
+/// emitted by bindgen as the definition of a C++ type emitted by CXX.
 ///
 /// By writing the unsafe `ExternType` impl, the programmer asserts that the C++
 /// namespace and type name given in the type id refers to a C++ type that is
@@ -69,10 +69,11 @@
 /// #     pub struct StringPiece([usize; 2]);
 /// # }
 ///
-/// use cxx::{type_id, ExternType};
+/// use cxx::{type_id, ExternType, Opaque};
 ///
 /// unsafe impl ExternType for folly_sys::StringPiece {
 ///     type Id = type_id!("folly::StringPiece");
+///     type Kind = Opaque;
 /// }
 ///
 /// #[cxx::bridge(namespace = folly)]
@@ -92,6 +93,29 @@
 /// #
 /// # fn main() {}
 /// ```
+///
+/// ## Opaque and Trivial types
+///
+/// Some C++ types are safe to hold and pass around in Rust, by value.
+/// Those C++ types must have a trivial move constructor, and must
+/// have no destructor.
+///
+/// If you believe your C++ type is indeed trivial, you can specify
+/// ```
+/// # struct TypeName;
+/// # unsafe impl cxx::ExternType for TypeName {
+/// type Id = cxx::type_id!("name::space::of::TypeName");
+/// type Kind = cxx::Trivial;
+/// # }
+/// ```
+/// which will enable you to pass it into C++ functions by value,
+/// return it by value from such functions, and include it in
+/// `struct`s that you have declared to `cxx::bridge`. Your promises
+/// about the triviality of the C++ type will be checked using
+/// `static_assert`s in the generated C++.
+///
+/// Opaque types can't be passed by value, but can still be held
+/// in `UniquePtr`.
 pub unsafe trait ExternType {
     /// A type-level representation of the type's C++ namespace and type name.
     ///
@@ -101,10 +125,32 @@ pub unsafe trait ExternType {
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
     /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// type Kind = cxx::Opaque;
     /// # }
     /// ```
     type Id;
+
+    /// Either `cxx::Opaque` or `cxx::Trivial`. If in doubt, use
+    /// `cxx::Opaque`.
+    type Kind;
+}
+
+pub(crate) mod kind {
+
+    /// An opaque type which can't be passed or held by value within Rust.
+    /// For example, a C++ type with a destructor, or a non-trivial move
+    /// constructor. Rust's strict move semantics mean that we can't own
+    /// these by value in Rust, but they can still be owned by a
+    /// `UniquePtr`...
+    pub struct Opaque;
+
+    /// A type with trivial move constructors and no destructor, which
+    /// can therefore be owned and moved around in Rust code directly.
+    pub struct Trivial;
 }
 
 #[doc(hidden)]
 pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
+
+#[doc(hidden)]
+pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
diff --git a/src/lib.rs b/src/lib.rs
index 5f52f49..b53a7b6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -395,6 +395,8 @@ mod unwind;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
+pub use crate::extern_type::kind::Opaque;
+pub use crate::extern_type::kind::Trivial;
 pub use crate::extern_type::ExternType;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
@@ -422,6 +424,7 @@ pub type Vector<T> = CxxVector<T>;
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
+    pub use crate::extern_type::verify_extern_kind;
     pub use crate::extern_type::verify_extern_type;
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
diff --git a/syntax/check.rs b/syntax/check.rs
index 147984e..cfac236 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -338,6 +338,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         || cx.types.cxx.contains(ident)
             && !cx.types.structs.contains_key(ident)
             && !cx.types.enums.contains_key(ident)
+            && !cx.types.required_trivial_aliases.contains(ident)
         || cx.types.rust.contains(ident)
 }
 
@@ -376,7 +377,11 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
             } else if cx.types.enums.contains_key(ident) {
                 "enum".to_owned()
             } else if cx.types.cxx.contains(ident) {
-                "C++ type".to_owned()
+                if cx.types.required_trivial_aliases.contains(ident) {
+                    "trivial C++ type".to_owned()
+                } else {
+                    "non-trivial C++ type".to_owned()
+                }
             } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
diff --git a/syntax/types.rs b/syntax/types.rs
index 8a86a46..ff78268 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,6 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
+    pub required_trivial_aliases: Set<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -135,6 +136,55 @@ impl<'a> Types<'a> {
             }
         }
 
+        // All these APIs may contain types passed by value. We need to ensure
+        // we check that this is permissible. We do this _after_ scanning all
+        // the APIs above, in case some function or struct references a type
+        // which is declared subsequently.
+        let mut required_trivial_aliases = Set::new();
+
+        fn insist_alias_types_are_trivial<'c>(
+            required_trivial_aliases: &mut Set<&'c Ident>,
+            aliases: &Map<&'c Ident, &'c TypeAlias>,
+            ty: &'c Type,
+        ) {
+            if let Type::Ident(ident) = ty {
+                if aliases.contains_key(ident) {
+                    required_trivial_aliases.insert(ident);
+                }
+            }
+        }
+
+        for api in apis {
+            match api {
+                Api::Struct(strct) => {
+                    for field in &strct.fields {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &field.ty,
+                        );
+                    }
+                }
+                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    for arg in &efn.args {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &arg.ty,
+                        );
+                    }
+                    if let Some(ret) = &efn.ret {
+                        insist_alias_types_are_trivial(
+                            &mut required_trivial_aliases,
+                            &aliases,
+                            &ret,
+                        );
+                    }
+                }
+                _ => {}
+            }
+        }
+
         Types {
             all,
             structs,
@@ -143,6 +193,7 @@ impl<'a> Types<'a> {
             rust,
             aliases,
             untrusted,
+            required_trivial_aliases,
         }
     }
 
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 1ff8dbf..e61ce84 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -1,4 +1,4 @@
-error: using C++ type by value is not supported
+error: using non-trivial C++ type by value is not supported
  --> $DIR/by_value_not_supported.rs:4:9
   |
 4 |         c: C,
@@ -16,13 +16,13 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: passing C++ type by value is not supported
+error: passing non-trivial C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
 16 |         fn f(c: C) -> C;
    |              ^^^^
 
-error: returning C++ type by value is not supported
+error: returning non-trivial C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:23
    |
 16 |         fn f(c: C) -> C;

From 38f5ad69da170b57bbacc77d0f669863c0055396 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:13 +0000
Subject: [PATCH 946/2232] Move Opaque and Trivial marker types under a ::kind module


In the interest of keeping the root module focused on the most widely
used items only.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9c8a117..fb011d5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -183,7 +183,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
-            type Kind = ::cxx::Opaque;
+            type Kind = ::cxx::kind::Opaque;
         }
     }
 }
@@ -692,7 +692,7 @@ fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream 
     let end = quote_spanned!(end_span=> >);
 
     quote! {
-        const _: fn() = #begin #ident, ::cxx::Trivial #end;
+        const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
     }
 }
 
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 9bc5947..d35b690 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -69,11 +69,11 @@
 /// #     pub struct StringPiece([usize; 2]);
 /// # }
 ///
-/// use cxx::{type_id, ExternType, Opaque};
+/// use cxx::{type_id, ExternType};
 ///
 /// unsafe impl ExternType for folly_sys::StringPiece {
 ///     type Id = type_id!("folly::StringPiece");
-///     type Kind = Opaque;
+///     type Kind = cxx::kind::Opaque;
 /// }
 ///
 /// #[cxx::bridge(namespace = folly)]
@@ -105,7 +105,7 @@
 /// # struct TypeName;
 /// # unsafe impl cxx::ExternType for TypeName {
 /// type Id = cxx::type_id!("name::space::of::TypeName");
-/// type Kind = cxx::Trivial;
+/// type Kind = cxx::kind::Trivial;
 /// # }
 /// ```
 /// which will enable you to pass it into C++ functions by value,
@@ -125,18 +125,17 @@ pub unsafe trait ExternType {
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
     /// type Id = cxx::type_id!("name::space::of::TypeName");
-    /// type Kind = cxx::Opaque;
+    /// type Kind = cxx::kind::Opaque;
     /// # }
     /// ```
     type Id;
 
-    /// Either `cxx::Opaque` or `cxx::Trivial`. If in doubt, use
-    /// `cxx::Opaque`.
+    /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
+    /// `cxx::kind::Opaque`.
     type Kind;
 }
 
-pub(crate) mod kind {
-
+pub mod kind {
     /// An opaque type which can't be passed or held by value within Rust.
     /// For example, a C++ type with a destructor, or a non-trivial move
     /// constructor. Rust's strict move semantics mean that we can't own
diff --git a/src/lib.rs b/src/lib.rs
index b53a7b6..815eacf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -395,9 +395,7 @@ mod unwind;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
-pub use crate::extern_type::kind::Opaque;
-pub use crate::extern_type::kind::Trivial;
-pub use crate::extern_type::ExternType;
+pub use crate::extern_type::{kind, ExternType};
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 

From 1bd502d89379471d41e10483de3f32d5cd4c0fa9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:13 +0000
Subject: [PATCH 947/2232] Add documentation of cxx::kind module


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index d35b690..498a558 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -94,6 +94,8 @@
 /// # fn main() {}
 /// ```
 ///
+/// <br><br>
+///
 /// ## Opaque and Trivial types
 ///
 /// Some C++ types are safe to hold and pass around in Rust, by value.
@@ -135,6 +137,13 @@ pub unsafe trait ExternType {
     type Kind;
 }
 
+/// Marker types identifying Rust's knowledge about an extern C++ type.
+///
+/// These markers are used in the `Kind` associated type in impls of the
+/// [`ExternType`] trait. Refer to the discussion of [Opaque and Trivial
+/// types][trait] for an overview of their purpose.
+///
+/// [trait]: ExternType#opaque-and-trivial-types
 pub mod kind {
     /// An opaque type which can't be passed or held by value within Rust.
     /// For example, a C++ type with a destructor, or a non-trivial move

From 978401978a64c7e0dbd855bb0195da851604cf82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 948/2232] Update documentation of Opaque and Trivial markers


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 498a558..d5a5d67 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -145,15 +145,21 @@ pub unsafe trait ExternType {
 ///
 /// [trait]: ExternType#opaque-and-trivial-types
 pub mod kind {
-    /// An opaque type which can't be passed or held by value within Rust.
-    /// For example, a C++ type with a destructor, or a non-trivial move
-    /// constructor. Rust's strict move semantics mean that we can't own
-    /// these by value in Rust, but they can still be owned by a
-    /// `UniquePtr`...
+    /// An opaque type which cannot be passed or held by value within Rust.
+    ///
+    /// Rust's move semantics are such that every move is equivalent to a
+    /// memcpy. This is incompatible in general with C++'s constructor-based
+    /// move semantics, so a C++ type which has a destructor or nontrivial move
+    /// constructor must never exist by value in Rust. In CXX, such types are
+    /// called opaque C++ types.
+    ///
+    /// When passed across an FFI boundary, an opaque C++ type must be behind an
+    /// indirection such as a reference or UniquePtr.
     pub struct Opaque;
 
-    /// A type with trivial move constructors and no destructor, which
-    /// can therefore be owned and moved around in Rust code directly.
+    /// A type with trivial move constructor and no destructor, which can
+    /// therefore be owned and moved around in Rust code without requiring
+    /// indirection.
     pub struct Trivial;
 }
 

From 4e8c7b9fc6c1e4197bc3b4d7ed07a1a31a9409c3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 949/2232] Move overview of extern type kinds to the Kind associated type


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index d5a5d67..8737d8b 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -93,31 +93,6 @@
 /// #
 /// # fn main() {}
 /// ```
-///
-/// <br><br>
-///
-/// ## Opaque and Trivial types
-///
-/// Some C++ types are safe to hold and pass around in Rust, by value.
-/// Those C++ types must have a trivial move constructor, and must
-/// have no destructor.
-///
-/// If you believe your C++ type is indeed trivial, you can specify
-/// ```
-/// # struct TypeName;
-/// # unsafe impl cxx::ExternType for TypeName {
-/// type Id = cxx::type_id!("name::space::of::TypeName");
-/// type Kind = cxx::kind::Trivial;
-/// # }
-/// ```
-/// which will enable you to pass it into C++ functions by value,
-/// return it by value from such functions, and include it in
-/// `struct`s that you have declared to `cxx::bridge`. Your promises
-/// about the triviality of the C++ type will be checked using
-/// `static_assert`s in the generated C++.
-///
-/// Opaque types can't be passed by value, but can still be held
-/// in `UniquePtr`.
 pub unsafe trait ExternType {
     /// A type-level representation of the type's C++ namespace and type name.
     ///
@@ -134,16 +109,35 @@ pub unsafe trait ExternType {
 
     /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
     /// `cxx::kind::Opaque`.
+    ///
+    /// Some C++ types are safe to hold and pass around in Rust, by value.
+    /// Those C++ types must have a trivial move constructor, and must
+    /// have no destructor.
+    ///
+    /// If you believe your C++ type is indeed trivial, you can specify
+    /// ```
+    /// # struct TypeName;
+    /// # unsafe impl cxx::ExternType for TypeName {
+    /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// type Kind = cxx::kind::Trivial;
+    /// # }
+    /// ```
+    /// which will enable you to pass it into C++ functions by value,
+    /// return it by value from such functions, and include it in
+    /// `struct`s that you have declared to `cxx::bridge`. Your promises
+    /// about the triviality of the C++ type will be checked using
+    /// `static_assert`s in the generated C++.
+    ///
+    /// Opaque types can't be passed by value, but can still be held
+    /// in `UniquePtr`.
     type Kind;
 }
 
 /// Marker types identifying Rust's knowledge about an extern C++ type.
 ///
-/// These markers are used in the `Kind` associated type in impls of the
-/// [`ExternType`] trait. Refer to the discussion of [Opaque and Trivial
-/// types][trait] for an overview of their purpose.
-///
-/// [trait]: ExternType#opaque-and-trivial-types
+/// These markers are used in the [`Kind`][ExternType::Kind] associated type in
+/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
+/// overview of their purpose.
 pub mod kind {
     /// An opaque type which cannot be passed or held by value within Rust.
     ///

From 0d161d2c18f6b0258db2aa947669fe724d0567d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 950/2232] Show only the associated type being discussed


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 8737d8b..b1400ad 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -102,7 +102,7 @@ pub unsafe trait ExternType {
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
     /// type Id = cxx::type_id!("name::space::of::TypeName");
-    /// type Kind = cxx::kind::Opaque;
+    /// #     type Kind = cxx::kind::Opaque;
     /// # }
     /// ```
     type Id;
@@ -118,7 +118,7 @@ pub unsafe trait ExternType {
     /// ```
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
-    /// type Id = cxx::type_id!("name::space::of::TypeName");
+    /// #     type Id = cxx::type_id!("name::space::of::TypeName");
     /// type Kind = cxx::kind::Trivial;
     /// # }
     /// ```

From 73e0582300296aab2d543304511ea5b2a724f393 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 951/2232] Update documentation of ExternType::Kind


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index b1400ad..554c406 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -107,14 +107,22 @@ pub unsafe trait ExternType {
     /// ```
     type Id;
 
-    /// Either `cxx::kind::Opaque` or `cxx::kind::Trivial`. If in doubt, use
-    /// `cxx::kind::Opaque`.
+    /// Either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`].
     ///
-    /// Some C++ types are safe to hold and pass around in Rust, by value.
-    /// Those C++ types must have a trivial move constructor, and must
-    /// have no destructor.
+    /// [`cxx::kind::Opaque`]: kind::Opaque
+    /// [`cxx::kind::Trivial`]: kind::Trivial
+    ///
+    /// A C++ type is only okay to hold and pass around by value in Rust if its
+    /// [move constructor is trivial] and it has no destructor. In CXX, these
+    /// are called Trivial extern C++ types, while types with nontrivial move
+    /// behavior or a destructor must be considered Opaque and handled by Rust
+    /// only behind an indirection, such as a reference or UniquePtr.
+    ///
+    /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
+    ///
+    /// If you believe your C++ type reflected by this ExternType impl is indeed
+    /// trivial, you can specify:
     ///
-    /// If you believe your C++ type is indeed trivial, you can specify
     /// ```
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
@@ -122,14 +130,11 @@ pub unsafe trait ExternType {
     /// type Kind = cxx::kind::Trivial;
     /// # }
     /// ```
-    /// which will enable you to pass it into C++ functions by value,
-    /// return it by value from such functions, and include it in
-    /// `struct`s that you have declared to `cxx::bridge`. Your promises
-    /// about the triviality of the C++ type will be checked using
-    /// `static_assert`s in the generated C++.
     ///
-    /// Opaque types can't be passed by value, but can still be held
-    /// in `UniquePtr`.
+    /// which will enable you to pass it into C++ functions by value, return it
+    /// by value, and include it in `struct`s that you have declared to
+    /// `cxx::bridge`. Your claim about the triviality of the C++ type will be
+    /// checked by a `static_assert` in the generated C++ side of the binding.
     type Kind;
 }
 

From 61ca18da6fa20b3a4bdd0549c3b915de6a5dabe8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 952/2232] Make kind::Opaque and kind::Trivial impossible to instantiate


These marker types are never intended to exist at runtime, only at
compile time in a trait impl.

---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 554c406..ab7b3fd 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -154,12 +154,12 @@ pub mod kind {
     ///
     /// When passed across an FFI boundary, an opaque C++ type must be behind an
     /// indirection such as a reference or UniquePtr.
-    pub struct Opaque;
+    pub enum Opaque {}
 
     /// A type with trivial move constructor and no destructor, which can
     /// therefore be owned and moved around in Rust code without requiring
     /// indirection.
-    pub struct Trivial;
+    pub enum Trivial {}
 }
 
 #[doc(hidden)]

From 43232b9effde329dbfae09316495ddbafd458253 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 953/2232] Add trait bound to ExternType::Kind


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index ab7b3fd..b984f55 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,3 +1,5 @@
+use self::kind::Kind;
+
 /// A type for which the layout is determined by its C++ definition.
 ///
 /// This trait serves the following two related purposes.
@@ -135,7 +137,7 @@ pub unsafe trait ExternType {
     /// by value, and include it in `struct`s that you have declared to
     /// `cxx::bridge`. Your claim about the triviality of the C++ type will be
     /// checked by a `static_assert` in the generated C++ side of the binding.
-    type Kind;
+    type Kind: Kind;
 }
 
 /// Marker types identifying Rust's knowledge about an extern C++ type.
@@ -160,6 +162,10 @@ pub mod kind {
     /// therefore be owned and moved around in Rust code without requiring
     /// indirection.
     pub enum Trivial {}
+
+    pub trait Kind {}
+    impl Kind for Opaque {}
+    impl Kind for Trivial {}
 }
 
 #[doc(hidden)]

From 38670b9a700e77bafa35137167a558c3ddb9d8d6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 03:54:14 +0000
Subject: [PATCH 954/2232] Seal the Kind trait


This trait is not intended to be implementable outside of the cxx crate,
and by sealing we retain the ability to add methods or associated items
into the trait in the future without a breaking change.

---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index b984f55..0432096 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,4 +1,4 @@
-use self::kind::Kind;
+use self::kind::{Kind, Opaque, Trivial};
 
 /// A type for which the layout is determined by its C++ definition.
 ///
@@ -146,6 +146,8 @@ pub unsafe trait ExternType {
 /// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
 /// overview of their purpose.
 pub mod kind {
+    use super::private;
+
     /// An opaque type which cannot be passed or held by value within Rust.
     ///
     /// Rust's move semantics are such that every move is equivalent to a
@@ -163,13 +165,19 @@ pub mod kind {
     /// indirection.
     pub enum Trivial {}
 
-    pub trait Kind {}
+    pub trait Kind: private::Sealed {}
     impl Kind for Opaque {}
     impl Kind for Trivial {}
 }
 
+mod private {
+    pub trait Sealed {}
+    impl Sealed for super::Opaque {}
+    impl Sealed for super::Trivial {}
+}
+
 #[doc(hidden)]
 pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
 
 #[doc(hidden)]
-pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
+pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}

From 445dcc6a33aad1e724ee6664c1d46ffc83ff66e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:02:17 +0000
Subject: [PATCH 955/2232] Merge pull request #333 from dtolnay/kind


Update documentation and API of Trivial and Opaque kind markers
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9c8a117..fb011d5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -183,7 +183,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
-            type Kind = ::cxx::Opaque;
+            type Kind = ::cxx::kind::Opaque;
         }
     }
 }
@@ -692,7 +692,7 @@ fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream 
     let end = quote_spanned!(end_span=> >);
 
     quote! {
-        const _: fn() = #begin #ident, ::cxx::Trivial #end;
+        const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
     }
 }
 
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 9bc5947..0432096 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,3 +1,5 @@
+use self::kind::{Kind, Opaque, Trivial};
+
 /// A type for which the layout is determined by its C++ definition.
 ///
 /// This trait serves the following two related purposes.
@@ -69,11 +71,11 @@
 /// #     pub struct StringPiece([usize; 2]);
 /// # }
 ///
-/// use cxx::{type_id, ExternType, Opaque};
+/// use cxx::{type_id, ExternType};
 ///
 /// unsafe impl ExternType for folly_sys::StringPiece {
 ///     type Id = type_id!("folly::StringPiece");
-///     type Kind = Opaque;
+///     type Kind = cxx::kind::Opaque;
 /// }
 ///
 /// #[cxx::bridge(namespace = folly)]
@@ -93,29 +95,6 @@
 /// #
 /// # fn main() {}
 /// ```
-///
-/// ## Opaque and Trivial types
-///
-/// Some C++ types are safe to hold and pass around in Rust, by value.
-/// Those C++ types must have a trivial move constructor, and must
-/// have no destructor.
-///
-/// If you believe your C++ type is indeed trivial, you can specify
-/// ```
-/// # struct TypeName;
-/// # unsafe impl cxx::ExternType for TypeName {
-/// type Id = cxx::type_id!("name::space::of::TypeName");
-/// type Kind = cxx::Trivial;
-/// # }
-/// ```
-/// which will enable you to pass it into C++ functions by value,
-/// return it by value from such functions, and include it in
-/// `struct`s that you have declared to `cxx::bridge`. Your promises
-/// about the triviality of the C++ type will be checked using
-/// `static_assert`s in the generated C++.
-///
-/// Opaque types can't be passed by value, but can still be held
-/// in `UniquePtr`.
 pub unsafe trait ExternType {
     /// A type-level representation of the type's C++ namespace and type name.
     ///
@@ -125,32 +104,80 @@ pub unsafe trait ExternType {
     /// # struct TypeName;
     /// # unsafe impl cxx::ExternType for TypeName {
     /// type Id = cxx::type_id!("name::space::of::TypeName");
-    /// type Kind = cxx::Opaque;
+    /// #     type Kind = cxx::kind::Opaque;
     /// # }
     /// ```
     type Id;
 
-    /// Either `cxx::Opaque` or `cxx::Trivial`. If in doubt, use
-    /// `cxx::Opaque`.
-    type Kind;
+    /// Either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`].
+    ///
+    /// [`cxx::kind::Opaque`]: kind::Opaque
+    /// [`cxx::kind::Trivial`]: kind::Trivial
+    ///
+    /// A C++ type is only okay to hold and pass around by value in Rust if its
+    /// [move constructor is trivial] and it has no destructor. In CXX, these
+    /// are called Trivial extern C++ types, while types with nontrivial move
+    /// behavior or a destructor must be considered Opaque and handled by Rust
+    /// only behind an indirection, such as a reference or UniquePtr.
+    ///
+    /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
+    ///
+    /// If you believe your C++ type reflected by this ExternType impl is indeed
+    /// trivial, you can specify:
+    ///
+    /// ```
+    /// # struct TypeName;
+    /// # unsafe impl cxx::ExternType for TypeName {
+    /// #     type Id = cxx::type_id!("name::space::of::TypeName");
+    /// type Kind = cxx::kind::Trivial;
+    /// # }
+    /// ```
+    ///
+    /// which will enable you to pass it into C++ functions by value, return it
+    /// by value, and include it in `struct`s that you have declared to
+    /// `cxx::bridge`. Your claim about the triviality of the C++ type will be
+    /// checked by a `static_assert` in the generated C++ side of the binding.
+    type Kind: Kind;
 }
 
-pub(crate) mod kind {
+/// Marker types identifying Rust's knowledge about an extern C++ type.
+///
+/// These markers are used in the [`Kind`][ExternType::Kind] associated type in
+/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an
+/// overview of their purpose.
+pub mod kind {
+    use super::private;
+
+    /// An opaque type which cannot be passed or held by value within Rust.
+    ///
+    /// Rust's move semantics are such that every move is equivalent to a
+    /// memcpy. This is incompatible in general with C++'s constructor-based
+    /// move semantics, so a C++ type which has a destructor or nontrivial move
+    /// constructor must never exist by value in Rust. In CXX, such types are
+    /// called opaque C++ types.
+    ///
+    /// When passed across an FFI boundary, an opaque C++ type must be behind an
+    /// indirection such as a reference or UniquePtr.
+    pub enum Opaque {}
+
+    /// A type with trivial move constructor and no destructor, which can
+    /// therefore be owned and moved around in Rust code without requiring
+    /// indirection.
+    pub enum Trivial {}
 
-    /// An opaque type which can't be passed or held by value within Rust.
-    /// For example, a C++ type with a destructor, or a non-trivial move
-    /// constructor. Rust's strict move semantics mean that we can't own
-    /// these by value in Rust, but they can still be owned by a
-    /// `UniquePtr`...
-    pub struct Opaque;
+    pub trait Kind: private::Sealed {}
+    impl Kind for Opaque {}
+    impl Kind for Trivial {}
+}
 
-    /// A type with trivial move constructors and no destructor, which
-    /// can therefore be owned and moved around in Rust code directly.
-    pub struct Trivial;
+mod private {
+    pub trait Sealed {}
+    impl Sealed for super::Opaque {}
+    impl Sealed for super::Trivial {}
 }
 
 #[doc(hidden)]
 pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
 
 #[doc(hidden)]
-pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind>() {}
+pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
diff --git a/src/lib.rs b/src/lib.rs
index b53a7b6..815eacf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -395,9 +395,7 @@ mod unwind;
 pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
-pub use crate::extern_type::kind::Opaque;
-pub use crate::extern_type::kind::Trivial;
-pub use crate::extern_type::ExternType;
+pub use crate::extern_type::{kind, ExternType};
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 

From 63a0e4ee03a3288aa3a246b973952459ae4688fd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:02:27 +0000
Subject: [PATCH 956/2232] Combine Kind verification into expand_type_alias_verify


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fb011d5..02817a4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -56,11 +56,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             }
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
-                hidden.extend(expand_type_alias_verify(namespace, alias));
-                let ident = &alias.ident;
-                if types.required_trivial_aliases.contains(ident) {
-                    hidden.extend(expand_type_alias_kind_trivial_verify(alias));
-                }
+                hidden.extend(expand_type_alias_verify(namespace, alias, types));
             }
         }
     }
@@ -671,7 +667,11 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     }
 }
 
-fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
+fn expand_type_alias_verify(
+    namespace: &Namespace,
+    alias: &TypeAlias,
+    types: &Types,
+) -> TokenStream {
     let ident = &alias.ident;
     let type_id = type_id(namespace, ident);
     let begin_span = alias.type_token.span;
@@ -679,21 +679,18 @@ fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenSt
     let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
     let end = quote_spanned!(end_span=> >);
 
-    quote! {
+    let mut verify = quote! {
         const _: fn() = #begin #ident, #type_id #end;
-    }
-}
-
-fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream {
-    let ident = &type_alias.ident;
-    let begin_span = type_alias.type_token.span;
-    let end_span = type_alias.semi_token.span;
-    let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
-    let end = quote_spanned!(end_span=> >);
+    };
 
-    quote! {
-        const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
+    if types.required_trivial_aliases.contains(&alias.ident) {
+        let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
+        verify.extend(quote! {
+            const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
+        });
     }
+
+    verify
 }
 
 fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
diff --git a/src/lib.rs b/src/lib.rs
index 815eacf..9287101 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -422,8 +422,7 @@ pub type Vector<T> = CxxVector<T>;
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
-    pub use crate::extern_type::verify_extern_kind;
-    pub use crate::extern_type::verify_extern_type;
+    pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};

From 163564c305bf25ce67310080579bc661840474cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:02:27 +0000
Subject: [PATCH 957/2232] Simplify scan for required trivial aliases using a closure


---

diff --git a/syntax/types.rs b/syntax/types.rs
index ff78268..8ecc417 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -141,44 +141,26 @@ impl<'a> Types<'a> {
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
         let mut required_trivial_aliases = Set::new();
-
-        fn insist_alias_types_are_trivial<'c>(
-            required_trivial_aliases: &mut Set<&'c Ident>,
-            aliases: &Map<&'c Ident, &'c TypeAlias>,
-            ty: &'c Type,
-        ) {
+        let mut insist_alias_types_are_trivial = |ty: &'a Type| {
             if let Type::Ident(ident) = ty {
                 if aliases.contains_key(ident) {
                     required_trivial_aliases.insert(ident);
                 }
             }
-        }
-
+        };
         for api in apis {
             match api {
                 Api::Struct(strct) => {
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &field.ty,
-                        );
+                        insist_alias_types_are_trivial(&field.ty);
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &arg.ty,
-                        );
+                        insist_alias_types_are_trivial(&arg.ty);
                     }
                     if let Some(ret) = &efn.ret {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &ret,
-                        );
+                        insist_alias_types_are_trivial(&ret);
                     }
                 }
                 _ => {}

From 89e386d115393de3d72ac3732ece486736e0bea5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:07:48 +0000
Subject: [PATCH 958/2232] Atom cannot be in required_trivial_aliases


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index e0b1b30..e9e2239 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -129,18 +129,18 @@ pub(super) fn gen(
 fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
-            Type::Ident(ident) => {
-                match Atom::from(ident) {
-                    Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16)
-                    | Some(I32) | Some(I64) => out.include.cstdint = true,
-                    Some(Usize) => out.include.cstddef = true,
-                    Some(CxxString) => out.include.string = true,
-                    Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
-                };
-                if types.required_trivial_aliases.contains(&ident) {
-                    out.include.type_traits = true;
-                };
-            }
+            Type::Ident(ident) => match Atom::from(ident) {
+                Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
+                | Some(I64) => out.include.cstdint = true,
+                Some(Usize) => out.include.cstddef = true,
+                Some(CxxString) => out.include.string = true,
+                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) => {}
+                None => {
+                    if types.required_trivial_aliases.contains(&ident) {
+                        out.include.type_traits = true;
+                    }
+                }
+            },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
             Type::CxxVector(_) => out.include.vector = true,

From 7426cc1c33a5ac3e9721c4daa10e74d288561378 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:07:57 +0000
Subject: [PATCH 959/2232] Wrap the trivial type static assertions


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index e9e2239..ddde8a9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -412,8 +412,24 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
-    writeln!(out, "static_assert(std::is_trivially_move_constructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially move constructible in C++\");", id, id);
-    writeln!(out, "static_assert(std::is_trivially_destructible<{}>::value,\"type {} marked as Trivial in Rust is not trivially destructible in C++\");", id, id);
+    writeln!(out, "static_assert(");
+    writeln!(
+        out,
+        "    std::is_trivially_move_constructible<{}>::value,",
+        id,
+    );
+    writeln!(
+        out,
+        "    \"type {} marked as Trivial in Rust is not trivially move constructible in C++\");",
+        id,
+    );
+    writeln!(out, "static_assert(");
+    writeln!(out, "    std::is_trivially_destructible<{}>::value,", id);
+    writeln!(
+        out,
+        "    \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",
+        id,
+    );
 }
 
 fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {

From 373d70457a8e9907173beb5f410f6e7d53f8e7ca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:09:11 +0000
Subject: [PATCH 960/2232] Merge pull request #334 from dtolnay/kind


Touch up PR 325
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fb011d5..02817a4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -56,11 +56,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             }
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
-                hidden.extend(expand_type_alias_verify(namespace, alias));
-                let ident = &alias.ident;
-                if types.required_trivial_aliases.contains(ident) {
-                    hidden.extend(expand_type_alias_kind_trivial_verify(alias));
-                }
+                hidden.extend(expand_type_alias_verify(namespace, alias, types));
             }
         }
     }
@@ -671,7 +667,11 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     }
 }
 
-fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
+fn expand_type_alias_verify(
+    namespace: &Namespace,
+    alias: &TypeAlias,
+    types: &Types,
+) -> TokenStream {
     let ident = &alias.ident;
     let type_id = type_id(namespace, ident);
     let begin_span = alias.type_token.span;
@@ -679,21 +679,18 @@ fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenSt
     let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_type::<);
     let end = quote_spanned!(end_span=> >);
 
-    quote! {
+    let mut verify = quote! {
         const _: fn() = #begin #ident, #type_id #end;
-    }
-}
-
-fn expand_type_alias_kind_trivial_verify(type_alias: &TypeAlias) -> TokenStream {
-    let ident = &type_alias.ident;
-    let begin_span = type_alias.type_token.span;
-    let end_span = type_alias.semi_token.span;
-    let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
-    let end = quote_spanned!(end_span=> >);
+    };
 
-    quote! {
-        const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
+    if types.required_trivial_aliases.contains(&alias.ident) {
+        let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
+        verify.extend(quote! {
+            const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
+        });
     }
+
+    verify
 }
 
 fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
diff --git a/src/lib.rs b/src/lib.rs
index 815eacf..9287101 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -422,8 +422,7 @@ pub type Vector<T> = CxxVector<T>;
 #[doc(hidden)]
 pub mod private {
     pub use crate::cxx_vector::VectorElement;
-    pub use crate::extern_type::verify_extern_kind;
-    pub use crate::extern_type::verify_extern_type;
+    pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
diff --git a/syntax/types.rs b/syntax/types.rs
index ff78268..8ecc417 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -141,44 +141,26 @@ impl<'a> Types<'a> {
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
         let mut required_trivial_aliases = Set::new();
-
-        fn insist_alias_types_are_trivial<'c>(
-            required_trivial_aliases: &mut Set<&'c Ident>,
-            aliases: &Map<&'c Ident, &'c TypeAlias>,
-            ty: &'c Type,
-        ) {
+        let mut insist_alias_types_are_trivial = |ty: &'a Type| {
             if let Type::Ident(ident) = ty {
                 if aliases.contains_key(ident) {
                     required_trivial_aliases.insert(ident);
                 }
             }
-        }
-
+        };
         for api in apis {
             match api {
                 Api::Struct(strct) => {
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &field.ty,
-                        );
+                        insist_alias_types_are_trivial(&field.ty);
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &arg.ty,
-                        );
+                        insist_alias_types_are_trivial(&arg.ty);
                     }
                     if let Some(ret) = &efn.ret {
-                        insist_alias_types_are_trivial(
-                            &mut required_trivial_aliases,
-                            &aliases,
-                            &ret,
-                        );
+                        insist_alias_types_are_trivial(&ret);
                     }
                 }
                 _ => {}

From 11fd6d0f1bd377ab6f3a774a6cb4a564b0a35f88 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:09:23 +0000
Subject: [PATCH 961/2232] An unordered set suffices for required_trivial_aliases


---

diff --git a/syntax/types.rs b/syntax/types.rs
index 8ecc417..7eb22d4 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,7 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial_aliases: Set<&'a Ident>,
+    pub required_trivial_aliases: UnorderedSet<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -140,7 +140,7 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial_aliases = Set::new();
+        let mut required_trivial_aliases = UnorderedSet::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type| {
             if let Type::Ident(ident) = ty {
                 if aliases.contains_key(ident) {

From b5aca7b8a7ee7b88534d39657beefabd8bed9a01 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:10:02 +0000
Subject: [PATCH 962/2232] Collect reason that each alias is required trivial


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ddde8a9..1f4b7bc 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -81,7 +81,7 @@ pub(super) fn gen(
                 }
             }
             Api::TypeAlias(ety) => {
-                if types.required_trivial_aliases.contains(&ety.ident) {
+                if types.required_trivial_aliases.contains_key(&ety.ident) {
                     check_trivial_extern_type(out, &ety.ident)
                 }
             }
@@ -136,7 +136,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(CxxString) => out.include.string = true,
                 Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) => {}
                 None => {
-                    if types.required_trivial_aliases.contains(&ident) {
+                    if types.required_trivial_aliases.contains_key(&ident) {
                         out.include.type_traits = true;
                     }
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 02817a4..739529f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -683,7 +683,7 @@ fn expand_type_alias_verify(
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial_aliases.contains(&alias.ident) {
+    if types.required_trivial_aliases.contains_key(&alias.ident) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
diff --git a/syntax/check.rs b/syntax/check.rs
index cfac236..1543918 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -338,7 +338,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         || cx.types.cxx.contains(ident)
             && !cx.types.structs.contains_key(ident)
             && !cx.types.enums.contains_key(ident)
-            && !cx.types.required_trivial_aliases.contains(ident)
+            && !cx.types.required_trivial_aliases.contains_key(ident)
         || cx.types.rust.contains(ident)
 }
 
@@ -377,7 +377,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
             } else if cx.types.enums.contains_key(ident) {
                 "enum".to_owned()
             } else if cx.types.cxx.contains(ident) {
-                if cx.types.required_trivial_aliases.contains(ident) {
+                if cx.types.required_trivial_aliases.contains_key(ident) {
                     "trivial C++ type".to_owned()
                 } else {
                     "non-trivial C++ type".to_owned()
diff --git a/syntax/types.rs b/syntax/types.rs
index 7eb22d4..efccb2b 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -14,7 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial_aliases: UnorderedSet<&'a Ident>,
+    pub required_trivial_aliases: Map<&'a Ident, TrivialReason<'a>>,
 }
 
 impl<'a> Types<'a> {
@@ -140,27 +140,30 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial_aliases = UnorderedSet::new();
-        let mut insist_alias_types_are_trivial = |ty: &'a Type| {
+        let mut required_trivial_aliases = Map::new();
+        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
                 if aliases.contains_key(ident) {
-                    required_trivial_aliases.insert(ident);
+                    required_trivial_aliases.entry(ident).or_insert(reason);
                 }
             }
         };
         for api in apis {
             match api {
                 Api::Struct(strct) => {
+                    let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(&field.ty);
+                        insist_alias_types_are_trivial(&field.ty, reason);
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(&arg.ty);
+                        insist_alias_types_are_trivial(&arg.ty, reason);
                     }
                     if let Some(ret) = &efn.ret {
-                        insist_alias_types_are_trivial(&ret);
+                        let reason = TrivialReason::FunctionReturn(efn);
+                        insist_alias_types_are_trivial(&ret, reason);
                     }
                 }
                 _ => {}
@@ -211,6 +214,13 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
+#[derive(Copy, Clone)]
+pub enum TrivialReason<'a> {
+    StructField(&'a Struct),
+    FunctionArgument(&'a ExternFn),
+    FunctionReturn(&'a ExternFn),
+}
+
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
     cx.error(sp, msg);

From 3208fd7a582bee72046b821dae191bac2026bcf0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:10:05 +0000
Subject: [PATCH 963/2232] Provide more helpful error when opaque C++ type used by value


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1f4b7bc..3c81dc8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -81,7 +81,7 @@ pub(super) fn gen(
                 }
             }
             Api::TypeAlias(ety) => {
-                if types.required_trivial_aliases.contains_key(&ety.ident) {
+                if types.required_trivial.contains_key(&ety.ident) {
                     check_trivial_extern_type(out, &ety.ident)
                 }
             }
@@ -136,7 +136,9 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(CxxString) => out.include.string = true,
                 Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) => {}
                 None => {
-                    if types.required_trivial_aliases.contains_key(&ident) {
+                    if types.aliases.contains_key(ident)
+                        && types.required_trivial.contains_key(ident)
+                    {
                         out.include.type_traits = true;
                     }
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 739529f..e7b28b9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -683,7 +683,7 @@ fn expand_type_alias_verify(
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial_aliases.contains_key(&alias.ident) {
+    if types.required_trivial.contains_key(&alias.ident) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
diff --git a/syntax/check.rs b/syntax/check.rs
index 1543918..4960111 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
+use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
     Types,
@@ -208,6 +209,19 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
     check_reserved_name(cx, &ty.ident);
+
+    if let Some(reason) = cx.types.required_trivial.get(&ty.ident) {
+        let what = match reason {
+            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
+            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
+            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident),
+        };
+        let msg = format!(
+            "needs a cxx::ExternType impl in order to be used as {}",
+            what,
+        );
+        cx.error(ty, msg);
+    }
 }
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
@@ -338,7 +352,8 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         || cx.types.cxx.contains(ident)
             && !cx.types.structs.contains_key(ident)
             && !cx.types.enums.contains_key(ident)
-            && !cx.types.required_trivial_aliases.contains_key(ident)
+            && !(cx.types.aliases.contains_key(ident)
+                && cx.types.required_trivial.contains_key(ident))
         || cx.types.rust.contains(ident)
 }
 
@@ -376,12 +391,10 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
                 "struct".to_owned()
             } else if cx.types.enums.contains_key(ident) {
                 "enum".to_owned()
+            } else if cx.types.aliases.contains_key(ident) {
+                "C++ type".to_owned()
             } else if cx.types.cxx.contains(ident) {
-                if cx.types.required_trivial_aliases.contains_key(ident) {
-                    "trivial C++ type".to_owned()
-                } else {
-                    "non-trivial C++ type".to_owned()
-                }
+                "opaque C++ type".to_owned()
             } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
diff --git a/syntax/types.rs b/syntax/types.rs
index efccb2b..6924a78 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,7 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial_aliases: Map<&'a Ident, TrivialReason<'a>>,
+    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
 }
 
 impl<'a> Types<'a> {
@@ -140,11 +140,11 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial_aliases = Map::new();
+        let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if aliases.contains_key(ident) {
-                    required_trivial_aliases.entry(ident).or_insert(reason);
+                if cxx.contains(ident) {
+                    required_trivial.entry(ident).or_insert(reason);
                 }
             }
         };
@@ -178,7 +178,7 @@ impl<'a> Types<'a> {
             rust,
             aliases,
             untrusted,
-            required_trivial_aliases,
+            required_trivial,
         }
     }
 
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index e61ce84..0a56dd4 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -1,4 +1,4 @@
-error: using non-trivial C++ type by value is not supported
+error: using opaque C++ type by value is not supported
  --> $DIR/by_value_not_supported.rs:4:9
   |
 4 |         c: C,
@@ -16,13 +16,19 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: passing non-trivial C++ type by value is not supported
+error: needs a cxx::ExternType impl in order to be used as a field of `S`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
+error: passing opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
 16 |         fn f(c: C) -> C;
    |              ^^^^
 
-error: returning non-trivial C++ type by value is not supported
+error: returning opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:23
    |
 16 |         fn f(c: C) -> C;

From 44198dd15a306922f61da07e08f5aa6492e40a0e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:19:37 +0000
Subject: [PATCH 964/2232] Merge pull request #335 from dtolnay/kind


Add dedicated error message referring to cxx::ExternType when opaque type is used by value
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ddde8a9..3c81dc8 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -81,7 +81,7 @@ pub(super) fn gen(
                 }
             }
             Api::TypeAlias(ety) => {
-                if types.required_trivial_aliases.contains(&ety.ident) {
+                if types.required_trivial.contains_key(&ety.ident) {
                     check_trivial_extern_type(out, &ety.ident)
                 }
             }
@@ -136,7 +136,9 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 Some(CxxString) => out.include.string = true,
                 Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) => {}
                 None => {
-                    if types.required_trivial_aliases.contains(&ident) {
+                    if types.aliases.contains_key(ident)
+                        && types.required_trivial.contains_key(ident)
+                    {
                         out.include.type_traits = true;
                     }
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 02817a4..e7b28b9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -683,7 +683,7 @@ fn expand_type_alias_verify(
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial_aliases.contains(&alias.ident) {
+    if types.required_trivial.contains_key(&alias.ident) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
diff --git a/syntax/check.rs b/syntax/check.rs
index cfac236..4960111 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
+use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
     Types,
@@ -208,6 +209,19 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 
 fn check_api_type(cx: &mut Check, ty: &ExternType) {
     check_reserved_name(cx, &ty.ident);
+
+    if let Some(reason) = cx.types.required_trivial.get(&ty.ident) {
+        let what = match reason {
+            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
+            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
+            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident),
+        };
+        let msg = format!(
+            "needs a cxx::ExternType impl in order to be used as {}",
+            what,
+        );
+        cx.error(ty, msg);
+    }
 }
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
@@ -338,7 +352,8 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         || cx.types.cxx.contains(ident)
             && !cx.types.structs.contains_key(ident)
             && !cx.types.enums.contains_key(ident)
-            && !cx.types.required_trivial_aliases.contains(ident)
+            && !(cx.types.aliases.contains_key(ident)
+                && cx.types.required_trivial.contains_key(ident))
         || cx.types.rust.contains(ident)
 }
 
@@ -376,12 +391,10 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
                 "struct".to_owned()
             } else if cx.types.enums.contains_key(ident) {
                 "enum".to_owned()
+            } else if cx.types.aliases.contains_key(ident) {
+                "C++ type".to_owned()
             } else if cx.types.cxx.contains(ident) {
-                if cx.types.required_trivial_aliases.contains(ident) {
-                    "trivial C++ type".to_owned()
-                } else {
-                    "non-trivial C++ type".to_owned()
-                }
+                "opaque C++ type".to_owned()
             } else if cx.types.rust.contains(ident) {
                 "opaque Rust type".to_owned()
             } else if Atom::from(ident) == Some(CxxString) {
diff --git a/syntax/types.rs b/syntax/types.rs
index 8ecc417..6924a78 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternType, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -14,7 +14,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial_aliases: Set<&'a Ident>,
+    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
 }
 
 impl<'a> Types<'a> {
@@ -140,27 +140,30 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial_aliases = Set::new();
-        let mut insist_alias_types_are_trivial = |ty: &'a Type| {
+        let mut required_trivial = Map::new();
+        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if aliases.contains_key(ident) {
-                    required_trivial_aliases.insert(ident);
+                if cxx.contains(ident) {
+                    required_trivial.entry(ident).or_insert(reason);
                 }
             }
         };
         for api in apis {
             match api {
                 Api::Struct(strct) => {
+                    let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(&field.ty);
+                        insist_alias_types_are_trivial(&field.ty, reason);
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(&arg.ty);
+                        insist_alias_types_are_trivial(&arg.ty, reason);
                     }
                     if let Some(ret) = &efn.ret {
-                        insist_alias_types_are_trivial(&ret);
+                        let reason = TrivialReason::FunctionReturn(efn);
+                        insist_alias_types_are_trivial(&ret, reason);
                     }
                 }
                 _ => {}
@@ -175,7 +178,7 @@ impl<'a> Types<'a> {
             rust,
             aliases,
             untrusted,
-            required_trivial_aliases,
+            required_trivial,
         }
     }
 
@@ -211,6 +214,13 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
+#[derive(Copy, Clone)]
+pub enum TrivialReason<'a> {
+    StructField(&'a Struct),
+    FunctionArgument(&'a ExternFn),
+    FunctionReturn(&'a ExternFn),
+}
+
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
     cx.error(sp, msg);
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index e61ce84..0a56dd4 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -1,4 +1,4 @@
-error: using non-trivial C++ type by value is not supported
+error: using opaque C++ type by value is not supported
  --> $DIR/by_value_not_supported.rs:4:9
   |
 4 |         c: C,
@@ -16,13 +16,19 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: passing non-trivial C++ type by value is not supported
+error: needs a cxx::ExternType impl in order to be used as a field of `S`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
+error: passing opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
 16 |         fn f(c: C) -> C;
    |              ^^^^
 
-error: returning non-trivial C++ type by value is not supported
+error: returning opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:23
    |
 16 |         fn f(c: C) -> C;

From 599fad85bf78d3b3421a4d8f833e618932afd1ca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:21:32 +0000
Subject: [PATCH 965/2232] Debug impl for OrderedSet


---

diff --git a/syntax/set.rs b/syntax/set.rs
index de13088..b553169 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -1,4 +1,5 @@
 use std::collections::HashSet;
+use std::fmt::{self, Debug};
 use std::hash::Hash;
 use std::slice;
 
@@ -47,3 +48,12 @@ impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
         self.0.next().copied()
     }
 }
+
+impl<'a, T> Debug for OrderedSet<&'a T>
+where
+    T: Debug,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.debug_set().entries(self).finish()
+    }
+}

From 4cefa728e050bf342550997450c8564bddb16975 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:24:07 +0000
Subject: [PATCH 966/2232] Consistently use ety for extern type variables


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 4960111..f256948 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -46,7 +46,7 @@ fn do_typecheck(cx: &mut Check) {
         match api {
             Api::Struct(strct) => check_api_struct(cx, strct),
             Api::Enum(enm) => check_api_enum(cx, enm),
-            Api::CxxType(ty) | Api::RustType(ty) => check_api_type(cx, ty),
+            Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             _ => {}
         }
@@ -207,10 +207,10 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
     }
 }
 
-fn check_api_type(cx: &mut Check, ty: &ExternType) {
-    check_reserved_name(cx, &ty.ident);
+fn check_api_type(cx: &mut Check, ety: &ExternType) {
+    check_reserved_name(cx, &ety.ident);
 
-    if let Some(reason) = cx.types.required_trivial.get(&ty.ident) {
+    if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
@@ -220,7 +220,7 @@ fn check_api_type(cx: &mut Check, ty: &ExternType) {
             "needs a cxx::ExternType impl in order to be used as {}",
             what,
         );
-        cx.error(ty, msg);
+        cx.error(ety, msg);
     }
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c1c565f..cec818d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -221,7 +221,7 @@ fn parse_foreign_mod(
     }
 
     let mut types = items.iter().filter_map(|item| match item {
-        Api::CxxType(ty) | Api::RustType(ty) => Some(&ty.ident),
+        Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident),
         Api::TypeAlias(alias) => Some(&alias.ident),
         _ => None,
     });

From fabca77bf8a0cfe9f2b945dd1e351aa214263b0f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 04:25:41 +0000
Subject: [PATCH 967/2232] Move type alias trivial asserts to section


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3c81dc8..4276e9b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -80,15 +80,19 @@ pub(super) fn gen(
                     write_struct_with_methods(out, ety, methods);
                 }
             }
-            Api::TypeAlias(ety) => {
-                if types.required_trivial.contains_key(&ety.ident) {
-                    check_trivial_extern_type(out, &ety.ident)
-                }
-            }
             _ => {}
         }
     }
 
+    out.next_section();
+    for api in apis {
+        if let Api::TypeAlias(ety) = api {
+            if types.required_trivial.contains_key(&ety.ident) {
+                check_trivial_extern_type(out, &ety.ident)
+            }
+        }
+    }
+
     if !header {
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);

From a291281acc7c105b9dcf358ef6762fb75f578201 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 06:23:02 +0000
Subject: [PATCH 968/2232] Add explanatory readmes to .devcontainer and .vscode dirs


---

diff --git a/.devcontainer/README.md b/.devcontainer/README.md
new file mode 100644
index 0000000..b30aebc
--- /dev/null
+++ b/.devcontainer/README.md
@@ -0,0 +1,4 @@
+This directory contains the container setup used when developing CXX inside of
+GitHub [Codespaces].
+
+[Codespaces]: https://github.com/features/codespaces
diff --git a/.vscode/README.md b/.vscode/README.md
new file mode 100644
index 0000000..5ed5b27
--- /dev/null
+++ b/.vscode/README.md
@@ -0,0 +1,4 @@
+VS Code actions and configuration. Applicable when developing CXX inside of
+GitHub [Codespaces].
+
+[Codespaces]: https://github.com/features/codespaces

From 762f0419749520a363c5c266923529d507d9f8b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 06:24:42 +0000
Subject: [PATCH 969/2232] Fix behavior of --include and --output flags


It was not intended that these would consume multiple arguments after a
single instance of the flag.

---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index 152f11a..bd3bcfd 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -136,6 +136,7 @@ into the generated C++ code as #include lines.
         .short("i")
         .takes_value(true)
         .multiple(true)
+        .number_of_values(1)
         .validator_os(validate_utf8)
         .help(HELP)
 }
@@ -150,6 +151,7 @@ not specified.
         .short("o")
         .takes_value(true)
         .multiple(true)
+        .number_of_values(1)
         .validator_os(validate_utf8)
         .help(HELP)
 }

From c86633d53c1150048cbcb2605403ffb227c853b4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 06:48:58 +0000
Subject: [PATCH 970/2232] Generalize OrderedSet::contains method


---

diff --git a/syntax/set.rs b/syntax/set.rs
index b553169..891df60 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -1,3 +1,4 @@
+use std::borrow::Borrow;
 use std::collections::HashSet;
 use std::fmt::{self, Debug};
 use std::hash::Hash;
@@ -27,7 +28,11 @@ where
         new
     }
 
-    pub fn contains(&self, value: &T) -> bool {
+    pub fn contains<Q>(&self, value: &Q) -> bool
+    where
+        &'a T: Borrow<Q>,
+        Q: ?Sized + Hash + Eq,
+    {
         self.set.contains(value)
     }
 }

From 7e69f89714717d7f6ca8ea3d2056035d860fd6cb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:20:17 +0000
Subject: [PATCH 971/2232] Explicitly requesting an instantiation


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4276e9b..b83611a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1056,14 +1056,18 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
+                if Atom::from(inner).is_none()
+                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
+                if Atom::from(inner).is_none()
+                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e7b28b9..4778b14 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -39,7 +39,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 
     for api in apis {
         match api {
-            Api::Include(_) | Api::RustType(_) => {}
+            Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -76,13 +76,17 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
+                if Atom::from(ident).is_none()
+                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                {
                     expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
+                if Atom::from(ident).is_none()
+                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
diff --git a/syntax/check.rs b/syntax/check.rs
index f256948..ff23ec9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,8 +3,8 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
-    Types,
+    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Slice, Struct, Ty1,
+    Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -48,6 +48,7 @@ fn do_typecheck(cx: &mut Check) {
             Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
+            Api::Impl(imp) => check_api_impl(cx, imp),
             _ => {}
         }
     }
@@ -286,6 +287,18 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     check_multiple_arg_lifetimes(cx, efn);
 }
 
+fn check_api_impl(cx: &mut Check, imp: &Impl) {
+    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
+        if let Type::Ident(inner) = &ty.inner {
+            if Atom::from(inner).is_none() {
+                return;
+            }
+        }
+    }
+
+    cx.error(imp, "unsupported Self type of explicit impl");
+}
+
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutability.is_some() => {}
diff --git a/syntax/file.rs b/syntax/file.rs
index 8b86adc..931ce6e 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -2,8 +2,8 @@ use crate::syntax::namespace::Namespace;
 use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
 use syn::{
-    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
-    ItemUse, LitStr, Token, Visibility,
+    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
+    ItemStruct, ItemUse, LitStr, Token, Visibility,
 };
 
 pub struct Module {
@@ -22,6 +22,7 @@ pub enum Item {
     Enum(ItemEnum),
     ForeignMod(ItemForeignMod),
     Use(ItemUse),
+    Impl(ItemImpl),
     Other(RustItem),
 }
 
@@ -99,6 +100,7 @@ impl Parse for Item {
                 brace_token: item.brace_token,
                 items: item.items,
             })),
+            RustItem::Impl(item) => Ok(Item::Impl(ItemImpl { attrs, ..item })),
             RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
             other => Ok(Item::Other(other)),
         }
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 7545e92..74e7799 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -20,7 +20,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
 
     for api in apis {
         match api {
-            Api::Include(_) => {}
+            Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
                 check(cx, &strct.ident);
                 for field in &strct.fields {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8ef3c8b..934f6c6 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -42,6 +42,7 @@ pub enum Api {
     RustType(ExternType),
     RustFunction(ExternFn),
     TypeAlias(TypeAlias),
+    Impl(Impl),
 }
 
 pub struct ExternType {
@@ -87,6 +88,12 @@ pub struct TypeAlias {
     pub semi_token: Token![;],
 }
 
+pub struct Impl {
+    pub impl_token: Token![impl],
+    pub ty: Type,
+    pub brace_token: Brace,
+}
+
 pub struct Signature {
     pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index cec818d..49dc26b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,17 +3,17 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::{TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, ItemEnum, ItemStruct, LitStr, Pat, PathArguments, Result, ReturnType,
-    Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat, PathArguments, Result,
+    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -33,6 +33,10 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api>
                 Err(err) => cx.push(err),
             },
             Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
+            Item::Impl(item) => match parse_impl(item) {
+                Ok(imp) => apis.push(imp),
+                Err(err) => cx.push(err),
+            },
             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
             Item::Other(item) => cx.error(item, "unsupported item"),
         }
@@ -420,6 +424,37 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
+fn parse_impl(imp: ItemImpl) -> Result<Api> {
+    if !imp.items.is_empty() {
+        let mut span = Group::new(Delimiter::Brace, TokenStream::new());
+        span.set_span(imp.brace_token.span);
+        return Err(Error::new_spanned(span, "expected an empty impl block"));
+    }
+
+    let self_ty = &imp.self_ty;
+    if let Some((bang, path, for_token)) = &imp.trait_ {
+        let span = quote!(#bang #path #for_token #self_ty);
+        return Err(Error::new_spanned(
+            span,
+            "unexpected impl, expected something like `impl UniquePtr<T> {}`",
+        ));
+    }
+
+    let generics = &imp.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        return Err(Error::new_spanned(
+            imp,
+            "generic parameters on an impl is not supported",
+        ));
+    }
+
+    Ok(Api::Impl(Impl {
+        impl_token: imp.impl_token,
+        ty: parse_type(&self_ty)?,
+        brace_token: imp.brace_token,
+    }))
+}
+
 fn parse_include(input: ParseStream) -> Result<String> {
     if input.peek(LitStr) {
         return Ok(input.parse::<LitStr>()?.value());
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 4ed264a..7618e99 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
-    TypeAlias, Var,
+    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, Signature, Slice, Struct, Ty1,
+    Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -121,6 +121,14 @@ impl ToTokens for ExternFn {
     }
 }
 
+impl ToTokens for Impl {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.impl_token.to_tokens(tokens);
+        self.ty.to_tokens(tokens);
+        self.brace_token.surround(tokens, |_tokens| {});
+    }
+}
+
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.fn_token.to_tokens(tokens);
diff --git a/syntax/types.rs b/syntax/types.rs
index 6924a78..2afce25 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -15,6 +15,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
+    pub explicit_impls: Set<&'a Type>,
 }
 
 impl<'a> Types<'a> {
@@ -26,6 +27,7 @@ impl<'a> Types<'a> {
         let mut rust = Set::new();
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
+        let mut explicit_impls = Set::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -133,6 +135,10 @@ impl<'a> Types<'a> {
                     cxx.insert(ident);
                     aliases.insert(ident, alias);
                 }
+                Api::Impl(imp) => {
+                    visit(&mut all, &imp.ty);
+                    explicit_impls.insert(&imp.ty);
+                }
             }
         }
 
@@ -179,6 +185,7 @@ impl<'a> Types<'a> {
             aliases,
             untrusted,
             required_trivial,
+            explicit_impls,
         }
     }
 

From ac8394bd1897a1f1880238a4fecc5cf5f45d21c0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:20:21 +0000
Subject: [PATCH 972/2232] Add test of UniquePtrTarget impl conflict


---

diff --git a/tests/ui/unique_ptr_twice.rs b/tests/ui/unique_ptr_twice.rs
new file mode 100644
index 0000000..b6cb4d4
--- /dev/null
+++ b/tests/ui/unique_ptr_twice.rs
@@ -0,0 +1,19 @@
+#[cxx::bridge]
+mod here {
+    extern "C" {
+        type C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+#[cxx::bridge]
+mod there {
+    extern "C" {
+        type C = crate::here::C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+fn main() {}
diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
new file mode 100644
index 0000000..d77d3ff
--- /dev/null
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
+  --> $DIR/unique_ptr_twice.rs:10:1
+   |
+1  | #[cxx::bridge]
+   | -------------- first implementation here
+...
+10 | #[cxx::bridge]
+   | ^^^^^^^^^^^^^^ conflicting implementation for `here::C`
+   |
+   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 50b7563de4e41dace6477d707d33fa5bd4141d85 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:20:22 +0000
Subject: [PATCH 973/2232] Add ui test of explicit impl with unsupported Self


---

diff --git a/tests/ui/bad_explicit_impl.rs b/tests/ui/bad_explicit_impl.rs
new file mode 100644
index 0000000..2106446
--- /dev/null
+++ b/tests/ui/bad_explicit_impl.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl fn() -> &S {}
+}
+
+fn main() {}
diff --git a/tests/ui/bad_explicit_impl.stderr b/tests/ui/bad_explicit_impl.stderr
new file mode 100644
index 0000000..cd0a317
--- /dev/null
+++ b/tests/ui/bad_explicit_impl.stderr
@@ -0,0 +1,5 @@
+error: unsupported Self type of explicit impl
+ --> $DIR/bad_explicit_impl.rs:7:5
+  |
+7 |     impl fn() -> &S {}
+  |     ^^^^^^^^^^^^^^^^^^

From 2b3c2b2fa4ac49ddd382d3dded3fdb9008c4162c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:20:22 +0000
Subject: [PATCH 974/2232] Add ui test of invalid nonempty impl block


---

diff --git a/tests/ui/nonempty_impl_block.rs b/tests/ui/nonempty_impl_block.rs
new file mode 100644
index 0000000..239d1ec
--- /dev/null
+++ b/tests/ui/nonempty_impl_block.rs
@@ -0,0 +1,12 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl UniquePtr<S> {
+        fn new() -> Self;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nonempty_impl_block.stderr b/tests/ui/nonempty_impl_block.stderr
new file mode 100644
index 0000000..e7881bb
--- /dev/null
+++ b/tests/ui/nonempty_impl_block.stderr
@@ -0,0 +1,8 @@
+error: expected an empty impl block
+ --> $DIR/nonempty_impl_block.rs:7:23
+  |
+7 |       impl UniquePtr<S> {
+  |  _______________________^
+8 | |         fn new() -> Self;
+9 | |     }
+  | |_____^

From 64cab486888bc24fc7e4abbaef6d12f74960f0cb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:20:22 +0000
Subject: [PATCH 975/2232] Add ui test of explicit impl trait for type


---

diff --git a/tests/ui/impl_trait_for_type.rs b/tests/ui/impl_trait_for_type.rs
new file mode 100644
index 0000000..9284f73
--- /dev/null
+++ b/tests/ui/impl_trait_for_type.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl UniquePtrTarget for S {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl_trait_for_type.stderr b/tests/ui/impl_trait_for_type.stderr
new file mode 100644
index 0000000..e05a461
--- /dev/null
+++ b/tests/ui/impl_trait_for_type.stderr
@@ -0,0 +1,5 @@
+error: unexpected impl, expected something like `impl UniquePtr<T> {}`
+ --> $DIR/impl_trait_for_type.rs:7:10
+  |
+7 |     impl UniquePtrTarget for S {}
+  |          ^^^^^^^^^^^^^^^^^^^^^

From 1cbd1b29ddc853fa4d2a965a9ee879d041fe3a83 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:35:35 +0000
Subject: [PATCH 976/2232] Merge pull request #336 from dtolnay/impl


Explicitly requesting an instantiation
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4276e9b..b83611a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1056,14 +1056,18 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
+                if Atom::from(inner).is_none()
+                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
+                if Atom::from(inner).is_none()
+                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e7b28b9..4778b14 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -39,7 +39,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 
     for api in apis {
         match api {
-            Api::Include(_) | Api::RustType(_) => {}
+            Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -76,13 +76,17 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
+                if Atom::from(ident).is_none()
+                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                {
                     expanded.extend(expand_unique_ptr(namespace, ident, types));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
+                if Atom::from(ident).is_none()
+                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
diff --git a/syntax/check.rs b/syntax/check.rs
index f256948..ff23ec9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,8 +3,8 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Slice, Struct, Ty1, Type,
-    Types,
+    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Slice, Struct, Ty1,
+    Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -48,6 +48,7 @@ fn do_typecheck(cx: &mut Check) {
             Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
+            Api::Impl(imp) => check_api_impl(cx, imp),
             _ => {}
         }
     }
@@ -286,6 +287,18 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     check_multiple_arg_lifetimes(cx, efn);
 }
 
+fn check_api_impl(cx: &mut Check, imp: &Impl) {
+    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
+        if let Type::Ident(inner) = &ty.inner {
+            if Atom::from(inner).is_none() {
+                return;
+            }
+        }
+    }
+
+    cx.error(imp, "unsupported Self type of explicit impl");
+}
+
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutability.is_some() => {}
diff --git a/syntax/file.rs b/syntax/file.rs
index 8b86adc..931ce6e 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -2,8 +2,8 @@ use crate::syntax::namespace::Namespace;
 use quote::quote;
 use syn::parse::{Error, Parse, ParseStream, Result};
 use syn::{
-    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
-    ItemUse, LitStr, Token, Visibility,
+    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
+    ItemStruct, ItemUse, LitStr, Token, Visibility,
 };
 
 pub struct Module {
@@ -22,6 +22,7 @@ pub enum Item {
     Enum(ItemEnum),
     ForeignMod(ItemForeignMod),
     Use(ItemUse),
+    Impl(ItemImpl),
     Other(RustItem),
 }
 
@@ -99,6 +100,7 @@ impl Parse for Item {
                 brace_token: item.brace_token,
                 items: item.items,
             })),
+            RustItem::Impl(item) => Ok(Item::Impl(ItemImpl { attrs, ..item })),
             RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
             other => Ok(Item::Other(other)),
         }
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 7545e92..74e7799 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -20,7 +20,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
 
     for api in apis {
         match api {
-            Api::Include(_) => {}
+            Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
                 check(cx, &strct.ident);
                 for field in &strct.fields {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8ef3c8b..934f6c6 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -42,6 +42,7 @@ pub enum Api {
     RustType(ExternType),
     RustFunction(ExternFn),
     TypeAlias(TypeAlias),
+    Impl(Impl),
 }
 
 pub struct ExternType {
@@ -87,6 +88,12 @@ pub struct TypeAlias {
     pub semi_token: Token![;],
 }
 
+pub struct Impl {
+    pub impl_token: Token![impl],
+    pub ty: Type,
+    pub brace_token: Brace,
+}
+
 pub struct Signature {
     pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index cec818d..49dc26b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,17 +3,17 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::{TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, ItemEnum, ItemStruct, LitStr, Pat, PathArguments, Result, ReturnType,
-    Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat, PathArguments, Result,
+    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -33,6 +33,10 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api>
                 Err(err) => cx.push(err),
             },
             Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
+            Item::Impl(item) => match parse_impl(item) {
+                Ok(imp) => apis.push(imp),
+                Err(err) => cx.push(err),
+            },
             Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
             Item::Other(item) => cx.error(item, "unsupported item"),
         }
@@ -420,6 +424,37 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
+fn parse_impl(imp: ItemImpl) -> Result<Api> {
+    if !imp.items.is_empty() {
+        let mut span = Group::new(Delimiter::Brace, TokenStream::new());
+        span.set_span(imp.brace_token.span);
+        return Err(Error::new_spanned(span, "expected an empty impl block"));
+    }
+
+    let self_ty = &imp.self_ty;
+    if let Some((bang, path, for_token)) = &imp.trait_ {
+        let span = quote!(#bang #path #for_token #self_ty);
+        return Err(Error::new_spanned(
+            span,
+            "unexpected impl, expected something like `impl UniquePtr<T> {}`",
+        ));
+    }
+
+    let generics = &imp.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        return Err(Error::new_spanned(
+            imp,
+            "generic parameters on an impl is not supported",
+        ));
+    }
+
+    Ok(Api::Impl(Impl {
+        impl_token: imp.impl_token,
+        ty: parse_type(&self_ty)?,
+        brace_token: imp.brace_token,
+    }))
+}
+
 fn parse_include(input: ParseStream) -> Result<String> {
     if input.peek(LitStr) {
         return Ok(input.parse::<LitStr>()?.value());
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 4ed264a..7618e99 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Receiver, Ref, Signature, Slice, Struct, Ty1, Type,
-    TypeAlias, Var,
+    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, Signature, Slice, Struct, Ty1,
+    Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -121,6 +121,14 @@ impl ToTokens for ExternFn {
     }
 }
 
+impl ToTokens for Impl {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.impl_token.to_tokens(tokens);
+        self.ty.to_tokens(tokens);
+        self.brace_token.surround(tokens, |_tokens| {});
+    }
+}
+
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.fn_token.to_tokens(tokens);
diff --git a/syntax/types.rs b/syntax/types.rs
index 6924a78..2afce25 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -15,6 +15,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
+    pub explicit_impls: Set<&'a Type>,
 }
 
 impl<'a> Types<'a> {
@@ -26,6 +27,7 @@ impl<'a> Types<'a> {
         let mut rust = Set::new();
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
+        let mut explicit_impls = Set::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -133,6 +135,10 @@ impl<'a> Types<'a> {
                     cxx.insert(ident);
                     aliases.insert(ident, alias);
                 }
+                Api::Impl(imp) => {
+                    visit(&mut all, &imp.ty);
+                    explicit_impls.insert(&imp.ty);
+                }
             }
         }
 
@@ -179,6 +185,7 @@ impl<'a> Types<'a> {
             aliases,
             untrusted,
             required_trivial,
+            explicit_impls,
         }
     }
 
diff --git a/tests/ui/bad_explicit_impl.rs b/tests/ui/bad_explicit_impl.rs
new file mode 100644
index 0000000..2106446
--- /dev/null
+++ b/tests/ui/bad_explicit_impl.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl fn() -> &S {}
+}
+
+fn main() {}
diff --git a/tests/ui/bad_explicit_impl.stderr b/tests/ui/bad_explicit_impl.stderr
new file mode 100644
index 0000000..cd0a317
--- /dev/null
+++ b/tests/ui/bad_explicit_impl.stderr
@@ -0,0 +1,5 @@
+error: unsupported Self type of explicit impl
+ --> $DIR/bad_explicit_impl.rs:7:5
+  |
+7 |     impl fn() -> &S {}
+  |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl_trait_for_type.rs b/tests/ui/impl_trait_for_type.rs
new file mode 100644
index 0000000..9284f73
--- /dev/null
+++ b/tests/ui/impl_trait_for_type.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl UniquePtrTarget for S {}
+}
+
+fn main() {}
diff --git a/tests/ui/impl_trait_for_type.stderr b/tests/ui/impl_trait_for_type.stderr
new file mode 100644
index 0000000..e05a461
--- /dev/null
+++ b/tests/ui/impl_trait_for_type.stderr
@@ -0,0 +1,5 @@
+error: unexpected impl, expected something like `impl UniquePtr<T> {}`
+ --> $DIR/impl_trait_for_type.rs:7:10
+  |
+7 |     impl UniquePtrTarget for S {}
+  |          ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/nonempty_impl_block.rs b/tests/ui/nonempty_impl_block.rs
new file mode 100644
index 0000000..239d1ec
--- /dev/null
+++ b/tests/ui/nonempty_impl_block.rs
@@ -0,0 +1,12 @@
+#[cxx::bridge]
+mod ffi {
+    struct S {
+        x: u8,
+    }
+
+    impl UniquePtr<S> {
+        fn new() -> Self;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nonempty_impl_block.stderr b/tests/ui/nonempty_impl_block.stderr
new file mode 100644
index 0000000..e7881bb
--- /dev/null
+++ b/tests/ui/nonempty_impl_block.stderr
@@ -0,0 +1,8 @@
+error: expected an empty impl block
+ --> $DIR/nonempty_impl_block.rs:7:23
+  |
+7 |       impl UniquePtr<S> {
+  |  _______________________^
+8 | |         fn new() -> Self;
+9 | |     }
+  | |_____^
diff --git a/tests/ui/unique_ptr_twice.rs b/tests/ui/unique_ptr_twice.rs
new file mode 100644
index 0000000..b6cb4d4
--- /dev/null
+++ b/tests/ui/unique_ptr_twice.rs
@@ -0,0 +1,19 @@
+#[cxx::bridge]
+mod here {
+    extern "C" {
+        type C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+#[cxx::bridge]
+mod there {
+    extern "C" {
+        type C = crate::here::C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+fn main() {}
diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
new file mode 100644
index 0000000..d77d3ff
--- /dev/null
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
+  --> $DIR/unique_ptr_twice.rs:10:1
+   |
+1  | #[cxx::bridge]
+   | -------------- first implementation here
+...
+10 | #[cxx::bridge]
+   | ^^^^^^^^^^^^^^ conflicting implementation for `here::C`
+   |
+   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 6586c69a114a274481cbab1017927d6273419b4d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:36:47 +0000
Subject: [PATCH 977/2232] Store original Impl in explicit impls set


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index ebebb3e..6a177d5 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,5 @@
-use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{ExternFn, Impl, Receiver, Ref, Signature, Slice, Ty1, Type};
+use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
@@ -238,3 +239,38 @@ impl Hash for Receiver {
         ty.hash(state);
     }
 }
+
+impl Hash for Impl {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Impl {
+            impl_token: _,
+            ty,
+            brace_token: _,
+        } = self;
+        ty.hash(state);
+    }
+}
+
+impl Eq for Impl {}
+
+impl PartialEq for Impl {
+    fn eq(&self, other: &Impl) -> bool {
+        let Impl {
+            impl_token: _,
+            ty,
+            brace_token: _,
+        } = self;
+        let Impl {
+            impl_token: _,
+            ty: ty2,
+            brace_token: _,
+        } = other;
+        ty == ty2
+    }
+}
+
+impl Borrow<Type> for &Impl {
+    fn borrow(&self) -> &Type {
+        &self.ty
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 2afce25..3f8d10c 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Impl, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -15,7 +15,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
-    pub explicit_impls: Set<&'a Type>,
+    pub explicit_impls: Set<&'a Impl>,
 }
 
 impl<'a> Types<'a> {
@@ -137,7 +137,7 @@ impl<'a> Types<'a> {
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
-                    explicit_impls.insert(&imp.ty);
+                    explicit_impls.insert(imp);
                 }
             }
         }

From 0531f43ce9c777b8e579a87f0411bf9b328158ce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:36:56 +0000
Subject: [PATCH 978/2232] Improve error message on a conflicting explicit impl


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4778b14..13134d0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -4,9 +4,10 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Signature, Struct, Type, TypeAlias,
+    Types,
 };
-use proc_macro2::{Ident, TokenStream};
+use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
 use syn::{parse_quote, Result, Token};
@@ -62,6 +63,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 
     for ty in types {
+        let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
                 if Atom::from(ident).is_none() {
@@ -77,20 +79,20 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none()
-                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
                 {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types));
+                    expanded.extend(expand_unique_ptr(namespace, ident, types, explicit_impl));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none()
-                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
                 {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
-                    expanded.extend(expand_cxx_vector(namespace, ident));
+                    expanded.extend(expand_cxx_vector(namespace, ident, explicit_impl));
                 }
             }
         }
@@ -784,7 +786,12 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
+fn expand_unique_ptr(
+    namespace: &Namespace,
+    ident: &Ident,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
     let name = ident.to_string();
     let prefix = format!("cxxbridge04$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
@@ -810,8 +817,13 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
         None
     };
 
-    quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::UniquePtrTarget for #ident {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -857,7 +869,12 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     }
 }
 
-fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
+fn expand_cxx_vector(
+    namespace: &Namespace,
+    elem: &Ident,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let _ = explicit_impl;
     let name = elem.to_string();
     let prefix = format!("cxxbridge04$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
@@ -869,8 +886,13 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
-    quote! {
-        unsafe impl ::cxx::private::VectorElement for #elem {
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::VectorElement for #elem {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
diff --git a/syntax/set.rs b/syntax/set.rs
index 891df60..73e3909 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -35,6 +35,14 @@ where
     {
         self.set.contains(value)
     }
+
+    pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
+    where
+        &'a T: Borrow<Q>,
+        Q: ?Sized + Hash + Eq,
+    {
+        self.set.get(value).copied()
+    }
 }
 
 impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
index d77d3ff..5686cf1 100644
--- a/tests/ui/unique_ptr_twice.stderr
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -1,10 +1,8 @@
 error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
-  --> $DIR/unique_ptr_twice.rs:10:1
+  --> $DIR/unique_ptr_twice.rs:16:5
    |
-1  | #[cxx::bridge]
-   | -------------- first implementation here
+7  |     impl UniquePtr<C> {}
+   |     ----------------- first implementation here
 ...
-10 | #[cxx::bridge]
-   | ^^^^^^^^^^^^^^ conflicting implementation for `here::C`
-   |
-   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+16 |     impl UniquePtr<C> {}
+   |     ^^^^^^^^^^^^^^^^^ conflicting implementation for `here::C`

From debd9d5bf325adbbf070434a8d6acfb390c04948 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 07:48:22 +0000
Subject: [PATCH 979/2232] Merge pull request #337 from dtolnay/impl


Improve error message on a conflicting explicit impl
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4778b14..13134d0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -4,9 +4,10 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Signature, Struct, Type, TypeAlias,
+    Types,
 };
-use proc_macro2::{Ident, TokenStream};
+use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
 use syn::{parse_quote, Result, Token};
@@ -62,6 +63,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 
     for ty in types {
+        let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
                 if Atom::from(ident).is_none() {
@@ -77,20 +79,20 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none()
-                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
                 {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types));
+                    expanded.extend(expand_unique_ptr(namespace, ident, types, explicit_impl));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(ident).is_none()
-                    && (!types.aliases.contains_key(ident) || types.explicit_impls.contains(ty))
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
                 {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
-                    expanded.extend(expand_cxx_vector(namespace, ident));
+                    expanded.extend(expand_cxx_vector(namespace, ident, explicit_impl));
                 }
             }
         }
@@ -784,7 +786,12 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> TokenStream {
+fn expand_unique_ptr(
+    namespace: &Namespace,
+    ident: &Ident,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
     let name = ident.to_string();
     let prefix = format!("cxxbridge04$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
@@ -810,8 +817,13 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
         None
     };
 
-    quote! {
-        unsafe impl ::cxx::private::UniquePtrTarget for #ident {
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::UniquePtrTarget for #ident {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -857,7 +869,12 @@ fn expand_unique_ptr(namespace: &Namespace, ident: &Ident, types: &Types) -> Tok
     }
 }
 
-fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
+fn expand_cxx_vector(
+    namespace: &Namespace,
+    elem: &Ident,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let _ = explicit_impl;
     let name = elem.to_string();
     let prefix = format!("cxxbridge04$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
@@ -869,8 +886,13 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream {
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
-    quote! {
-        unsafe impl ::cxx::private::VectorElement for #elem {
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::VectorElement for #elem {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index ebebb3e..6a177d5 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,5 @@
-use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{ExternFn, Impl, Receiver, Ref, Signature, Slice, Ty1, Type};
+use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
@@ -238,3 +239,38 @@ impl Hash for Receiver {
         ty.hash(state);
     }
 }
+
+impl Hash for Impl {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Impl {
+            impl_token: _,
+            ty,
+            brace_token: _,
+        } = self;
+        ty.hash(state);
+    }
+}
+
+impl Eq for Impl {}
+
+impl PartialEq for Impl {
+    fn eq(&self, other: &Impl) -> bool {
+        let Impl {
+            impl_token: _,
+            ty,
+            brace_token: _,
+        } = self;
+        let Impl {
+            impl_token: _,
+            ty: ty2,
+            brace_token: _,
+        } = other;
+        ty == ty2
+    }
+}
+
+impl Borrow<Type> for &Impl {
+    fn borrow(&self) -> &Type {
+        &self.ty
+    }
+}
diff --git a/syntax/set.rs b/syntax/set.rs
index 891df60..73e3909 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -35,6 +35,14 @@ where
     {
         self.set.contains(value)
     }
+
+    pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
+    where
+        &'a T: Borrow<Q>,
+        Q: ?Sized + Hash + Eq,
+    {
+        self.set.get(value).copied()
+    }
 }
 
 impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
diff --git a/syntax/types.rs b/syntax/types.rs
index 2afce25..3f8d10c 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Struct, Type, TypeAlias};
+use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Impl, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -15,7 +15,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
-    pub explicit_impls: Set<&'a Type>,
+    pub explicit_impls: Set<&'a Impl>,
 }
 
 impl<'a> Types<'a> {
@@ -137,7 +137,7 @@ impl<'a> Types<'a> {
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
-                    explicit_impls.insert(&imp.ty);
+                    explicit_impls.insert(imp);
                 }
             }
         }
diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
index d77d3ff..5686cf1 100644
--- a/tests/ui/unique_ptr_twice.stderr
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -1,10 +1,8 @@
 error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
-  --> $DIR/unique_ptr_twice.rs:10:1
+  --> $DIR/unique_ptr_twice.rs:16:5
    |
-1  | #[cxx::bridge]
-   | -------------- first implementation here
+7  |     impl UniquePtr<C> {}
+   |     ----------------- first implementation here
 ...
-10 | #[cxx::bridge]
-   | ^^^^^^^^^^^^^^ conflicting implementation for `here::C`
-   |
-   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+16 |     impl UniquePtr<C> {}
+   |     ^^^^^^^^^^^^^^^^^ conflicting implementation for `here::C`

From d93afe7a92bc8ba403c72d825c7e759e4f9cb692 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 20:07:23 +0000
Subject: [PATCH 980/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index d4c77b9..f07de50 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -40,7 +40,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.21/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.24/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "proc-macro",
@@ -64,7 +64,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.41/src/**"]),
+    srcs = glob(["vendor/syn-1.0.42/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index e5cb808..0d602a8 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -45,7 +45,7 @@ rust_library(
 
 rust_library(
     name = "proc-macro2",
-    srcs = glob(["vendor/proc-macro2-1.0.21/src/**"]),
+    srcs = glob(["vendor/proc-macro2-1.0.24/src/**"]),
     crate_features = [
         "proc-macro",
         "span-locations",
@@ -69,7 +69,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.41/src/**"]),
+    srcs = glob(["vendor/syn-1.0.42/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 1c43f70..00ecb95 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -171,24 +171,24 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.77"
+version = "0.2.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
+checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98"
 
 [[package]]
 name = "link-cplusplus"
-version = "1.0.2"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f563b3814ea63e830e3e321206e4e2b5177854586ebe3f595795ed7053b217f5"
+checksum = "372d61b8ffdc79aa85d5f679e16c9e34da2357796186e877001f21998ece1f99"
 dependencies = [
  "cc",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.21"
+version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c"
+checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
 dependencies = [
  "unicode-xid",
 ]
@@ -241,9 +241,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.57"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
+checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4"
 dependencies = [
  "itoa",
  "ryu",
@@ -258,9 +258,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.41"
+version = "1.0.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
+checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228"
 dependencies = [
  "proc-macro2",
  "quote",

From fd0034ecf32a1f53d666782dc14c8de56488c5b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 20:15:34 +0000
Subject: [PATCH 981/2232] Add some thoughts about the triviality static assertions


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b83611a..1a071a2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -418,6 +418,24 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+    // 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:
+    //
+    //     unsafe impl ExternType for MyType {
+    //         type Id = cxx::type_id!("...");
+    //         type Kind = cxx::kind::Trivial;
+    //     }
+    //
+    // Since the user went on the record with their unsafe impl to unsafely
+    // claim they KNOW that the type is trivial, it's fine for that to be on
+    // them if that were wrong.
+    //
+    // There may be a legitimate reason we'll want to remove these assertions
+    // for support of types that the programmer knows are Rust-movable despite
+    // not being recognized as such by the C++ type system due to a move
+    // constructor or destructor.
+
     writeln!(out, "static_assert(");
     writeln!(
         out,

From e9a7d1ae0b8245edd45d6a5546b3b6b6241aa07b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 20:22:33 +0000
Subject: [PATCH 982/2232] Merge pull request #338 from dtolnay/trivial


Add some thoughts about the triviality static assertions
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b83611a..1a071a2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -418,6 +418,24 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+    // 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:
+    //
+    //     unsafe impl ExternType for MyType {
+    //         type Id = cxx::type_id!("...");
+    //         type Kind = cxx::kind::Trivial;
+    //     }
+    //
+    // Since the user went on the record with their unsafe impl to unsafely
+    // claim they KNOW that the type is trivial, it's fine for that to be on
+    // them if that were wrong.
+    //
+    // There may be a legitimate reason we'll want to remove these assertions
+    // for support of types that the programmer knows are Rust-movable despite
+    // not being recognized as such by the C++ type system due to a move
+    // constructor or destructor.
+
     writeln!(out, "static_assert(");
     writeln!(
         out,

From cc44c7abeadb45fc9afffd04ff274d203b65f226 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 04 2020 20:22:39 +0000
Subject: [PATCH 983/2232] Consistently use ::std in generated code


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1a071a2..328c166 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -322,10 +322,10 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "missing trycatch(...);");
         writeln!(out);
         writeln!(out, "template <typename Try, typename Fail>");
-        writeln!(out, "static typename std::enable_if<");
+        writeln!(out, "static typename ::std::enable_if<");
         writeln!(
             out,
-            "    std::is_same<decltype(trycatch(std::declval<Try>(), std::declval<Fail>())),",
+            "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
         );
         writeln!(out, "                 missing>::value>::type");
         writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
@@ -439,7 +439,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     writeln!(out, "static_assert(");
     writeln!(
         out,
-        "    std::is_trivially_move_constructible<{}>::value,",
+        "    ::std::is_trivially_move_constructible<{}>::value,",
         id,
     );
     writeln!(
@@ -448,7 +448,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
         id,
     );
     writeln!(out, "static_assert(");
-    writeln!(out, "    std::is_trivially_destructible<{}>::value,", id);
+    writeln!(out, "    ::std::is_trivially_destructible<{}>::value,", id);
     writeln!(
         out,
         "    \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",

From 821402b2a6849cf4382d8a0ca3a1af010dfdb0bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 02:50:35 +0000
Subject: [PATCH 984/2232] Move C++ generated code test to cxx's integration test


---

diff --git a/Cargo.toml b/Cargo.toml
index 57b4320..d8b93f1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,7 @@ cxxbridge-flags = { version = "=0.4.7", path = "flags", default-features = false
 
 [dev-dependencies]
 cxx-build = { version = "=0.4.7", path = "gen/build" }
+cxx-gen = { version = "0.4", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 8522715..2fee0e9 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -8,9 +8,6 @@ pub(super) mod include;
 pub(super) mod out;
 mod write;
 
-#[cfg(test)]
-mod tests;
-
 pub(super) use self::error::Error;
 use self::error::{format_err, Result};
 use self::file::File;
diff --git a/gen/src/tests.rs b/gen/src/tests.rs
deleted file mode 100644
index dbf4c62..0000000
--- a/gen/src/tests.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::gen::{generate_from_string, Opt};
-
-const CPP_EXAMPLE: &str = r#"
-    #[cxx::bridge]
-    mod ffi {
-        extern "C" {
-            pub fn do_cpp_thing(foo: &str);
-        }
-    }
-"#;
-
-#[test]
-fn test_cpp() {
-    let opts = Opt {
-        include: Vec::new(),
-        cxx_impl_annotations: None,
-        gen_header: false,
-        gen_implementation: true,
-    };
-    let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
-    let output = std::str::from_utf8(&output.implementation).unwrap();
-    // To avoid continual breakage we won't test every byte.
-    // Let's look for the major features.
-    assert!(output.contains("void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
-}
-
-#[test]
-fn test_annotation() {
-    let opts = Opt {
-        include: Vec::new(),
-        cxx_impl_annotations: Some("ANNOTATION".to_string()),
-        gen_header: false,
-        gen_implementation: true,
-    };
-    let output = generate_from_string(CPP_EXAMPLE, &opts).unwrap();
-    let output = std::str::from_utf8(&output.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
-}
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
new file mode 100644
index 0000000..b5ff106
--- /dev/null
+++ b/tests/cxx_gen.rs
@@ -0,0 +1,31 @@
+use cxx_gen::{generate_header_and_cc, Opt};
+
+const CPP_EXAMPLE: &str = r#"
+    #[cxx::bridge]
+    mod ffi {
+        extern "C" {
+            pub fn do_cpp_thing(foo: &str);
+        }
+    }
+"#;
+
+#[test]
+fn test_cpp() {
+    let opt = Opt::default();
+    let source = CPP_EXAMPLE.parse().unwrap();
+    let output = generate_header_and_cc(source, &opt).unwrap();
+    let output = std::str::from_utf8(&output.implementation).unwrap();
+    // To avoid continual breakage we won't test every byte.
+    // Let's look for the major features.
+    assert!(output.contains("void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
+}
+
+#[test]
+fn test_annotation() {
+    let mut opt = Opt::default();
+    opt.cxx_impl_annotations = Some("ANNOTATION".to_owned());
+    let source = CPP_EXAMPLE.parse().unwrap();
+    let output = generate_header_and_cc(source, &opt).unwrap();
+    let output = std::str::from_utf8(&output.implementation).unwrap();
+    assert!(output.contains("ANNOTATION void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
+}

From 1f7a7e5bca38e204bb31243fca633220784de96d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 02:50:35 +0000
Subject: [PATCH 985/2232] Touch up cxx_gen test


---

diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index b5ff106..139950e 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -1,6 +1,7 @@
 use cxx_gen::{generate_header_and_cc, Opt};
+use std::str;
 
-const CPP_EXAMPLE: &str = r#"
+const BRIDGE0: &str = r#"
     #[cxx::bridge]
     mod ffi {
         extern "C" {
@@ -10,22 +11,22 @@ const CPP_EXAMPLE: &str = r#"
 "#;
 
 #[test]
-fn test_cpp() {
+fn test_extern_c_function() {
     let opt = Opt::default();
-    let source = CPP_EXAMPLE.parse().unwrap();
-    let output = generate_header_and_cc(source, &opt).unwrap();
-    let output = std::str::from_utf8(&output.implementation).unwrap();
+    let source = BRIDGE0.parse().unwrap();
+    let generated = generate_header_and_cc(source, &opt).unwrap();
+    let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
     assert!(output.contains("void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
 }
 
 #[test]
-fn test_annotation() {
+fn test_impl_annotation() {
     let mut opt = Opt::default();
     opt.cxx_impl_annotations = Some("ANNOTATION".to_owned());
-    let source = CPP_EXAMPLE.parse().unwrap();
-    let output = generate_header_and_cc(source, &opt).unwrap();
-    let output = std::str::from_utf8(&output.implementation).unwrap();
+    let source = BRIDGE0.parse().unwrap();
+    let generated = generate_header_and_cc(source, &opt).unwrap();
+    let output = str::from_utf8(&generated.implementation).unwrap();
     assert!(output.contains("ANNOTATION void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From b22ac4e4b9fc55479de2bed3712a9cc1c8e5dba6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 03:01:00 +0000
Subject: [PATCH 986/2232] Reflect new dev dependency on cxx-gen in lockfile


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 00ecb95..041c9cc 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -63,6 +63,7 @@ version = "0.4.7"
 dependencies = [
  "cc",
  "cxx-build",
+ "cxx-gen",
  "cxx-test-suite",
  "cxxbridge-flags",
  "cxxbridge-macro",

From f57f75668915b15cfcc17fa324ed13adeb39a4b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 03:01:00 +0000
Subject: [PATCH 987/2232] Move <type_traits> include to the place its functions are used


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 328c166..1048272 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -138,14 +138,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
                 | Some(I64) => out.include.cstdint = true,
                 Some(Usize) => out.include.cstddef = true,
                 Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) => {}
-                None => {
-                    if types.aliases.contains_key(ident)
-                        && types.required_trivial.contains_key(ident)
-                    {
-                        out.include.type_traits = true;
-                    }
-                }
+                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
             },
             Type::RustBox(_) => out.include.type_traits = true,
             Type::UniquePtr(_) => out.include.memory = true,
@@ -436,6 +429,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     // not being recognized as such by the C++ type system due to a move
     // constructor or destructor.
 
+    out.include.type_traits = true;
     writeln!(out, "static_assert(");
     writeln!(
         out,

From 2c4b35f486ae4c14d60a9fd2239ee1be57460403 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 04:22:34 +0000
Subject: [PATCH 988/2232] Format in a way that rustfmt 1.x and 2.0.0-rc.2 both render the same


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 2a731d7..7408d40 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -190,7 +190,9 @@ unsafe impl UniquePtrTarget for CxxString {
     const __NAME: &'static dyn Display = &"CxxString";
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
-        unsafe { unique_ptr_std_string_null(&mut repr) }
+        unsafe {
+            unique_ptr_std_string_null(&mut repr);
+        }
         repr
     }
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 49dc26b..c611c8b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -73,7 +73,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
         Fields::Unnamed(_) => {
-            return Err(Error::new_spanned(item, "tuple structs are not supported"))
+            return Err(Error::new_spanned(item, "tuple structs are not supported"));
         }
     };
 

From b8543bd30c4b3bb2e528643082f85a296ed85c08 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 20:28:27 +0000
Subject: [PATCH 989/2232] Tweak wording of the triviality requirement


It isn't actually a requirement that the type have no destructor as
brought up by the previous paragraph. Rather, it just needs to be safe
for values of that type to be moved via Rust's memcpy-based move
semantics.

The distinction is relevant e.g. for `struct S { s: String }` which
would have a C++ destructor and nontrivial move constructor but still be
safely memcpy movable.

---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 0432096..b9c5386 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -123,7 +123,7 @@ pub unsafe trait ExternType {
     /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
     ///
     /// If you believe your C++ type reflected by this ExternType impl is indeed
-    /// trivial, you can specify:
+    /// fine to hold by value and move in Rust, you can specify:
     ///
     /// ```
     /// # struct TypeName;

From 942053246687c1e1578ed0bc0736a81c53a71300 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 05 2020 22:47:19 +0000
Subject: [PATCH 990/2232] Merge pull request #339 from dtolnay/triviality


Tweak wording of the triviality requirement
---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index 0432096..b9c5386 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -123,7 +123,7 @@ pub unsafe trait ExternType {
     /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
     ///
     /// If you believe your C++ type reflected by this ExternType impl is indeed
-    /// trivial, you can specify:
+    /// fine to hold by value and move in Rust, you can specify:
     ///
     /// ```
     /// # struct TypeName;

From 8684cc51ad3a9a4d988e462138c902b89c7a029d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 00:09:48 +0000
Subject: [PATCH 991/2232] Emit an ExternType impl for shared structs and enums


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 13134d0..dd5350f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -41,8 +41,8 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
-            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
+            Api::Struct(strct) => expanded.extend(expand_struct(namespace, strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(namespace, enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.ident;
                 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
@@ -125,16 +125,18 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 }
 
-fn expand_struct(strct: &Struct) -> TokenStream {
+fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
     let ident = &strct.ident;
     let doc = &strct.doc;
     let derives = &strct.derives;
+    let type_id = type_id(namespace, 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.
         let vis = Token![pub](field.ident.span());
         quote!(#vis #field)
     });
+
     quote! {
         #doc
         #[derive(#(#derives),*)]
@@ -142,13 +144,19 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         pub struct #ident {
             #(#fields,)*
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+            type Kind = ::cxx::kind::Trivial;
+        }
     }
 }
 
-fn expand_enum(enm: &Enum) -> TokenStream {
+fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
     let repr = enm.repr;
+    let type_id = type_id(namespace, ident);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -156,6 +164,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
+
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
@@ -168,6 +177,11 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         impl #ident {
             #(#variants)*
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+            type Kind = ::cxx::kind::Trivial;
+        }
     }
 }
 

From 4396abfafc69d5fe65fb10a5393a001d700a5043 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 00:20:11 +0000
Subject: [PATCH 992/2232] Merge pull request #341 from dtolnay/shared


Emit an ExternType impl for shared structs and enums
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 13134d0..dd5350f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -41,8 +41,8 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
-            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
+            Api::Struct(strct) => expanded.extend(expand_struct(namespace, strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(namespace, enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.ident;
                 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
@@ -125,16 +125,18 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 }
 
-fn expand_struct(strct: &Struct) -> TokenStream {
+fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
     let ident = &strct.ident;
     let doc = &strct.doc;
     let derives = &strct.derives;
+    let type_id = type_id(namespace, 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.
         let vis = Token![pub](field.ident.span());
         quote!(#vis #field)
     });
+
     quote! {
         #doc
         #[derive(#(#derives),*)]
@@ -142,13 +144,19 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         pub struct #ident {
             #(#fields,)*
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+            type Kind = ::cxx::kind::Trivial;
+        }
     }
 }
 
-fn expand_enum(enm: &Enum) -> TokenStream {
+fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
     let ident = &enm.ident;
     let doc = &enm.doc;
     let repr = enm.repr;
+    let type_id = type_id(namespace, ident);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -156,6 +164,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
+
     quote! {
         #doc
         #[derive(Copy, Clone, PartialEq, Eq)]
@@ -168,6 +177,11 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         impl #ident {
             #(#variants)*
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+            type Kind = ::cxx::kind::Trivial;
+        }
     }
 }
 

From 870bc01e459a9be43159b9923bb39294b722d248 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 00:52:34 +0000
Subject: [PATCH 993/2232] Recognize CARGO_TARGET_DIR env var if set


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 35b6606..7db8a4c 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -1,4 +1,5 @@
 use crate::paths::TargetDir;
+use std::env;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::str;
@@ -8,6 +9,10 @@ pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
 }
 
 fn try_target_dir(out_dir: &Path) -> Option<PathBuf> {
+    if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
+        return Some(PathBuf::from(target_dir));
+    }
+
     let cargo = option_env!("CARGO").unwrap_or("cargo");
     let output = Command::new(cargo)
         .current_dir(out_dir)

From 69080574d52fc85c5ec81f84e808ba62a27801a6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 00:54:45 +0000
Subject: [PATCH 994/2232] Skip trying to call `cargo metadata` if CARGO_TARGET_DIR is relative


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
index 7db8a4c..18b6b6f 100644
--- a/gen/build/src/cargo.rs
+++ b/gen/build/src/cargo.rs
@@ -10,7 +10,12 @@ pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
 
 fn try_target_dir(out_dir: &Path) -> Option<PathBuf> {
     if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
-        return Some(PathBuf::from(target_dir));
+        let target_dir = PathBuf::from(target_dir);
+        if target_dir.is_absolute() {
+            return Some(target_dir);
+        } else {
+            return None;
+        };
     }
 
     let cargo = option_env!("CARGO").unwrap_or("cargo");

From 59b103fe5cd409cb37457571ae701bab07744e3d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 01:22:15 +0000
Subject: [PATCH 995/2232] Remove extraneous create_dir_all


The directory creation is already handled by out::write.

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ef284c4..838908b 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -62,7 +62,7 @@ mod syntax;
 
 use crate::error::Result;
 use crate::gen::error::report;
-use crate::gen::{fs, Opt};
+use crate::gen::Opt;
 use crate::paths::{PathExt, TargetDir};
 use cc::Build;
 use std::io::{self, Write};
@@ -148,9 +148,7 @@ fn write_header(prj: &Project) {
     let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
     let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
     if let TargetDir::Path(target_dir) = &prj.target_dir {
-        let ref header_dir = target_dir.join("cxxbridge").join("rust");
-        let _ = fs::create_dir_all(header_dir);
-        let ref cxx_h = header_dir.join("cxx.h");
+        let ref cxx_h = target_dir.join("cxxbridge").join("rust").join("cxx.h");
         let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
     }
 }

From ee907be404300e5101e9a1b6bf598bd44a5cd400 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:14:53 +0000
Subject: [PATCH 996/2232] Use Cargo's build script metadata feature to make reliable include dirs


---

diff --git a/BUCK b/BUCK
index 695c079..0505bd2 100644
--- a/BUCK
+++ b/BUCK
@@ -48,6 +48,7 @@ rust_library(
 rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**"]),
+    env = {"OUT_DIR": ""},
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:cc",
diff --git a/BUILD b/BUILD
index 4700e06..e551d18 100644
--- a/BUILD
+++ b/BUILD
@@ -54,6 +54,7 @@ rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**/*.rs"]),
     data = ["gen/build/src/gen/include/cxx.h"],
+    rustc_env = {"OUT_DIR": ""},
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:cc",
diff --git a/build.rs b/build.rs
index 502a60b..688b5b7 100644
--- a/build.rs
+++ b/build.rs
@@ -1,3 +1,6 @@
+use std::env;
+use std::path::Path;
+
 fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
@@ -8,4 +11,8 @@ fn main() {
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
+    if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
+        let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
+        println!("cargo:HEADER={}", cxx_h.to_string_lossy());
+    }
 }
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 0ed4d74..2fbd41d 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,19 +1,22 @@
 use crate::gen::fs;
 use std::error::Error as StdError;
+use std::ffi::OsString;
 use std::fmt::{self, Display};
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub(super) enum Error {
-    MissingOutDir,
+    NoEnv(OsString),
     Fs(fs::Error),
 }
 
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
+            Error::NoEnv(var) => {
+                write!(f, "missing {} environment variable", var.to_string_lossy())
+            }
             Error::Fs(err) => err.fmt(f),
         }
     }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 838908b..0b4ae98 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -60,11 +60,13 @@ mod out;
 mod paths;
 mod syntax;
 
-use crate::error::Result;
+use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
 use crate::paths::{PathExt, TargetDir};
 use cc::Build;
+use std::env;
+use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
@@ -100,12 +102,29 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 struct Project {
+    package_name: OsString,
+    manifest_dir: PathBuf,
+    // Output directory as received from Cargo.
     out_dir: PathBuf,
-    target_dir: TargetDir,
+    // Directory into which to symlink all generated code.
+    //
+    // This is *not* used for an #include path, only as a debugging convenience.
+    // Normally available at target/cxxbridge/ if we are able to know where the
+    // target dir is, otherwise under a common scratch dir.
+    //
+    // The reason this isn't the #include dir is that we do not want builds to
+    // have access to headers from arbitrary other parts of the dependency
+    // graph. Using a global directory for all builds would be both a race
+    // condition depending on what order Cargo randomly executes the build
+    // scripts, as well as semantically undesirable for builds not to have to
+    // declare their real dependencies.
+    shared_dir: PathBuf,
 }
 
 impl Project {
     fn init() -> Result<Self> {
+        let package_name = env_os("CARGO_PKG_NAME")?;
+        let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
         let target_dir = match cargo::target_dir(&out_dir) {
@@ -114,60 +133,89 @@ impl Project {
             TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
         };
 
+        let shared_dir = match target_dir {
+            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
+            // Use cxx-build's OUT_DIR.
+            TargetDir::Unknown => PathBuf::from(env!("OUT_DIR")),
+        };
+
         Ok(Project {
+            package_name,
+            manifest_dir,
             out_dir,
-            target_dir,
+            shared_dir,
         })
     }
 }
 
+// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
+// subdirectory to avoid stomping on other things that the caller's build script
+// might be doing inside OUT_DIR.
+//
+//     $OUT_DIR/
+//        cxxbridge/
+//           crate/
+//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
+//           include/
+//              rust/
+//                 cxx.h
+//              $CARGO_PKG_NAME/
+//                 .../
+//                    lib.rs.h
+//           sources/
+//              $CARGO_PKG_NAME/
+//                 .../
+//                    lib.rs.cc
+//
+// The crate/ and include/ directories are placed on the #include path.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
-    let include_dir = paths::include_dir(prj);
+
+    let ref crate_dir = make_crate_dir(prj);
+    let ref include_dir = make_include_dir(prj)?;
 
     let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    build.include(&include_dir);
-    write_header(prj);
-    let crate_dir = symlink_crate(prj, &mut build);
+    if let Some(crate_dir) = crate_dir {
+        build.include(crate_dir);
+    }
+    build.include(include_dir);
 
     for path in rust_source_files {
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
     eprintln!("\nCXX include path:");
-    eprintln!("  {}", include_dir.display());
     if let Some(crate_dir) = crate_dir {
         eprintln!("  {}", crate_dir.display());
     }
+    eprintln!("  {}", include_dir.display());
     Ok(build)
 }
 
-fn write_header(prj: &Project) {
-    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
-    let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
-    if let TargetDir::Path(target_dir) = &prj.target_dir {
-        let ref cxx_h = target_dir.join("cxxbridge").join("rust").join("cxx.h");
-        let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
+fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
+    let link = crate_dir.join(&prj.package_name);
+    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
+        Some(crate_dir)
+    } else {
+        None
     }
 }
 
-fn symlink_crate(prj: &Project, build: &mut Build) -> Option<PathBuf> {
-    let manifest_dir = match paths::manifest_dir() {
-        Some(manifest_dir) => manifest_dir,
-        None => return None,
-    };
-    let package_name = match paths::package_name() {
-        Some(package_name) => package_name,
-        None => return None,
-    };
-
-    let mut link = paths::include_dir(prj);
-    link.push("CRATE");
-    let _ = out::symlink_dir(manifest_dir, link.join(package_name));
-    build.include(&link);
-    Some(link)
+fn make_include_dir(prj: &Project) -> Result<PathBuf> {
+    let include_dir = prj.out_dir.join("cxxbridge").join("include");
+    let cxx_h = include_dir.join("rust").join("cxx.h");
+    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
+    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE04_HEADER") {
+        out::symlink_file(original, cxx_h)?;
+        out::symlink_file(original, shared_cxx_h)?;
+    } else {
+        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
+        out::symlink_file(shared_cxx_h, cxx_h)?;
+    }
+    Ok(include_dir)
 }
 
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
@@ -175,21 +223,30 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let generated = gen::generate_from_path(rust_source_file, &opt);
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
+    let cxxbridge = prj.out_dir.join("cxxbridge");
+    let include_dir = cxxbridge.join("include").join(&prj.package_name);
+    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);
+
     let ref rel_path_h = rel_path.with_appended_extension(".h");
-    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
+    let ref header_path = include_dir.join(rel_path_h);
     out::write(header_path, &generated.header)?;
 
-    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
+    let ref link_path = include_dir.join(rel_path);
     let _ = out::symlink_file(header_path, link_path);
-    if let TargetDir::Path(target_dir) = &prj.target_dir {
-        let ref link_path = paths::namespaced(target_dir, rel_path);
-        let _ = out::symlink_file(header_path, link_path);
-        let _ = out::symlink_file(header_path, link_path.with_appended_extension(".h"));
-    }
 
     let ref rel_path_cc = rel_path.with_appended_extension(".cc");
-    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
+    let ref implementation_path = sources_dir.join(rel_path_cc);
     out::write(implementation_path, &generated.implementation)?;
     build.file(implementation_path);
+
+    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
+    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
+    let _ = out::symlink_file(header_path, shared_h);
+    let _ = out::symlink_file(implementation_path, shared_cc);
     Ok(())
 }
+
+fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
+    let key = key.as_ref();
+    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 1007730..56c0018 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,8 +1,6 @@
-use crate::error::{Error, Result};
+use crate::error::Result;
 use crate::gen::fs;
-use crate::Project;
-use std::env;
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsStr;
 use std::path::{Component, Path, PathBuf};
 
 pub(crate) enum TargetDir {
@@ -10,10 +8,12 @@ pub(crate) enum TargetDir {
     Unknown,
 }
 
+pub(crate) fn manifest_dir() -> Result<PathBuf> {
+    crate::env_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
+}
+
 pub(crate) fn out_dir() -> Result<PathBuf> {
-    env::var_os("OUT_DIR")
-        .map(PathBuf::from)
-        .ok_or(Error::MissingOutDir)
+    crate::env_os("OUT_DIR").map(PathBuf::from)
 }
 
 // Given a path provided by the user, determines where generated files related
@@ -32,14 +32,6 @@ pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
     rel_path
 }
 
-pub(crate) fn namespaced(base: &Path, rel_path: &Path) -> PathBuf {
-    let mut path = base.to_owned();
-    path.push("cxxbridge");
-    path.extend(package_name());
-    path.push(rel_path);
-    path
-}
-
 pub(crate) trait PathExt {
     fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
 }
@@ -52,21 +44,6 @@ impl PathExt for Path {
     }
 }
 
-pub(crate) fn include_dir(prj: &Project) -> PathBuf {
-    match &prj.target_dir {
-        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
-        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
-    }
-}
-
-pub(crate) fn manifest_dir() -> Option<PathBuf> {
-    env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
-}
-
-pub(crate) fn package_name() -> Option<OsString> {
-    env::var_os("CARGO_PKG_NAME")
-}
-
 pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
     // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
     // handle in includes.

From 45ded8884695c4ece59bbf27df0e12ef6cd4dd05 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:14:53 +0000
Subject: [PATCH 997/2232] Swap include line order to support #include of a .rs file


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 0b4ae98..538ef12 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -177,10 +177,14 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+    build.include(include_dir);
     if let Some(crate_dir) = crate_dir {
+        // Placed after the generated code directory (include_dir) on the
+        // include line so that `#include "path/to/file.rs"` from C++
+        // "magically" works and refers to the API generated from that Rust
+        // source file.
         build.include(crate_dir);
     }
-    build.include(include_dir);
 
     for path in rust_source_files {
         generate_bridge(prj, &mut build, path.as_ref())?;

From d7c7e675551f051933d36cf7e30dbd808b27195f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:14:53 +0000
Subject: [PATCH 998/2232] Place direct dependencies on the include path


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 538ef12..3782543 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -65,6 +65,7 @@ use crate::gen::error::report;
 use crate::gen::Opt;
 use crate::paths::{PathExt, TargetDir};
 use cc::Build;
+use std::collections::BTreeMap;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -167,7 +168,9 @@ impl Project {
 //                 .../
 //                    lib.rs.cc
 //
-// The crate/ and include/ directories are placed on the #include path.
+// The crate/ and include/ directories are placed on the #include path for the
+// current build as well as for downstream builds that have a direct dependency
+// on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
 
@@ -177,31 +180,69 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+
+    for path in rust_source_files {
+        generate_bridge(prj, &mut build, path.as_ref())?;
+    }
+
+    eprintln!("\nCXX include path:");
     build.include(include_dir);
+    eprintln!("  {}", include_dir.display());
     if let Some(crate_dir) = crate_dir {
         // Placed after the generated code directory (include_dir) on the
         // include line so that `#include "path/to/file.rs"` from C++
         // "magically" works and refers to the API generated from that Rust
         // source file.
         build.include(crate_dir);
+        eprintln!("  {}", crate_dir.display());
     }
-
-    for path in rust_source_files {
-        generate_bridge(prj, &mut build, path.as_ref())?;
+    for dep in env_include_dirs() {
+        build.include(&dep);
+        eprintln!("  {}", dep.display());
     }
+    Ok(build)
+}
 
-    eprintln!("\nCXX include path:");
-    if let Some(crate_dir) = crate_dir {
-        eprintln!("  {}", crate_dir.display());
+fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
+    let mut env_include_dirs = BTreeMap::new();
+    for (k, v) in env::vars_os() {
+        let mut k = k.to_string_lossy().into_owned();
+        // Only variables set from a build script of direct dependencies are
+        // observable. That's exactly what we want! Your crate needs to declare
+        // a direct dependency on the other crate in order to be able to
+        // #include its headers.
+        //
+        // Also, they're only observable if the dependency's manifest contains a
+        // `links` key. This is important because Cargo imposes no ordering on
+        // the execution of build scripts without a `links` key. When exposing a
+        // generated header for the current crate to #include, we need to be
+        // sure the dependency's build script has already executed and emitted
+        // that generated header.
+        //
+        // References:
+        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
+        if k.starts_with("DEP_") {
+            if k.ends_with("_CXXBRIDGE_INCLUDE") {
+                // Tweak to ensure sorted before the other one, for the same
+                // reason as the comment on ordering of include_dir vs crate_dir
+                // above.
+                k.replace_range(k.len() - "INCLUDE".len().., "0");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_CRATE") {
+                k.replace_range(k.len() - "CRATE".len().., "1");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            }
+        }
     }
-    eprintln!("  {}", include_dir.display());
-    Ok(build)
+    env_include_dirs.into_iter().map(|entry| entry.1)
 }
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
     let link = crate_dir.join(&prj.package_name);
     if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
+        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         Some(crate_dir)
     } else {
         None
@@ -219,6 +260,7 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
         out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
         out::symlink_file(shared_cxx_h, cxx_h)?;
     }
+    println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
     Ok(include_dir)
 }
 

From 1f7edf8d2723bfa21cd061add727fde94b161fe4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:38:43 +0000
Subject: [PATCH 999/2232] Merge pull request #346 from dtolnay/build


Use Cargo's build script metadata feature to make reliable include dirs
---

diff --git a/BUCK b/BUCK
index 695c079..0505bd2 100644
--- a/BUCK
+++ b/BUCK
@@ -48,6 +48,7 @@ rust_library(
 rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**"]),
+    env = {"OUT_DIR": ""},
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:cc",
diff --git a/BUILD b/BUILD
index 4700e06..e551d18 100644
--- a/BUILD
+++ b/BUILD
@@ -54,6 +54,7 @@ rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**/*.rs"]),
     data = ["gen/build/src/gen/include/cxx.h"],
+    rustc_env = {"OUT_DIR": ""},
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:cc",
diff --git a/build.rs b/build.rs
index 502a60b..688b5b7 100644
--- a/build.rs
+++ b/build.rs
@@ -1,3 +1,6 @@
+use std::env;
+use std::path::Path;
+
 fn main() {
     cc::Build::new()
         .file("src/cxx.cc")
@@ -8,4 +11,8 @@ fn main() {
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
+    if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
+        let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
+        println!("cargo:HEADER={}", cxx_h.to_string_lossy());
+    }
 }
diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 0ed4d74..2fbd41d 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,19 +1,22 @@
 use crate::gen::fs;
 use std::error::Error as StdError;
+use std::ffi::OsString;
 use std::fmt::{self, Display};
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
 #[derive(Debug)]
 pub(super) enum Error {
-    MissingOutDir,
+    NoEnv(OsString),
     Fs(fs::Error),
 }
 
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Error::MissingOutDir => write!(f, "missing OUT_DIR environment variable"),
+            Error::NoEnv(var) => {
+                write!(f, "missing {} environment variable", var.to_string_lossy())
+            }
             Error::Fs(err) => err.fmt(f),
         }
     }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 838908b..3782543 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -60,11 +60,14 @@ mod out;
 mod paths;
 mod syntax;
 
-use crate::error::Result;
+use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
 use crate::paths::{PathExt, TargetDir};
 use cc::Build;
+use std::collections::BTreeMap;
+use std::env;
+use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
@@ -100,12 +103,29 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 struct Project {
+    package_name: OsString,
+    manifest_dir: PathBuf,
+    // Output directory as received from Cargo.
     out_dir: PathBuf,
-    target_dir: TargetDir,
+    // Directory into which to symlink all generated code.
+    //
+    // This is *not* used for an #include path, only as a debugging convenience.
+    // Normally available at target/cxxbridge/ if we are able to know where the
+    // target dir is, otherwise under a common scratch dir.
+    //
+    // The reason this isn't the #include dir is that we do not want builds to
+    // have access to headers from arbitrary other parts of the dependency
+    // graph. Using a global directory for all builds would be both a race
+    // condition depending on what order Cargo randomly executes the build
+    // scripts, as well as semantically undesirable for builds not to have to
+    // declare their real dependencies.
+    shared_dir: PathBuf,
 }
 
 impl Project {
     fn init() -> Result<Self> {
+        let package_name = env_os("CARGO_PKG_NAME")?;
+        let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
         let target_dir = match cargo::target_dir(&out_dir) {
@@ -114,60 +134,134 @@ impl Project {
             TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
         };
 
+        let shared_dir = match target_dir {
+            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
+            // Use cxx-build's OUT_DIR.
+            TargetDir::Unknown => PathBuf::from(env!("OUT_DIR")),
+        };
+
         Ok(Project {
+            package_name,
+            manifest_dir,
             out_dir,
-            target_dir,
+            shared_dir,
         })
     }
 }
 
+// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
+// subdirectory to avoid stomping on other things that the caller's build script
+// might be doing inside OUT_DIR.
+//
+//     $OUT_DIR/
+//        cxxbridge/
+//           crate/
+//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
+//           include/
+//              rust/
+//                 cxx.h
+//              $CARGO_PKG_NAME/
+//                 .../
+//                    lib.rs.h
+//           sources/
+//              $CARGO_PKG_NAME/
+//                 .../
+//                    lib.rs.cc
+//
+// The crate/ and include/ directories are placed on the #include path for the
+// current build as well as for downstream builds that have a direct dependency
+// on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
-    let include_dir = paths::include_dir(prj);
+
+    let ref crate_dir = make_crate_dir(prj);
+    let ref include_dir = make_include_dir(prj)?;
 
     let mut build = Build::new();
     build.cpp(true);
     build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-    build.include(&include_dir);
-    write_header(prj);
-    let crate_dir = symlink_crate(prj, &mut build);
 
     for path in rust_source_files {
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
     eprintln!("\nCXX include path:");
+    build.include(include_dir);
     eprintln!("  {}", include_dir.display());
     if let Some(crate_dir) = crate_dir {
+        // Placed after the generated code directory (include_dir) on the
+        // include line so that `#include "path/to/file.rs"` from C++
+        // "magically" works and refers to the API generated from that Rust
+        // source file.
+        build.include(crate_dir);
         eprintln!("  {}", crate_dir.display());
     }
+    for dep in env_include_dirs() {
+        build.include(&dep);
+        eprintln!("  {}", dep.display());
+    }
     Ok(build)
 }
 
-fn write_header(prj: &Project) {
-    let ref cxx_h = prj.out_dir.join("cxxbridge").join("rust").join("cxx.h");
-    let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
-    if let TargetDir::Path(target_dir) = &prj.target_dir {
-        let ref cxx_h = target_dir.join("cxxbridge").join("rust").join("cxx.h");
-        let _ = out::write(cxx_h, gen::include::HEADER.as_bytes());
+fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
+    let mut env_include_dirs = BTreeMap::new();
+    for (k, v) in env::vars_os() {
+        let mut k = k.to_string_lossy().into_owned();
+        // Only variables set from a build script of direct dependencies are
+        // observable. That's exactly what we want! Your crate needs to declare
+        // a direct dependency on the other crate in order to be able to
+        // #include its headers.
+        //
+        // Also, they're only observable if the dependency's manifest contains a
+        // `links` key. This is important because Cargo imposes no ordering on
+        // the execution of build scripts without a `links` key. When exposing a
+        // generated header for the current crate to #include, we need to be
+        // sure the dependency's build script has already executed and emitted
+        // that generated header.
+        //
+        // References:
+        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
+        if k.starts_with("DEP_") {
+            if k.ends_with("_CXXBRIDGE_INCLUDE") {
+                // Tweak to ensure sorted before the other one, for the same
+                // reason as the comment on ordering of include_dir vs crate_dir
+                // above.
+                k.replace_range(k.len() - "INCLUDE".len().., "0");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_CRATE") {
+                k.replace_range(k.len() - "CRATE".len().., "1");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            }
+        }
     }
+    env_include_dirs.into_iter().map(|entry| entry.1)
 }
 
-fn symlink_crate(prj: &Project, build: &mut Build) -> Option<PathBuf> {
-    let manifest_dir = match paths::manifest_dir() {
-        Some(manifest_dir) => manifest_dir,
-        None => return None,
-    };
-    let package_name = match paths::package_name() {
-        Some(package_name) => package_name,
-        None => return None,
-    };
-
-    let mut link = paths::include_dir(prj);
-    link.push("CRATE");
-    let _ = out::symlink_dir(manifest_dir, link.join(package_name));
-    build.include(&link);
-    Some(link)
+fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
+    let link = crate_dir.join(&prj.package_name);
+    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
+        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
+        Some(crate_dir)
+    } else {
+        None
+    }
+}
+
+fn make_include_dir(prj: &Project) -> Result<PathBuf> {
+    let include_dir = prj.out_dir.join("cxxbridge").join("include");
+    let cxx_h = include_dir.join("rust").join("cxx.h");
+    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
+    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE04_HEADER") {
+        out::symlink_file(original, cxx_h)?;
+        out::symlink_file(original, shared_cxx_h)?;
+    } else {
+        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
+        out::symlink_file(shared_cxx_h, cxx_h)?;
+    }
+    println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
+    Ok(include_dir)
 }
 
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
@@ -175,21 +269,30 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let generated = gen::generate_from_path(rust_source_file, &opt);
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
+    let cxxbridge = prj.out_dir.join("cxxbridge");
+    let include_dir = cxxbridge.join("include").join(&prj.package_name);
+    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);
+
     let ref rel_path_h = rel_path.with_appended_extension(".h");
-    let ref header_path = paths::namespaced(&prj.out_dir, rel_path_h);
+    let ref header_path = include_dir.join(rel_path_h);
     out::write(header_path, &generated.header)?;
 
-    let ref link_path = paths::namespaced(&prj.out_dir, rel_path);
+    let ref link_path = include_dir.join(rel_path);
     let _ = out::symlink_file(header_path, link_path);
-    if let TargetDir::Path(target_dir) = &prj.target_dir {
-        let ref link_path = paths::namespaced(target_dir, rel_path);
-        let _ = out::symlink_file(header_path, link_path);
-        let _ = out::symlink_file(header_path, link_path.with_appended_extension(".h"));
-    }
 
     let ref rel_path_cc = rel_path.with_appended_extension(".cc");
-    let ref implementation_path = paths::namespaced(&prj.out_dir, rel_path_cc);
+    let ref implementation_path = sources_dir.join(rel_path_cc);
     out::write(implementation_path, &generated.implementation)?;
     build.file(implementation_path);
+
+    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
+    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
+    let _ = out::symlink_file(header_path, shared_h);
+    let _ = out::symlink_file(implementation_path, shared_cc);
     Ok(())
 }
+
+fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
+    let key = key.as_ref();
+    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 1007730..56c0018 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -1,8 +1,6 @@
-use crate::error::{Error, Result};
+use crate::error::Result;
 use crate::gen::fs;
-use crate::Project;
-use std::env;
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsStr;
 use std::path::{Component, Path, PathBuf};
 
 pub(crate) enum TargetDir {
@@ -10,10 +8,12 @@ pub(crate) enum TargetDir {
     Unknown,
 }
 
+pub(crate) fn manifest_dir() -> Result<PathBuf> {
+    crate::env_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
+}
+
 pub(crate) fn out_dir() -> Result<PathBuf> {
-    env::var_os("OUT_DIR")
-        .map(PathBuf::from)
-        .ok_or(Error::MissingOutDir)
+    crate::env_os("OUT_DIR").map(PathBuf::from)
 }
 
 // Given a path provided by the user, determines where generated files related
@@ -32,14 +32,6 @@ pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
     rel_path
 }
 
-pub(crate) fn namespaced(base: &Path, rel_path: &Path) -> PathBuf {
-    let mut path = base.to_owned();
-    path.push("cxxbridge");
-    path.extend(package_name());
-    path.push(rel_path);
-    path
-}
-
 pub(crate) trait PathExt {
     fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
 }
@@ -52,21 +44,6 @@ impl PathExt for Path {
     }
 }
 
-pub(crate) fn include_dir(prj: &Project) -> PathBuf {
-    match &prj.target_dir {
-        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
-        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
-    }
-}
-
-pub(crate) fn manifest_dir() -> Option<PathBuf> {
-    env::var_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
-}
-
-pub(crate) fn package_name() -> Option<OsString> {
-    env::var_os("CARGO_PKG_NAME")
-}
-
 pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
     // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
     // handle in includes.

From de0c14d532ed1c6657b7d583457b93327cbc2682 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:41:44 +0000
Subject: [PATCH 1000/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index f07de50..e6a5611 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.60/src/**"]),
+    srcs = glob(["vendor/cc-1.0.61/src/**"]),
     visibility = ["PUBLIC"],
 )
 
diff --git a/third-party/BUILD b/third-party/BUILD
index 0d602a8..f874d07 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -12,7 +12,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.60/src/**"]),
+    srcs = glob(["vendor/cc-1.0.61/src/**"]),
     visibility = ["//visibility:public"],
 )
 
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 041c9cc..7e6a175 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.60"
+version = "1.0.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
+checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
 
 [[package]]
 name = "clap"
@@ -151,9 +151,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.16"
+version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
+checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
 dependencies = [
  "libc",
 ]
@@ -172,15 +172,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.78"
+version = "0.2.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98"
+checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
 
 [[package]]
 name = "link-cplusplus"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372d61b8ffdc79aa85d5f679e16c9e34da2357796186e877001f21998ece1f99"
+checksum = "f96aa785c87218ec773df6c510af203872b34e2df2cf47d6e908e5f36231e354"
 dependencies = [
  "cc",
 ]

From 4563fb1c746d4526d210e95b66d548632bbe72e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:43:19 +0000
Subject: [PATCH 1001/2232] Add lazy_static dep to cxx-build


---

diff --git a/BUCK b/BUCK
index 0505bd2..22db155 100644
--- a/BUCK
+++ b/BUCK
@@ -53,6 +53,7 @@ rust_library(
     deps = [
         "//third-party:cc",
         "//third-party:codespan-reporting",
+        "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
diff --git a/BUILD b/BUILD
index e551d18..782374b 100644
--- a/BUILD
+++ b/BUILD
@@ -59,6 +59,7 @@ rust_library(
     deps = [
         "//third-party:cc",
         "//third-party:codespan-reporting",
+        "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 675261e..3671781 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,6 +13,7 @@ categories = ["development-tools::ffi"]
 [dependencies]
 cc = "1.0.49"
 codespan-reporting = "0.9"
+lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/third-party/BUCK b/third-party/BUCK
index e6a5611..3b0ec99 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -36,6 +36,7 @@ rust_library(
 rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+    visibility = ["PUBLIC"],
 )
 
 rust_library(
diff --git a/third-party/BUILD b/third-party/BUILD
index f874d07..3477326 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -41,6 +41,7 @@ rust_library(
 rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+    visibility = ["//visibility:public"],
 )
 
 rust_library(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 7e6a175..d975d6e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -79,6 +79,7 @@ dependencies = [
  "cc",
  "codespan-reporting",
  "cxx-gen",
+ "lazy_static",
  "proc-macro2",
  "quote",
  "syn",

From e5098cb4a702140427e18f65b3094ca7f9d24e18 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:57:54 +0000
Subject: [PATCH 1002/2232] Expose control of import prefix to Cargo builds


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
new file mode 100644
index 0000000..ecc9bfb
--- /dev/null
+++ b/gen/build/src/cfg.rs
@@ -0,0 +1,131 @@
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+
+pub struct Cfg<'a> {
+    pub include_prefix: &'a str,
+    marker: PhantomData<*const ()>, // !Send + !Sync
+}
+
+#[cfg(doc)]
+pub static mut CFG: Cfg = Cfg {
+    include_prefix: "",
+    marker: PhantomData,
+};
+
+impl<'a> Debug for Cfg<'a> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter
+            .debug_struct("Cfg")
+            .field("include_prefix", &self.include_prefix)
+            .finish()
+    }
+}
+
+#[cfg(not(doc))]
+pub use self::r#impl::Cfg::CFG;
+
+#[cfg(not(doc))]
+mod r#impl {
+    use lazy_static::lazy_static;
+    use std::cell::RefCell;
+    use std::collections::HashMap;
+    use std::fmt::{self, Debug};
+    use std::marker::PhantomData;
+    use std::ops::{Deref, DerefMut};
+    use std::sync::{PoisonError, RwLock};
+
+    lazy_static! {
+        static ref PACKAGE_NAME: Box<str> = {
+            crate::env_os("CARGO_PKG_NAME")
+                .map(|pkg| pkg.to_string_lossy().into_owned().into_boxed_str())
+                .unwrap_or_default()
+        };
+        static ref INCLUDE_PREFIX: RwLock<Vec<&'static str>> = RwLock::new(vec![&PACKAGE_NAME]);
+    }
+
+    thread_local! {
+        static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
+    }
+
+    #[derive(Eq, PartialEq, Hash)]
+    struct Handle(*const Cfg<'static>);
+
+    impl<'a> Cfg<'a> {
+        fn current() -> super::Cfg<'a> {
+            let include_prefix = *INCLUDE_PREFIX
+                .read()
+                .unwrap_or_else(PoisonError::into_inner)
+                .last()
+                .unwrap();
+            super::Cfg {
+                include_prefix,
+                marker: PhantomData,
+            }
+        }
+
+        const fn handle(self: &Cfg<'a>) -> Handle {
+            Handle(<*const Cfg>::cast(self))
+        }
+    }
+
+    // Since super::Cfg is !Send and !Sync, all Cfg are thread local and will
+    // drop on the same thread where they were created.
+    pub enum Cfg<'a> {
+        Mut(super::Cfg<'a>),
+        CFG,
+    }
+
+    impl<'a> Debug for Cfg<'a> {
+        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+            if let Cfg::Mut(cfg) = self {
+                Debug::fmt(cfg, formatter)
+            } else {
+                Debug::fmt(&Cfg::current(), formatter)
+            }
+        }
+    }
+
+    impl<'a> Deref for Cfg<'a> {
+        type Target = super::Cfg<'a>;
+
+        fn deref(&self) -> &Self::Target {
+            if let Cfg::Mut(cfg) = self {
+                cfg
+            } else {
+                let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg {
+                    &mut **derefs
+                        .borrow_mut()
+                        .entry(self.handle())
+                        .or_insert_with(|| Box::new(Cfg::current()))
+                });
+                unsafe { &mut *cfg }
+            }
+        }
+    }
+
+    impl<'a> DerefMut for Cfg<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            if let Cfg::CFG = self {
+                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
+                *self = Cfg::Mut(Cfg::current());
+            }
+            match self {
+                Cfg::Mut(cfg) => cfg,
+                Cfg::CFG => unreachable!(),
+            }
+        }
+    }
+
+    impl<'a> Drop for Cfg<'a> {
+        fn drop(&mut self) {
+            if let Cfg::Mut(cfg) = self {
+                INCLUDE_PREFIX
+                    .write()
+                    .unwrap_or_else(PoisonError::into_inner)
+                    .push(Box::leak(Box::from(cfg.include_prefix)));
+            } else {
+                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
+            }
+        }
+    }
+}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 3782543..1e466e5 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -54,6 +54,7 @@
 )]
 
 mod cargo;
+mod cfg;
 mod error;
 mod gen;
 mod out;
@@ -73,6 +74,8 @@ use std::iter;
 use std::path::{Path, PathBuf};
 use std::process;
 
+pub use crate::cfg::{Cfg, CFG};
+
 /// This returns a [`cc::Build`] on which you should continue to set up any
 /// additional source files or compiler flags, and lastly call its [`compile`]
 /// method to execute the C++ build.
@@ -103,7 +106,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 struct Project {
-    package_name: OsString,
+    include_prefix: PathBuf,
     manifest_dir: PathBuf,
     // Output directory as received from Cargo.
     out_dir: PathBuf,
@@ -124,7 +127,11 @@ struct Project {
 
 impl Project {
     fn init() -> Result<Self> {
-        let package_name = env_os("CARGO_PKG_NAME")?;
+        let include_prefix = Path::new(CFG.include_prefix);
+        assert!(include_prefix.is_relative());
+        assert!(!include_prefix.as_os_str().is_empty());
+        let include_prefix = include_prefix.components().collect();
+
         let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
@@ -141,7 +148,7 @@ impl Project {
         };
 
         Ok(Project {
-            package_name,
+            include_prefix,
             manifest_dir,
             out_dir,
             shared_dir,
@@ -240,7 +247,7 @@ fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
-    let link = crate_dir.join(&prj.package_name);
+    let link = crate_dir.join(&prj.include_prefix);
     if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
         println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         Some(crate_dir)
@@ -270,8 +277,8 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
     let cxxbridge = prj.out_dir.join("cxxbridge");
-    let include_dir = cxxbridge.join("include").join(&prj.package_name);
-    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);
+    let include_dir = cxxbridge.join("include").join(&prj.include_prefix);
+    let sources_dir = cxxbridge.join("sources").join(&prj.include_prefix);
 
     let ref rel_path_h = rel_path.with_appended_extension(".h");
     let ref header_path = include_dir.join(rel_path_h);
@@ -285,8 +292,8 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     out::write(implementation_path, &generated.implementation)?;
     build.file(implementation_path);
 
-    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
-    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
+    let shared_h = prj.shared_dir.join(&prj.include_prefix).join(rel_path_h);
+    let shared_cc = prj.shared_dir.join(&prj.include_prefix).join(rel_path_cc);
     let _ = out::symlink_file(header_path, shared_h);
     let _ = out::symlink_file(implementation_path, shared_cc);
     Ok(())

From d41eef59c96993ff17f929751d3fff5f901ad7b2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 08 2020 23:57:55 +0000
Subject: [PATCH 1003/2232] Change test suite's include_prefix to match workspace path


---

diff --git a/tests/BUCK b/tests/BUCK
index 47fc557..f066542 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -26,10 +26,9 @@ cxx_library(
         ":bridge/source",
         ":module/source",
     ],
-    header_namespace = "cxx-test-suite",
     headers = {
-        "lib.rs.h": ":bridge/header",
-        "tests.h": "ffi/tests.h",
+        "ffi/lib.rs.h": ":bridge/header",
+        "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
diff --git a/tests/BUILD b/tests/BUILD
index 68e7be3..1345a7a 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -29,8 +29,6 @@ cc_library(
         ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [
         ":bridge/include",
         "//:core",
@@ -40,15 +38,11 @@ cc_library(
 rust_cxx_bridge(
     name = "bridge",
     src = "ffi/lib.rs",
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [":impl"],
 )
 
 rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [":impl"],
 )
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 8042129..e583944 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -1,8 +1,11 @@
+use cxx_build::CFG;
+
 fn main() {
     if cfg!(trybuild) {
         return;
     }
 
+    CFG.include_prefix = "tests/ffi";
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9ace1f2..cc07752 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -23,7 +23,7 @@ pub mod ffi {
     }
 
     extern "C" {
-        include!("cxx-test-suite/tests.h");
+        include!("tests/ffi/tests.h");
 
         type C;
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 8862dc1..77bae06 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -4,7 +4,7 @@
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     extern "C" {
-        include!("cxx-test-suite/tests.h");
+        include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 1f88d8b..9cb6ed0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
-#include "cxx-test-suite/tests.h"
-#include "cxx-test-suite/lib.rs.h"
+#include "tests/ffi/tests.h"
+#include "tests/ffi/lib.rs.h"
 #include <cstring>
 #include <iterator>
 #include <numeric>
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index d4111c6..534f6b5 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,12 +1,7 @@
 load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
-def rust_cxx_bridge(
-        name,
-        src,
-        include_prefix = None,
-        strip_include_prefix = None,
-        deps = []):
+def rust_cxx_bridge(name, src, deps = []):
     native.alias(
         name = "%s/header" % name,
         actual = src + ".h",
@@ -43,6 +38,4 @@ def rust_cxx_bridge(
     cc_library(
         name = "%s/include" % name,
         hdrs = [src + ".h"],
-        include_prefix = include_prefix,
-        strip_include_prefix = strip_include_prefix,
     )

From cf3c3f8f5e44a7283601c9648302aa4d4422e899 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 00:23:36 +0000
Subject: [PATCH 1004/2232] Make it possible to have an empty include prefix


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 1e466e5..267b8cf 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -129,7 +129,6 @@ impl Project {
     fn init() -> Result<Self> {
         let include_prefix = Path::new(CFG.include_prefix);
         assert!(include_prefix.is_relative());
-        assert!(!include_prefix.as_os_str().is_empty());
         let include_prefix = include_prefix.components().collect();
 
         let manifest_dir = paths::manifest_dir()?;
@@ -246,6 +245,11 @@ fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
 }
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+    if prj.include_prefix.as_os_str().is_empty() {
+        let crate_dir = prj.manifest_dir.clone();
+        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
+        return Some(crate_dir);
+    }
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
     let link = crate_dir.join(&prj.include_prefix);
     if out::symlink_dir(&prj.manifest_dir, link).is_ok() {

From 983ccf83690d777bda71e4d93703c5227f94457d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 00:36:35 +0000
Subject: [PATCH 1005/2232] Add documentation on CFG and Cfg


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index ecc9bfb..05578df 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -1,11 +1,64 @@
 use std::fmt::{self, Debug};
 use std::marker::PhantomData;
 
+/// Build configuration. See [CFG].
 pub struct Cfg<'a> {
     pub include_prefix: &'a str,
     marker: PhantomData<*const ()>, // !Send + !Sync
 }
 
+/// Global configuration of the current build.
+///
+/// <br>
+///
+/// ## **`CFG.include_prefix`**
+///
+/// Presently the only exposed configuration is the `include_prefix`, the prefix
+/// at which C++ code from your crate as well as directly dependent crates can
+/// access the code generated during this build.
+///
+/// By default, the `include_prefix` is equal to the name of the current crate.
+/// That means if our crate is called `demo` and has Rust source files in a
+/// *src/* directory and maybe some handwritten C++ header files in an
+/// *include/* directory, then the current crate as well as downstream crates
+/// might include them as follows:
+///
+/// ```
+/// # const _: &str = stringify! {
+///   // include one of the handwritten headers:
+/// #include "demo/include/wow.h"
+///
+///   // include a header generated from Rust cxx::bridge:
+/// #include "demo/src/lib.rs.h"
+/// # };
+/// ```
+///
+/// By modifying `CFG.include_prefix` we can substitute a prefix that is
+/// different from the crate name if desired. Here we'll change it to
+/// `"path/to"` which will make import paths take the form
+/// `"path/to/include/wow.h"` and `"path/to/src/lib.rs.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.include_prefix = "path/to";
+///
+///     cxx_build::bridge("src/lib.rs")
+///         .file("src/demo.cc") // probably contains `#include "path/to/src/lib.rs.h"`
+///         /* ... */
+///         .compile("demo");
+/// }
+/// ```
+///
+/// Note that cross-crate imports are only made available between **direct
+/// dependencies**. Another crate must directly depend on your crate in order to
+/// #include its headers; a transitive dependency is not sufficient.
+/// Additionally, headers from a direct dependency are only importable if the
+/// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
+/// will not be importable from outside of the same crate.
 #[cfg(doc)]
 pub static mut CFG: Cfg = Cfg {
     include_prefix: "",

From 40299e2ccd4d4e96945092fc0c9a7b5c4ceb30c0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 01:01:29 +0000
Subject: [PATCH 1006/2232] Merge pull request #347 from dtolnay/cfg


Expose control of import prefix to Cargo builds
---

diff --git a/BUCK b/BUCK
index 0505bd2..22db155 100644
--- a/BUCK
+++ b/BUCK
@@ -53,6 +53,7 @@ rust_library(
     deps = [
         "//third-party:cc",
         "//third-party:codespan-reporting",
+        "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
diff --git a/BUILD b/BUILD
index e551d18..782374b 100644
--- a/BUILD
+++ b/BUILD
@@ -59,6 +59,7 @@ rust_library(
     deps = [
         "//third-party:cc",
         "//third-party:codespan-reporting",
+        "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
         "//third-party:syn",
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 675261e..3671781 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,6 +13,7 @@ categories = ["development-tools::ffi"]
 [dependencies]
 cc = "1.0.49"
 codespan-reporting = "0.9"
+lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
new file mode 100644
index 0000000..05578df
--- /dev/null
+++ b/gen/build/src/cfg.rs
@@ -0,0 +1,184 @@
+use std::fmt::{self, Debug};
+use std::marker::PhantomData;
+
+/// Build configuration. See [CFG].
+pub struct Cfg<'a> {
+    pub include_prefix: &'a str,
+    marker: PhantomData<*const ()>, // !Send + !Sync
+}
+
+/// Global configuration of the current build.
+///
+/// <br>
+///
+/// ## **`CFG.include_prefix`**
+///
+/// Presently the only exposed configuration is the `include_prefix`, the prefix
+/// at which C++ code from your crate as well as directly dependent crates can
+/// access the code generated during this build.
+///
+/// By default, the `include_prefix` is equal to the name of the current crate.
+/// That means if our crate is called `demo` and has Rust source files in a
+/// *src/* directory and maybe some handwritten C++ header files in an
+/// *include/* directory, then the current crate as well as downstream crates
+/// might include them as follows:
+///
+/// ```
+/// # const _: &str = stringify! {
+///   // include one of the handwritten headers:
+/// #include "demo/include/wow.h"
+///
+///   // include a header generated from Rust cxx::bridge:
+/// #include "demo/src/lib.rs.h"
+/// # };
+/// ```
+///
+/// By modifying `CFG.include_prefix` we can substitute a prefix that is
+/// different from the crate name if desired. Here we'll change it to
+/// `"path/to"` which will make import paths take the form
+/// `"path/to/include/wow.h"` and `"path/to/src/lib.rs.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.include_prefix = "path/to";
+///
+///     cxx_build::bridge("src/lib.rs")
+///         .file("src/demo.cc") // probably contains `#include "path/to/src/lib.rs.h"`
+///         /* ... */
+///         .compile("demo");
+/// }
+/// ```
+///
+/// Note that cross-crate imports are only made available between **direct
+/// dependencies**. Another crate must directly depend on your crate in order to
+/// #include its headers; a transitive dependency is not sufficient.
+/// Additionally, headers from a direct dependency are only importable if the
+/// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
+/// will not be importable from outside of the same crate.
+#[cfg(doc)]
+pub static mut CFG: Cfg = Cfg {
+    include_prefix: "",
+    marker: PhantomData,
+};
+
+impl<'a> Debug for Cfg<'a> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter
+            .debug_struct("Cfg")
+            .field("include_prefix", &self.include_prefix)
+            .finish()
+    }
+}
+
+#[cfg(not(doc))]
+pub use self::r#impl::Cfg::CFG;
+
+#[cfg(not(doc))]
+mod r#impl {
+    use lazy_static::lazy_static;
+    use std::cell::RefCell;
+    use std::collections::HashMap;
+    use std::fmt::{self, Debug};
+    use std::marker::PhantomData;
+    use std::ops::{Deref, DerefMut};
+    use std::sync::{PoisonError, RwLock};
+
+    lazy_static! {
+        static ref PACKAGE_NAME: Box<str> = {
+            crate::env_os("CARGO_PKG_NAME")
+                .map(|pkg| pkg.to_string_lossy().into_owned().into_boxed_str())
+                .unwrap_or_default()
+        };
+        static ref INCLUDE_PREFIX: RwLock<Vec<&'static str>> = RwLock::new(vec![&PACKAGE_NAME]);
+    }
+
+    thread_local! {
+        static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
+    }
+
+    #[derive(Eq, PartialEq, Hash)]
+    struct Handle(*const Cfg<'static>);
+
+    impl<'a> Cfg<'a> {
+        fn current() -> super::Cfg<'a> {
+            let include_prefix = *INCLUDE_PREFIX
+                .read()
+                .unwrap_or_else(PoisonError::into_inner)
+                .last()
+                .unwrap();
+            super::Cfg {
+                include_prefix,
+                marker: PhantomData,
+            }
+        }
+
+        const fn handle(self: &Cfg<'a>) -> Handle {
+            Handle(<*const Cfg>::cast(self))
+        }
+    }
+
+    // Since super::Cfg is !Send and !Sync, all Cfg are thread local and will
+    // drop on the same thread where they were created.
+    pub enum Cfg<'a> {
+        Mut(super::Cfg<'a>),
+        CFG,
+    }
+
+    impl<'a> Debug for Cfg<'a> {
+        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+            if let Cfg::Mut(cfg) = self {
+                Debug::fmt(cfg, formatter)
+            } else {
+                Debug::fmt(&Cfg::current(), formatter)
+            }
+        }
+    }
+
+    impl<'a> Deref for Cfg<'a> {
+        type Target = super::Cfg<'a>;
+
+        fn deref(&self) -> &Self::Target {
+            if let Cfg::Mut(cfg) = self {
+                cfg
+            } else {
+                let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg {
+                    &mut **derefs
+                        .borrow_mut()
+                        .entry(self.handle())
+                        .or_insert_with(|| Box::new(Cfg::current()))
+                });
+                unsafe { &mut *cfg }
+            }
+        }
+    }
+
+    impl<'a> DerefMut for Cfg<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            if let Cfg::CFG = self {
+                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
+                *self = Cfg::Mut(Cfg::current());
+            }
+            match self {
+                Cfg::Mut(cfg) => cfg,
+                Cfg::CFG => unreachable!(),
+            }
+        }
+    }
+
+    impl<'a> Drop for Cfg<'a> {
+        fn drop(&mut self) {
+            if let Cfg::Mut(cfg) = self {
+                INCLUDE_PREFIX
+                    .write()
+                    .unwrap_or_else(PoisonError::into_inner)
+                    .push(Box::leak(Box::from(cfg.include_prefix)));
+            } else {
+                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
+            }
+        }
+    }
+}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 3782543..267b8cf 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -54,6 +54,7 @@
 )]
 
 mod cargo;
+mod cfg;
 mod error;
 mod gen;
 mod out;
@@ -73,6 +74,8 @@ use std::iter;
 use std::path::{Path, PathBuf};
 use std::process;
 
+pub use crate::cfg::{Cfg, CFG};
+
 /// This returns a [`cc::Build`] on which you should continue to set up any
 /// additional source files or compiler flags, and lastly call its [`compile`]
 /// method to execute the C++ build.
@@ -103,7 +106,7 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 }
 
 struct Project {
-    package_name: OsString,
+    include_prefix: PathBuf,
     manifest_dir: PathBuf,
     // Output directory as received from Cargo.
     out_dir: PathBuf,
@@ -124,7 +127,10 @@ struct Project {
 
 impl Project {
     fn init() -> Result<Self> {
-        let package_name = env_os("CARGO_PKG_NAME")?;
+        let include_prefix = Path::new(CFG.include_prefix);
+        assert!(include_prefix.is_relative());
+        let include_prefix = include_prefix.components().collect();
+
         let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
@@ -141,7 +147,7 @@ impl Project {
         };
 
         Ok(Project {
-            package_name,
+            include_prefix,
             manifest_dir,
             out_dir,
             shared_dir,
@@ -239,8 +245,13 @@ fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
 }
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+    if prj.include_prefix.as_os_str().is_empty() {
+        let crate_dir = prj.manifest_dir.clone();
+        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
+        return Some(crate_dir);
+    }
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
-    let link = crate_dir.join(&prj.package_name);
+    let link = crate_dir.join(&prj.include_prefix);
     if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
         println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         Some(crate_dir)
@@ -270,8 +281,8 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
     let cxxbridge = prj.out_dir.join("cxxbridge");
-    let include_dir = cxxbridge.join("include").join(&prj.package_name);
-    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);
+    let include_dir = cxxbridge.join("include").join(&prj.include_prefix);
+    let sources_dir = cxxbridge.join("sources").join(&prj.include_prefix);
 
     let ref rel_path_h = rel_path.with_appended_extension(".h");
     let ref header_path = include_dir.join(rel_path_h);
@@ -285,8 +296,8 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     out::write(implementation_path, &generated.implementation)?;
     build.file(implementation_path);
 
-    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
-    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
+    let shared_h = prj.shared_dir.join(&prj.include_prefix).join(rel_path_h);
+    let shared_cc = prj.shared_dir.join(&prj.include_prefix).join(rel_path_cc);
     let _ = out::symlink_file(header_path, shared_h);
     let _ = out::symlink_file(implementation_path, shared_cc);
     Ok(())
diff --git a/tests/BUCK b/tests/BUCK
index 47fc557..f066542 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -26,10 +26,9 @@ cxx_library(
         ":bridge/source",
         ":module/source",
     ],
-    header_namespace = "cxx-test-suite",
     headers = {
-        "lib.rs.h": ":bridge/header",
-        "tests.h": "ffi/tests.h",
+        "ffi/lib.rs.h": ":bridge/header",
+        "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
 )
diff --git a/tests/BUILD b/tests/BUILD
index 68e7be3..1345a7a 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -29,8 +29,6 @@ cc_library(
         ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [
         ":bridge/include",
         "//:core",
@@ -40,15 +38,11 @@ cc_library(
 rust_cxx_bridge(
     name = "bridge",
     src = "ffi/lib.rs",
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [":impl"],
 )
 
 rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
-    include_prefix = "cxx-test-suite",
-    strip_include_prefix = "ffi",
     deps = [":impl"],
 )
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 8042129..e583944 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -1,8 +1,11 @@
+use cxx_build::CFG;
+
 fn main() {
     if cfg!(trybuild) {
         return;
     }
 
+    CFG.include_prefix = "tests/ffi";
     let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9ace1f2..cc07752 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -23,7 +23,7 @@ pub mod ffi {
     }
 
     extern "C" {
-        include!("cxx-test-suite/tests.h");
+        include!("tests/ffi/tests.h");
 
         type C;
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 8862dc1..77bae06 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -4,7 +4,7 @@
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     extern "C" {
-        include!("cxx-test-suite/tests.h");
+        include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 1f88d8b..9cb6ed0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,5 @@
-#include "cxx-test-suite/tests.h"
-#include "cxx-test-suite/lib.rs.h"
+#include "tests/ffi/tests.h"
+#include "tests/ffi/lib.rs.h"
 #include <cstring>
 #include <iterator>
 #include <numeric>
diff --git a/third-party/BUCK b/third-party/BUCK
index e6a5611..3b0ec99 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -36,6 +36,7 @@ rust_library(
 rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+    visibility = ["PUBLIC"],
 )
 
 rust_library(
diff --git a/third-party/BUILD b/third-party/BUILD
index f874d07..3477326 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -41,6 +41,7 @@ rust_library(
 rust_library(
     name = "lazy_static",
     srcs = glob(["vendor/lazy_static-1.4.0/src/**"]),
+    visibility = ["//visibility:public"],
 )
 
 rust_library(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 7e6a175..d975d6e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -79,6 +79,7 @@ dependencies = [
  "cc",
  "codespan-reporting",
  "cxx-gen",
+ "lazy_static",
  "proc-macro2",
  "quote",
  "syn",
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index d4111c6..534f6b5 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,12 +1,7 @@
 load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
-def rust_cxx_bridge(
-        name,
-        src,
-        include_prefix = None,
-        strip_include_prefix = None,
-        deps = []):
+def rust_cxx_bridge(name, src, deps = []):
     native.alias(
         name = "%s/header" % name,
         actual = src + ".h",
@@ -43,6 +38,4 @@ def rust_cxx_bridge(
     cc_library(
         name = "%s/include" % name,
         hdrs = [src + ".h"],
-        include_prefix = include_prefix,
-        strip_include_prefix = strip_include_prefix,
     )

From 039320287d0ace5cf3ae776a361c17d4a6defb71 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 02:25:06 +0000
Subject: [PATCH 1007/2232] Add fixme to remove const derefs side table


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 05578df..e0186a3 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -97,6 +97,18 @@ mod r#impl {
     }
 
     thread_local! {
+        // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved,
+        // we can delete this thread local side table and instead make each CFG
+        // instance directly own the associated super::Cfg.
+        //
+        //     #[allow(const_item_mutation)]
+        //     pub const CFG: Cfg = Cfg {
+        //         cfg: AtomicPtr::new(ptr::null_mut()),
+        //     };
+        //     pub struct Cfg {
+        //         cfg: AtomicPtr<super::Cfg>,
+        //     }
+        //
         static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
     }
 

From a8beeef131270233940cb5e34bf63b05e886d352 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 02:29:21 +0000
Subject: [PATCH 1008/2232] Import scratch crate


---

diff --git a/BUCK b/BUCK
index 22db155..69b641e 100644
--- a/BUCK
+++ b/BUCK
@@ -56,6 +56,7 @@ rust_library(
         "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
+        "//third-party:scratch",
         "//third-party:syn",
     ],
 )
diff --git a/BUILD b/BUILD
index 782374b..3ada4bc 100644
--- a/BUILD
+++ b/BUILD
@@ -62,6 +62,7 @@ rust_library(
         "//third-party:lazy_static",
         "//third-party:proc-macro2",
         "//third-party:quote",
+        "//third-party:scratch",
         "//third-party:syn",
     ],
 )
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3671781..bf87f1f 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -16,6 +16,7 @@ codespan-reporting = "0.9"
 lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
+scratch = "1.0"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
diff --git a/third-party/BUCK b/third-party/BUCK
index 3b0ec99..afc696b 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -64,6 +64,13 @@ rust_library(
 )
 
 rust_library(
+    name = "scratch",
+    srcs = glob(["vendor/scratch-1.0.0/src/**"]),
+    env = {"OUT_DIR": ""},
+    visibility = ["PUBLIC"],
+)
+
+rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.42/src/**"]),
     visibility = ["PUBLIC"],
diff --git a/third-party/BUILD b/third-party/BUILD
index 3477326..49bf512 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -69,6 +69,13 @@ rust_library(
 )
 
 rust_library(
+    name = "scratch",
+    srcs = glob(["vendor/scratch-1.0.0/src/**"]),
+    rustc_env = {"OUT_DIR": ""},
+    visibility = ["//visibility:public"],
+)
+
+rust_library(
     name = "syn",
     srcs = glob(["vendor/syn-1.0.42/src/**"]),
     crate_features = [
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index d975d6e..c11e27e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -82,6 +82,7 @@ dependencies = [
  "lazy_static",
  "proc-macro2",
  "quote",
+ "scratch",
  "syn",
 ]
 
@@ -222,6 +223,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
 
 [[package]]
+name = "scratch"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
+
+[[package]]
 name = "serde"
 version = "1.0.116"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From 66ebdd1d1fecf1fe095aef6d0636dda580d5210e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 02:31:48 +0000
Subject: [PATCH 1009/2232] Move fallback to scratch crate's out dir


---

diff --git a/BUCK b/BUCK
index 69b641e..da6fcb2 100644
--- a/BUCK
+++ b/BUCK
@@ -48,7 +48,6 @@ rust_library(
 rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**"]),
-    env = {"OUT_DIR": ""},
     visibility = ["PUBLIC"],
     deps = [
         "//third-party:cc",
diff --git a/BUILD b/BUILD
index 3ada4bc..24a1c8b 100644
--- a/BUILD
+++ b/BUILD
@@ -54,7 +54,6 @@ rust_library(
     name = "build",
     srcs = glob(["gen/build/src/**/*.rs"]),
     data = ["gen/build/src/gen/include/cxx.h"],
-    rustc_env = {"OUT_DIR": ""},
     visibility = ["//visibility:public"],
     deps = [
         "//third-party:cc",
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 267b8cf..135833b 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -142,8 +142,7 @@ impl Project {
 
         let shared_dir = match target_dir {
             TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
-            // Use cxx-build's OUT_DIR.
-            TargetDir::Unknown => PathBuf::from(env!("OUT_DIR")),
+            TargetDir::Unknown => scratch::path("cxxbridge"),
         };
 
         Ok(Project {

From 8f16ae75f3fc84be1e17bc66d267f4aa2385ea7e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 02:34:50 +0000
Subject: [PATCH 1010/2232] Bump namespace to 05


---

diff --git a/Cargo.toml b/Cargo.toml
index d8b93f1..54c968f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "cxx"
 version = "0.4.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge04"
+links = "cxxbridge05"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
diff --git a/build.rs b/build.rs
index 688b5b7..57b3e52 100644
--- a/build.rs
+++ b/build.rs
@@ -7,7 +7,7 @@ fn main() {
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
-        .compile("cxxbridge04");
+        .compile("cxxbridge05");
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 135833b..7148d7b 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -263,7 +263,7 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
     let include_dir = prj.out_dir.join("cxxbridge").join("include");
     let cxx_h = include_dir.join("rust").join("cxx.h");
     let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
-    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE04_HEADER") {
+    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE05_HEADER") {
         out::symlink_file(original, cxx_h)?;
         out::symlink_file(original, shared_cxx_h)?;
     } else {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1048272..9e6a297 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -245,7 +245,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     }
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge04");
+    out.begin_block("inline namespace cxxbridge05");
 
     if needs_panic
         || needs_rust_string
@@ -263,22 +263,22 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    include::write(out, needs_panic, "CXXBRIDGE04_PANIC");
+    include::write(out, needs_panic, "CXXBRIDGE05_PANIC");
 
     if needs_rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    include::write(out, needs_rust_string, "CXXBRIDGE04_RUST_STRING");
-    include::write(out, needs_rust_str, "CXXBRIDGE04_RUST_STR");
-    include::write(out, needs_rust_slice, "CXXBRIDGE04_RUST_SLICE");
-    include::write(out, needs_rust_box, "CXXBRIDGE04_RUST_BOX");
-    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE04_RUST_BITCOPY");
-    include::write(out, needs_rust_vec, "CXXBRIDGE04_RUST_VEC");
-    include::write(out, needs_rust_fn, "CXXBRIDGE04_RUST_FN");
-    include::write(out, needs_rust_error, "CXXBRIDGE04_RUST_ERROR");
-    include::write(out, needs_rust_isize, "CXXBRIDGE04_RUST_ISIZE");
+    include::write(out, needs_rust_string, "CXXBRIDGE05_RUST_STRING");
+    include::write(out, needs_rust_str, "CXXBRIDGE05_RUST_STR");
+    include::write(out, needs_rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    include::write(out, needs_rust_box, "CXXBRIDGE05_RUST_BOX");
+    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    include::write(out, needs_rust_vec, "CXXBRIDGE05_RUST_VEC");
+    include::write(out, needs_rust_fn, "CXXBRIDGE05_RUST_FN");
+    include::write(out, needs_rust_error, "CXXBRIDGE05_RUST_ERROR");
+    include::write(out, needs_rust_isize, "CXXBRIDGE05_RUST_ISIZE");
 
     if needs_manually_drop {
         out.next_section();
@@ -304,7 +304,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace cxxbridge04");
+    out.end_block("namespace cxxbridge05");
 
     if needs_trycatch {
         out.begin_block("namespace behavior");
@@ -333,7 +333,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
-    let guard = format!("CXXBRIDGE04_STRUCT_{}{}", out.namespace, strct.ident);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, strct.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in strct.doc.to_string().lines() {
@@ -358,7 +358,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    let guard = format!("CXXBRIDGE04_STRUCT_{}{}", out.namespace, ety.ident);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, ety.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in ety.doc.to_string().lines() {
@@ -379,7 +379,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    let guard = format!("CXXBRIDGE04_ENUM_{}{}", out.namespace, enm.ident);
+    let guard = format!("CXXBRIDGE05_ENUM_{}{}", out.namespace, enm.ident);
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in enm.doc.to_string().lines() {
@@ -465,7 +465,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
         out.next_section();
         writeln!(
             out,
-            "const char *cxxbridge04$exception(const char *, size_t);",
+            "const char *cxxbridge05$exception(const char *, size_t);",
         );
     }
 }
@@ -610,7 +610,7 @@ fn write_cxx_function_shim(
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = cxxbridge04$exception(catch$, throw$.len);",
+            "        throw$.ptr = cxxbridge05$exception(catch$, throw$.len);",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -1089,7 +1089,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("extern \"C\"");
 
     out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge04");
+    out.begin_block("inline namespace cxxbridge05");
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1103,7 +1103,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         }
     }
-    out.end_block("namespace cxxbridge04");
+    out.end_block("namespace cxxbridge05");
     out.end_block("namespace rust");
 }
 
@@ -1116,19 +1116,19 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     inner += &ident.to_string();
     let instance = inner.replace("::", "$");
 
-    writeln!(out, "#ifndef CXXBRIDGE04_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE04_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge04$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge05$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge04$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge05$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE04_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
@@ -1136,34 +1136,34 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE04_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE04_RUST_VEC_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
     writeln!(
         out,
-        "void cxxbridge04$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge05$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge04$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge05$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge04$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        "size_t cxxbridge05$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge04$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        "const {} *cxxbridge05$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
     writeln!(
         out,
-        "size_t cxxbridge04$rust_vec${}$stride() noexcept;",
+        "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
         instance,
     );
-    writeln!(out, "#endif // CXXBRIDGE04_RUST_VEC_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
@@ -1177,12 +1177,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge04$box${}$uninit(this);", instance);
+    writeln!(out, "  cxxbridge05$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge04$box${}$drop(this);", instance);
+    writeln!(out, "  cxxbridge05$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 
@@ -1193,35 +1193,35 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge04$rust_vec${}$new(this);", instance);
+    writeln!(out, "  cxxbridge05$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge04$rust_vec${}$drop(this);",
+        "  return cxxbridge05$rust_vec${}$drop(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge04$rust_vec${}$len(this);", instance);
+    writeln!(out, "  return cxxbridge05$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge04$rust_vec${}$data(this);",
+        "  return cxxbridge05$rust_vec${}$data(this);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge04$rust_vec${}$stride();", instance);
+    writeln!(out, "  return cxxbridge05$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
 }
 
@@ -1229,12 +1229,12 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
     let ty = Type::Ident(ident.clone());
     let instance = to_mangled(&out.namespace, &ty);
 
-    writeln!(out, "#ifndef CXXBRIDGE04_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE04_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
 
     write_unique_ptr_common(out, &ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE04_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE05_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
@@ -1261,7 +1261,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     );
     writeln!(
         out,
-        "void cxxbridge04$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge05$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
@@ -1269,7 +1269,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     if can_construct_from_value {
         writeln!(
             out,
-            "void cxxbridge04$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            "void cxxbridge05$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
         writeln!(
@@ -1281,28 +1281,28 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     }
     writeln!(
         out,
-        "void cxxbridge04$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge05$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge04$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge05$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge04$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge05$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge04$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge05$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
@@ -1314,18 +1314,18 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
     let inner = to_typename(&out.namespace, &element);
     let instance = to_mangled(&out.namespace, &element);
 
-    writeln!(out, "#ifndef CXXBRIDGE04_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE04_VECTOR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge04$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge05$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge04$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge05$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return &s[pos];");
@@ -1333,5 +1333,5 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types:
 
     write_unique_ptr_common(out, vector_ty, types);
 
-    writeln!(out, "#endif // CXXBRIDGE04_VECTOR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE05_VECTOR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index b2e0eee..0373a38 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,12 +15,12 @@
 #endif
 
 namespace rust {
-inline namespace cxxbridge04 {
+inline namespace cxxbridge05 {
 
 struct unsafe_bitcopy_t;
 
-#ifndef CXXBRIDGE04_RUST_STRING
-#define CXXBRIDGE04_RUST_STRING
+#ifndef CXXBRIDGE05_RUST_STRING
+#define CXXBRIDGE05_RUST_STRING
 class String final {
 public:
   String() noexcept;
@@ -49,10 +49,10 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE04_RUST_STRING
+#endif // CXXBRIDGE05_RUST_STRING
 
-#ifndef CXXBRIDGE04_RUST_STR
-#define CXXBRIDGE04_RUST_STR
+#ifndef CXXBRIDGE05_RUST_STR
+#define CXXBRIDGE05_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -86,9 +86,9 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE04_RUST_STR
+#endif // CXXBRIDGE05_RUST_STR
 
-#ifndef CXXBRIDGE04_RUST_SLICE
+#ifndef CXXBRIDGE05_RUST_SLICE
 template <typename T>
 class Slice final {
 public:
@@ -117,9 +117,9 @@ public:
 private:
   Repr repr;
 };
-#endif // CXXBRIDGE04_RUST_SLICE
+#endif // CXXBRIDGE05_RUST_SLICE
 
-#ifndef CXXBRIDGE04_RUST_BOX
+#ifndef CXXBRIDGE05_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -158,9 +158,9 @@ private:
   void drop() noexcept;
   T *ptr;
 };
-#endif // CXXBRIDGE04_RUST_BOX
+#endif // CXXBRIDGE05_RUST_BOX
 
-#ifndef CXXBRIDGE04_RUST_VEC
+#ifndef CXXBRIDGE05_RUST_VEC
 template <typename T>
 class Vec final {
 public:
@@ -218,10 +218,10 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE04_RUST_VEC
+#endif // CXXBRIDGE05_RUST_VEC
 
-#ifndef CXXBRIDGE04_RUST_FN
-#define CXXBRIDGE04_RUST_FN
+#ifndef CXXBRIDGE05_RUST_FN
+#define CXXBRIDGE05_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -238,10 +238,10 @@ private:
 
 template <typename Signature>
 using TryFn = Fn<Signature, true>;
-#endif // CXXBRIDGE04_RUST_FN
+#endif // CXXBRIDGE05_RUST_FN
 
-#ifndef CXXBRIDGE04_RUST_ERROR
-#define CXXBRIDGE04_RUST_ERROR
+#ifndef CXXBRIDGE05_RUST_ERROR
+#define CXXBRIDGE05_RUST_ERROR
 class Error final : public std::exception {
 public:
   Error(const Error &);
@@ -253,16 +253,16 @@ public:
 private:
   Str::Repr msg;
 };
-#endif // CXXBRIDGE04_RUST_ERROR
+#endif // CXXBRIDGE05_RUST_ERROR
 
-#ifndef CXXBRIDGE04_RUST_ISIZE
-#define CXXBRIDGE04_RUST_ISIZE
+#ifndef CXXBRIDGE05_RUST_ISIZE
+#define CXXBRIDGE05_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
-#endif // CXXBRIDGE04_RUST_ISIZE
+#endif // CXXBRIDGE05_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -287,11 +287,11 @@ using try_fn = TryFn<Signature>;
 ////////////////////////////////////////////////////////////////////////////////
 /// end public API, begin implementation details
 
-#ifndef CXXBRIDGE04_PANIC
-#define CXXBRIDGE04_PANIC
+#ifndef CXXBRIDGE05_PANIC
+#define CXXBRIDGE05_PANIC
 template <typename Exception>
 void panic [[noreturn]] (const char *msg);
-#endif // CXXBRIDGE04_PANIC
+#endif // CXXBRIDGE05_PANIC
 
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
@@ -303,17 +303,17 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
 
-#ifndef CXXBRIDGE04_RUST_BITCOPY
-#define CXXBRIDGE04_RUST_BITCOPY
+#ifndef CXXBRIDGE05_RUST_BITCOPY
+#define CXXBRIDGE05_RUST_BITCOPY
 struct unsafe_bitcopy_t {
   explicit unsafe_bitcopy_t() = default;
 };
 
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE04_RUST_BITCOPY
+#endif // CXXBRIDGE05_RUST_BITCOPY
 
-#ifndef CXXBRIDGE04_RUST_SLICE
-#define CXXBRIDGE04_RUST_SLICE
+#ifndef CXXBRIDGE05_RUST_SLICE
+#define CXXBRIDGE05_RUST_SLICE
 template <typename T>
 Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
 
@@ -351,10 +351,10 @@ template <typename T>
 Slice<T>::operator Repr() noexcept {
   return this->repr;
 }
-#endif // CXXBRIDGE04_RUST_SLICE
+#endif // CXXBRIDGE05_RUST_SLICE
 
-#ifndef CXXBRIDGE04_RUST_BOX
-#define CXXBRIDGE04_RUST_BOX
+#ifndef CXXBRIDGE05_RUST_BOX
+#define CXXBRIDGE05_RUST_BOX
 template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
@@ -450,10 +450,10 @@ T *Box<T>::into_raw() noexcept {
 
 template <typename T>
 Box<T>::Box() noexcept {}
-#endif // CXXBRIDGE04_RUST_BOX
+#endif // CXXBRIDGE05_RUST_BOX
 
-#ifndef CXXBRIDGE04_RUST_VEC
-#define CXXBRIDGE04_RUST_VEC
+#ifndef CXXBRIDGE05_RUST_VEC
+#define CXXBRIDGE05_RUST_VEC
 template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept {
   this->repr = other.repr;
@@ -558,7 +558,7 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 // Internal API only intended for the cxxbridge code generator.
 template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
-#endif // CXXBRIDGE04_RUST_VEC
+#endif // CXXBRIDGE05_RUST_VEC
 
-} // namespace cxxbridge04
+} // namespace cxxbridge05
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index dd5350f..20f166f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -727,7 +727,7 @@ fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge04$box${}{}$", namespace, ident);
+    let link_prefix = format!("cxxbridge05$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
@@ -756,7 +756,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
 }
 
 fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge04$rust_vec${}{}$", namespace, elem);
+    let link_prefix = format!("cxxbridge05$rust_vec${}{}$", namespace, elem);
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -807,7 +807,7 @@ fn expand_unique_ptr(
     explicit_impl: Option<&Impl>,
 ) -> TokenStream {
     let name = ident.to_string();
-    let prefix = format!("cxxbridge04$unique_ptr${}{}$", namespace, ident);
+    let prefix = format!("cxxbridge05$unique_ptr${}{}$", namespace, ident);
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -890,10 +890,10 @@ fn expand_cxx_vector(
 ) -> TokenStream {
     let _ = explicit_impl;
     let name = elem.to_string();
-    let prefix = format!("cxxbridge04$std$vector${}{}$", namespace, elem);
+    let prefix = format!("cxxbridge05$std$vector${}{}$", namespace, elem);
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge04$unique_ptr$std$vector${}{}$", namespace, elem);
+    let unique_ptr_prefix = format!("cxxbridge05$unique_ptr$std$vector${}{}$", namespace, elem);
     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/src/cxx.cc b/src/cxx.cc
index cd75162..715e0ce 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -7,30 +7,30 @@
 #include <vector>
 
 extern "C" {
-const char *cxxbridge04$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge04$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
 // rust::String
-void cxxbridge04$string$new(rust::String *self) noexcept;
-void cxxbridge04$string$clone(rust::String *self,
+void cxxbridge05$string$new(rust::String *self) noexcept;
+void cxxbridge05$string$clone(rust::String *self,
                               const rust::String &other) noexcept;
-bool cxxbridge04$string$from(rust::String *self, const char *ptr,
+bool cxxbridge05$string$from(rust::String *self, const char *ptr,
                              size_t len) noexcept;
-void cxxbridge04$string$drop(rust::String *self) noexcept;
-const char *cxxbridge04$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge04$string$len(const rust::String *self) noexcept;
+void cxxbridge05$string$drop(rust::String *self) noexcept;
+const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge05$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge04$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge04 {
+inline namespace cxxbridge05 {
 
 template <typename Exception>
 void panic [[noreturn]] (const char *msg) {
@@ -44,42 +44,42 @@ void panic [[noreturn]] (const char *msg) {
 
 template void panic<std::out_of_range>[[noreturn]] (const char *msg);
 
-String::String() noexcept { cxxbridge04$string$new(this); }
+String::String() noexcept { cxxbridge05$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge04$string$clone(this, other);
+  cxxbridge05$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge04$string$new(&other);
+  cxxbridge05$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge04$string$drop(this); }
+String::~String() noexcept { cxxbridge05$string$drop(this); }
 
 String::String(const std::string &s) : String(s.data(), s.length()) {}
 
 String::String(const char *s) : String(s, std::strlen(s)) {}
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge04$string$from(this, s, len)) {
+  if (!cxxbridge05$string$from(this, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge04$string$drop(this);
-    cxxbridge04$string$clone(this, other);
+    cxxbridge05$string$drop(this);
+    cxxbridge05$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge04$string$drop(this);
+    cxxbridge05$string$drop(this);
     this->repr = other.repr;
-    cxxbridge04$string$new(&other);
+    cxxbridge05$string$new(&other);
   }
   return *this;
 }
@@ -89,12 +89,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge04$string$ptr(this);
+  return cxxbridge05$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge04$string$len(this); }
+size_t String::size() const noexcept { return cxxbridge05$string$len(this); }
 
-size_t String::length() const noexcept { return cxxbridge04$string$len(this); }
+size_t String::length() const noexcept { return cxxbridge05$string$len(this); }
 
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
@@ -113,7 +113,7 @@ Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
 Str::Str(const char *s) : Str(s, std::strlen(s)) {}
 
 Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
-  if (!cxxbridge04$str$valid(this->repr.ptr, this->repr.len)) {
+  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
@@ -143,7 +143,7 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
 }
 
 extern "C" {
-const char *cxxbridge04$error(const char *ptr, size_t len) {
+const char *cxxbridge05$error(const char *ptr, size_t len) {
   char *copy = new char[len];
   strncpy(copy, ptr, len);
   return copy;
@@ -153,7 +153,7 @@ const char *cxxbridge04$error(const char *ptr, size_t len) {
 Error::Error(Str::Repr msg) noexcept : msg(msg) {}
 
 Error::Error(const Error &other) {
-  this->msg.ptr = cxxbridge04$error(other.msg.ptr, other.msg.len);
+  this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
   this->msg.len = other.msg.len;
 }
 
@@ -168,96 +168,96 @@ Error::~Error() noexcept { delete[] this->msg.ptr; }
 
 const char *Error::what() const noexcept { return this->msg.ptr; }
 
-} // namespace cxxbridge04
+} // namespace cxxbridge05
 } // namespace rust
 
 extern "C" {
-void cxxbridge04$unique_ptr$std$string$null(
+void cxxbridge05$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge04$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                            std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge04$unique_ptr$std$string$get(
+const std::string *cxxbridge05$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge04$unique_ptr$std$string$release(
+std::string *cxxbridge05$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge04$unique_ptr$std$string$drop(
+void cxxbridge05$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
 } // extern "C"
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  size_t cxxbridge04$std$vector$##RUST_TYPE##$size(                            \
+  size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge04$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked(          \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
-  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
   const std::vector<CXX_TYPE>                                                  \
-      *cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
+      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
           const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
   std::vector<CXX_TYPE>                                                        \
-      *cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$release(                \
+      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release(                \
           std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
-  void cxxbridge04$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
   }
 
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
-  void cxxbridge04$rust_vec$##RUST_TYPE##$new(                                 \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$new(                                 \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  void cxxbridge04$rust_vec$##RUST_TYPE##$drop(                                \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$drop(                                \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  size_t cxxbridge04$rust_vec$##RUST_TYPE##$len(                               \
+  size_t cxxbridge05$rust_vec$##RUST_TYPE##$len(                               \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  const CXX_TYPE *cxxbridge04$rust_vec$##RUST_TYPE##$data(                     \
+  const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  size_t cxxbridge04$rust_vec$##RUST_TYPE##$stride() noexcept;
+  size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
   Vec<CXX_TYPE>::Vec() noexcept {                                              \
-    cxxbridge04$rust_vec$##RUST_TYPE##$new(this);                              \
+    cxxbridge05$rust_vec$##RUST_TYPE##$new(this);                              \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::drop() noexcept {                                        \
-    return cxxbridge04$rust_vec$##RUST_TYPE##$drop(this);                      \
+    return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::size() const noexcept {                                \
-    return cxxbridge04$rust_vec$##RUST_TYPE##$len(this);                       \
+    return cxxbridge05$rust_vec$##RUST_TYPE##$len(this);                       \
   }                                                                            \
   template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
-    return cxxbridge04$rust_vec$##RUST_TYPE##$data(this);                      \
+    return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
-    return cxxbridge04$rust_vec$##RUST_TYPE##$stride();                        \
+    return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
   }
 
 // Usize and isize are the same type as one of the below.
@@ -290,7 +290,7 @@ FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge04 {
+inline namespace cxxbridge05 {
 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
-} // namespace cxxbridge04
+} // namespace cxxbridge05
 } // namespace rust
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 2c712f1..7b47feb 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -5,9 +5,9 @@ use core::slice;
 use core::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge04$cxx_string$data"]
+    #[link_name = "cxxbridge05$cxx_string$data"]
     fn string_data(_: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge04$cxx_string$length"]
+    #[link_name = "cxxbridge05$cxx_string$length"]
     fn string_length(_: &CxxString) -> usize;
 }
 
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index a5fe536..5fb0807 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -157,7 +157,7 @@ macro_rules! impl_vector_element {
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$size")]
+                        #[link_name = concat!("cxxbridge05$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -166,7 +166,7 @@ macro_rules! impl_vector_element {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$std$vector$", $segment, "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge05$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -175,7 +175,7 @@ macro_rules! impl_vector_element {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$null")]
+                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -186,7 +186,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$raw")]
+                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -197,7 +197,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$get")]
+                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -206,7 +206,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$release")]
+                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -215,7 +215,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge04$unique_ptr$std$vector$", $segment, "$drop")]
+                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
diff --git a/src/result.rs b/src/result.rs
index 296d4a2..fcced76 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -34,7 +34,7 @@ unsafe fn to_c_error(msg: String) -> Result {
     let len = msg.len();
 
     extern "C" {
-        #[link_name = "cxxbridge04$error"]
+        #[link_name = "cxxbridge05$error"]
         fn error(ptr: *const u8, len: usize) -> *const u8;
     }
 
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index da1c3f9..b408f25 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -2,7 +2,7 @@ use alloc::boxed::Box;
 use alloc::string::String;
 use core::slice;
 
-#[export_name = "cxxbridge04$exception"]
+#[export_name = "cxxbridge05$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
     let slice = slice::from_raw_parts(ptr, len);
     let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 823173a..b655381 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,7 +1,7 @@
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge04$str$valid"]
+#[export_name = "cxxbridge05$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 774b824..e5ab9ea 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -5,17 +5,17 @@ use core::ptr;
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge04$string$new"]
+#[export_name = "cxxbridge05$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge04$string$clone"]
+#[export_name = "cxxbridge05$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge04$string$from"]
+#[export_name = "cxxbridge05$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -31,17 +31,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge04$string$drop"]
+#[export_name = "cxxbridge05$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge04$string$ptr"]
+#[export_name = "cxxbridge05$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge04$string$len"]
+#[export_name = "cxxbridge05$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 2304abf..00a7f16 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -11,31 +11,31 @@ macro_rules! rust_vec_shims {
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$new")]
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec { repr: Vec::new() });
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$drop")]
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$len")]
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).repr.len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$data")]
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge04$rust_vec$", $segment, "$stride")]
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 7408d40..477c716 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -174,15 +174,15 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge04$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge05$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge04$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge05$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge04$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge05$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge04$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge05$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge04$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge05$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 1c8c917..72233b3 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -3,7 +3,7 @@ use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::ExternFn;
 use proc_macro2::Ident;
 
-const CXXBRIDGE: &str = "cxxbridge04";
+const CXXBRIDGE: &str = "cxxbridge05";
 
 macro_rules! join {
     ($($segment:expr),*) => {
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index c8500b9..1e5b513 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -4,7 +4,7 @@ use quote::ToTokens;
 use std::fmt::{self, Display, Write};
 
 // A mangled symbol consisting of segments separated by '$'.
-// For example: cxxbridge04$string$new
+// For example: cxxbridge05$string$new
 pub struct Symbol(String);
 
 impl Display for Symbol {
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 139950e..527d709 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -18,7 +18,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
 }
 
 #[test]
@@ -28,5 +28,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge04$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
 }

From c499950924e05f2534ddd90fdd53fc87d0d3cecf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 02:34:50 +0000
Subject: [PATCH 1011/2232] Release 0.5.0


---

diff --git a/Cargo.toml b/Cargo.toml
index 54c968f..6ee9913 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.4.7" # remember to update html_root_url
+version = "0.5.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,16 +20,16 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.4.7", path = "macro" }
+cxxbridge-macro = { version = "=0.5.0", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.4.7", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.0", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.4.7", path = "gen/build" }
-cxx-gen = { version = "0.4", path = "gen/lib" }
+cxx-build = { version = "=0.5.0", path = "gen/build" }
+cxx-gen = { version = "0.5", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/README.md b/README.md
index 38fe682..46389a3 100644
--- a/README.md
+++ b/README.md
@@ -18,10 +18,10 @@ can be 100% safe.
 
 ```toml
 [dependencies]
-cxx = "0.4"
+cxx = "0.5"
 
 [build-dependencies]
-cxx-build = "0.4"
+cxx-build = "0.5"
 ```
 
 *Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
@@ -222,7 +222,7 @@ set up any additional source files and compiler flags as normal.
 # Cargo.toml
 
 [build-dependencies]
-cxx-build = "0.4"
+cxx-build = "0.5"
 ```
 
 ```rust
@@ -310,11 +310,11 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.4/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 5b4f666..bfaec83 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.4.7"
+version = "0.5.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index bf87f1f..c6ef927 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.4.7"
+version = "0.5.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -20,7 +20,7 @@ scratch = "1.0"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
-cxx-gen = { version = "0.4", path = "../lib" }
+cxx-gen = { version = "0.5", path = "../lib" }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 684642c..b8354f9 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.4.7"
+version = "0.5.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index faa82c2..ee4052f 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.4.1"
+version = "0.5.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9c151b8..9770a5e 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.4.7"
+version = "0.5.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -19,7 +19,7 @@ quote = "1.0.4"
 syn = { version = "1.0.20", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.4", path = ".." }
+cxx = { version = "0.5", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index 9287101..cb10a18 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -228,7 +228,7 @@
 //! # Cargo.toml
 //!
 //! [build-dependencies]
-//! cxx-build = "0.4"
+//! cxx-build = "0.5"
 //! ```
 //!
 //! ```no_run
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.4.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.0")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index c11e27e..6775e06 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.4.7"
+version = "0.5.0"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.4.7"
+version = "0.5.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -88,7 +88,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.4.1"
+version = "0.5.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.4.7"
+version = "0.5.0"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -119,11 +119,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.4.7"
+version = "0.5.0"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.4.7"
+version = "0.5.0"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5a4d53a1059cfa6c4ee189e52859b80a01f5b03e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 03:36:58 +0000
Subject: [PATCH 1012/2232] Update bazel build to rustc 1.47


---

diff --git a/WORKSPACE b/WORKSPACE
index 5e0cf9e..d62b5dd 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -24,13 +24,13 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_46_linux",
+    name = "rust_1_47_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.46.0",
+    version = "1.47.0",
 )
 
 rust_repository_set(
-    name = "rust_1_46_darwin",
+    name = "rust_1_47_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.46.0",
+    version = "1.47.0",
 )

From d9e789e8cf5bb0001b547e0c6f533a6febef990b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 04:22:45 +0000
Subject: [PATCH 1013/2232] Fix readme's reference to directory of cmd


This moved from cmd to gen/cmd in f8ed07327b5217c3e63b44597dc026f95156bdbd.

---

diff --git a/README.md b/README.md
index 46389a3..7171724 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ fn main() {
 For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate way of
 invoking the C++ code generator as a standalone command line tool. The tool is
 packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the
-*cmd* directory of this repo.
+*gen/cmd* directory of this repo.
 
 ```bash
 $ cargo install cxxbridge-cmd
diff --git a/src/lib.rs b/src/lib.rs
index cb10a18..aaf4196 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -253,7 +253,7 @@
 //! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
 //! way of invoking the C++ code generator as a standalone command line tool.
 //! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
-//! built from the *cmd* directory of [https://github.com/dtolnay/cxx].
+//! built from the *gen/cmd* directory of [https://github.com/dtolnay/cxx].
 //!
 //! ```bash
 //! $ cargo install cxxbridge-cmd

From f3a9afae5015971cc8b3e857c6dadbb9142bd3f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 09 2020 06:22:15 +0000
Subject: [PATCH 1014/2232] Omit empty derive attribute


Previously an empty #[derive()] would appear distractingly in
macro-expanded code.

---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
new file mode 100644
index 0000000..1abc5da
--- /dev/null
+++ b/macro/src/derive.rs
@@ -0,0 +1,14 @@
+use crate::syntax::Derive;
+use proc_macro2::TokenStream;
+use quote::{quote, ToTokens};
+
+pub struct DeriveAttribute<'a>(pub &'a [Derive]);
+
+impl<'a> ToTokens for DeriveAttribute<'a> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if !self.0.is_empty() {
+            let derives = self.0;
+            tokens.extend(quote!(#[derive(#(#derives),*)]));
+        }
+    }
+}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 20f166f..cb3babd 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,3 +1,4 @@
+use crate::derive::DeriveAttribute;
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
@@ -128,7 +129,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
     let ident = &strct.ident;
     let doc = &strct.doc;
-    let derives = &strct.derives;
+    let derives = DeriveAttribute(&strct.derives);
     let type_id = type_id(namespace, ident);
     let fields = strct.fields.iter().map(|field| {
         // This span on the pub makes "private type in public interface" errors
@@ -139,7 +140,7 @@ fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
 
     quote! {
         #doc
-        #[derive(#(#derives),*)]
+        #derives
         #[repr(C)]
         pub struct #ident {
             #(#fields,)*
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index fae874a..291b03c 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -9,6 +9,7 @@
 
 extern crate proc_macro;
 
+mod derive;
 mod expand;
 mod syntax;
 mod type_id;

From a4641c738ac9201880a3fce3449b4f481c3d7d3e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 02:12:17 +0000
Subject: [PATCH 1015/2232] Store independent rust name and c++ name for extern functions


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9e6a297..5d47c63 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -370,7 +370,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.to_string();
+        let local_name = method.ident.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
@@ -517,8 +517,8 @@ fn write_cxx_function_shim(
     write!(out, "  ");
     write_return_type(out, &efn.ret);
     match &efn.receiver {
-        None => write!(out, "(*{}$)(", efn.ident),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
+        None => write!(out, "(*{}$)(", efn.ident.rust),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident.rust),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -534,8 +534,8 @@ fn write_cxx_function_shim(
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
+        None => write!(out, "{}", efn.ident.cxx),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident.cxx),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -562,8 +562,8 @@ fn write_cxx_function_shim(
         _ => {}
     }
     match &efn.receiver {
-        None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
+        None => write!(out, "{}$(", efn.ident.rust),
+        Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -697,8 +697,8 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
+        None => efn.ident.cxx.to_string(),
+        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
     };
     let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index cb3babd..6fa7ea7 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -206,7 +206,6 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 }
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
         quote!(_: #receiver_type)
@@ -238,7 +237,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(namespace, efn);
-    let local_name = format_ident!("__{}", ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
     quote! {
         #[link_name = #link_name]
         fn #local_name(#(#all_args,)* #outparam) #ret;
@@ -246,7 +245,6 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
 }
 
 fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
@@ -329,7 +327,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
         })
         .collect::<TokenStream>();
-    let local_name = format_ident!("__{}", ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
     let call = if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         setup.extend(quote! {
@@ -426,6 +424,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
+    let ident = &efn.ident.rust;
     let function_shim = quote! {
         #doc
         pub #unsafety fn #ident(#(#all_args,)*) #ret {
@@ -455,7 +454,7 @@ fn expand_function_pointer_trampoline(
     let c_trampoline = mangle::c_trampoline(namespace, efn, var);
     let r_trampoline = mangle::r_trampoline(namespace, efn, var);
     let local_name = parse_quote!(__);
-    let catch_unwind_label = format!("::{}::{}", efn.ident, var);
+    let catch_unwind_label = format!("::{}::{}", efn.ident.rust, var);
     let shim = expand_rust_function_shim_impl(
         sig,
         types,
@@ -510,11 +509,10 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 }
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let link_name = mangle::extern_fn(namespace, efn);
-    let local_name = format_ident!("__{}", ident);
-    let catch_unwind_label = format!("::{}", ident);
-    let invoke = Some(ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
+    let catch_unwind_label = format!("::{}", efn.ident.rust);
+    let invoke = Some(&efn.ident.rust);
     expand_rust_function_shim_impl(
         efn,
         types,
diff --git a/syntax/check.rs b/syntax/check.rs
index ff23ec9..2f3c334 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -214,8 +214,8 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
-            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
-            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident),
+            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
+            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 74e7799..66f7365 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -37,7 +37,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                 check(cx, &ety.ident);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                check(cx, &efn.ident);
+                check(cx, &efn.ident.rust);
                 for arg in &efn.args {
                     check(cx, &arg.ident);
                 }
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 72233b3..e461887 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -13,8 +13,8 @@ macro_rules! join {
 
 pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
     match &efn.receiver {
-        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident),
-        None => join!(namespace, CXXBRIDGE, efn.ident),
+        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident.rust),
+        None => join!(namespace, CXXBRIDGE, efn.ident.rust),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 934f6c6..c8dea67 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -71,10 +71,15 @@ pub struct Enum {
     pub repr: Atom,
 }
 
+pub struct Pair {
+    pub cxx: Ident,
+    pub rust: Ident,
+}
+
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
-    pub ident: Ident,
+    pub ident: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c611c8b..142d063 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
     Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
@@ -370,7 +370,10 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     Ok(api_function(ExternFn {
         lang,
         doc,
-        ident,
+        ident: Pair {
+            cxx: ident.clone(),
+            rust: ident,
+        },
         sig: Signature {
             unsafety,
             fn_token,
diff --git a/syntax/types.rs b/syntax/types.rs
index 3f8d10c..5ec7d26 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -51,7 +51,8 @@ impl<'a> Types<'a> {
         }
 
         let mut type_names = UnorderedSet::new();
-        let mut function_names = UnorderedSet::new();
+        let mut cxx_function_names = UnorderedSet::new();
+        let mut rust_function_names = UnorderedSet::new();
         for api in apis {
             // The same identifier is permitted to be declared as both a shared
             // enum and extern C++ type, or shared struct and extern C++ type.
@@ -116,9 +117,15 @@ impl<'a> Types<'a> {
                     rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let ident = &efn.ident;
-                    if !function_names.insert((&efn.receiver, ident)) {
-                        duplicate_name(cx, efn, ident);
+                    let cxx_fn = (&efn.receiver, &efn.ident.cxx);
+                    let rust_fn = (&efn.receiver, &efn.ident.rust);
+                    let cxx_duplicate = !cxx_function_names.insert(cxx_fn);
+                    if !rust_function_names.insert(rust_fn) {
+                        duplicate_name(cx, efn, &efn.ident.rust);
+                    } else if cxx_duplicate {
+                        // Insert into cxx_function_names either way, but hide
+                        // error if we're already erroring on the rust name.
+                        duplicate_name(cx, efn, &efn.ident.cxx);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);

From 1d673d82a75c4960ed708850ddaa043b840bba11 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 02:44:02 +0000
Subject: [PATCH 1016/2232] Permit duplicate C++ names of extern functions


C++ has overloading so that's fine.

---

diff --git a/syntax/types.rs b/syntax/types.rs
index 5ec7d26..5bac76e 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -51,8 +51,7 @@ impl<'a> Types<'a> {
         }
 
         let mut type_names = UnorderedSet::new();
-        let mut cxx_function_names = UnorderedSet::new();
-        let mut rust_function_names = UnorderedSet::new();
+        let mut function_names = UnorderedSet::new();
         for api in apis {
             // The same identifier is permitted to be declared as both a shared
             // enum and extern C++ type, or shared struct and extern C++ type.
@@ -117,15 +116,10 @@ impl<'a> Types<'a> {
                     rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let cxx_fn = (&efn.receiver, &efn.ident.cxx);
-                    let rust_fn = (&efn.receiver, &efn.ident.rust);
-                    let cxx_duplicate = !cxx_function_names.insert(cxx_fn);
-                    if !rust_function_names.insert(rust_fn) {
+                    // Note: duplication of the C++ name is fine because C++ has
+                    // function overloading.
+                    if !function_names.insert((&efn.receiver, &efn.ident.rust)) {
                         duplicate_name(cx, efn, &efn.ident.rust);
-                    } else if cxx_duplicate {
-                        // Insert into cxx_function_names either way, but hide
-                        // error if we're already erroring on the rust name.
-                        duplicate_name(cx, efn, &efn.ident.cxx);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);

From e107c1b81d55e65030f41f741d547ce20212b51e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:22:01 +0000
Subject: [PATCH 1017/2232] Merge pull request #348 from dtolnay/alias


Store independent rust name and c++ name for extern functions
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9e6a297..5d47c63 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -370,7 +370,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.to_string();
+        let local_name = method.ident.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
@@ -517,8 +517,8 @@ fn write_cxx_function_shim(
     write!(out, "  ");
     write_return_type(out, &efn.ret);
     match &efn.receiver {
-        None => write!(out, "(*{}$)(", efn.ident),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident),
+        None => write!(out, "(*{}$)(", efn.ident.rust),
+        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident.rust),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -534,8 +534,8 @@ fn write_cxx_function_shim(
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident),
+        None => write!(out, "{}", efn.ident.cxx),
+        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident.cxx),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -562,8 +562,8 @@ fn write_cxx_function_shim(
         _ => {}
     }
     match &efn.receiver {
-        None => write!(out, "{}$(", efn.ident),
-        Some(_) => write!(out, "(self.*{}$)(", efn.ident),
+        None => write!(out, "{}$(", efn.ident.rust),
+        Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -697,8 +697,8 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident),
+        None => efn.ident.cxx.to_string(),
+        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
     };
     let invoke = mangle::extern_fn(&out.namespace, efn);
     let indirect_call = false;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index cb3babd..6fa7ea7 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -206,7 +206,6 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
 }
 
 fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
         quote!(_: #receiver_type)
@@ -238,7 +237,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(namespace, efn);
-    let local_name = format_ident!("__{}", ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
     quote! {
         #[link_name = #link_name]
         fn #local_name(#(#all_args,)* #outparam) #ret;
@@ -246,7 +245,6 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
 }
 
 fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(namespace, efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
@@ -329,7 +327,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
         })
         .collect::<TokenStream>();
-    let local_name = format_ident!("__{}", ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
     let call = if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         setup.extend(quote! {
@@ -426,6 +424,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
+    let ident = &efn.ident.rust;
     let function_shim = quote! {
         #doc
         pub #unsafety fn #ident(#(#all_args,)*) #ret {
@@ -455,7 +454,7 @@ fn expand_function_pointer_trampoline(
     let c_trampoline = mangle::c_trampoline(namespace, efn, var);
     let r_trampoline = mangle::r_trampoline(namespace, efn, var);
     let local_name = parse_quote!(__);
-    let catch_unwind_label = format!("::{}::{}", efn.ident, var);
+    let catch_unwind_label = format!("::{}::{}", efn.ident.rust, var);
     let shim = expand_rust_function_shim_impl(
         sig,
         types,
@@ -510,11 +509,10 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 }
 
 fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let ident = &efn.ident;
     let link_name = mangle::extern_fn(namespace, efn);
-    let local_name = format_ident!("__{}", ident);
-    let catch_unwind_label = format!("::{}", ident);
-    let invoke = Some(ident);
+    let local_name = format_ident!("__{}", efn.ident.rust);
+    let catch_unwind_label = format!("::{}", efn.ident.rust);
+    let invoke = Some(&efn.ident.rust);
     expand_rust_function_shim_impl(
         efn,
         types,
diff --git a/syntax/check.rs b/syntax/check.rs
index ff23ec9..2f3c334 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -214,8 +214,8 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
-            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident),
-            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident),
+            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
+            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 74e7799..66f7365 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -37,7 +37,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                 check(cx, &ety.ident);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                check(cx, &efn.ident);
+                check(cx, &efn.ident.rust);
                 for arg in &efn.args {
                     check(cx, &arg.ident);
                 }
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 72233b3..e461887 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -13,8 +13,8 @@ macro_rules! join {
 
 pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
     match &efn.receiver {
-        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident),
-        None => join!(namespace, CXXBRIDGE, efn.ident),
+        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident.rust),
+        None => join!(namespace, CXXBRIDGE, efn.ident.rust),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 934f6c6..c8dea67 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -71,10 +71,15 @@ pub struct Enum {
     pub repr: Atom,
 }
 
+pub struct Pair {
+    pub cxx: Ident,
+    pub rust: Ident,
+}
+
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
-    pub ident: Ident,
+    pub ident: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c611c8b..142d063 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
     Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
@@ -370,7 +370,10 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     Ok(api_function(ExternFn {
         lang,
         doc,
-        ident,
+        ident: Pair {
+            cxx: ident.clone(),
+            rust: ident,
+        },
         sig: Signature {
             unsafety,
             fn_token,
diff --git a/syntax/types.rs b/syntax/types.rs
index 3f8d10c..5bac76e 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -116,9 +116,10 @@ impl<'a> Types<'a> {
                     rust.insert(ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let ident = &efn.ident;
-                    if !function_names.insert((&efn.receiver, ident)) {
-                        duplicate_name(cx, efn, ident);
+                    // Note: duplication of the C++ name is fine because C++ has
+                    // function overloading.
+                    if !function_names.insert((&efn.receiver, &efn.ident.rust)) {
+                        duplicate_name(cx, efn, &efn.ident.rust);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);

From 1039a24ee4fed457873d8e07b8821db34ca1347f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:22:22 +0000
Subject: [PATCH 1018/2232] Attribute parser for cxx_name and rust_name attributes


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 4c76641..4c8a3e5 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -10,6 +10,8 @@ pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,
     pub derives: Option<&'a mut Vec<Derive>>,
     pub repr: Option<&'a mut Option<Atom>>,
+    pub cxx_name: Option<&'a mut Option<Ident>>,
+    pub rust_name: Option<&'a mut Option<Ident>>,
 }
 
 pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
@@ -57,6 +59,26 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("cxx_name") {
+            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(cxx_name) = &mut parser.cxx_name {
+                        **cxx_name = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
+        } else if attr.path.is_ident("rust_name") {
+            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(rust_name) = &mut parser.rust_name {
+                        **rust_name = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -99,3 +121,13 @@ fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
         "unrecognized repr",
     ))
 }
+
+fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
+    input.parse::<Token![=]>()?;
+    if input.peek(LitStr) {
+        let lit: LitStr = input.parse()?;
+        lit.parse()
+    } else {
+        input.parse()
+    }
+}

From 938ca8585645875dd8ab04a1b1e2e691f936a86c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:22:23 +0000
Subject: [PATCH 1019/2232] Translate cxx_/rust_name from attribute to syntax tree


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 142d063..367ad05 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,6 +300,20 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
         ));
     }
 
+    let mut doc = Doc::new();
+    let mut cxx_name = None;
+    let mut rust_name = None;
+    attrs::parse(
+        cx,
+        &foreign_fn.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
+            ..Default::default()
+        },
+    );
+
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -356,10 +370,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let doc = attrs::parse_doc(cx, &foreign_fn.attrs);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let ident = foreign_fn.sig.ident.clone();
+    let ident = Pair {
+        cxx: cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
+    };
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
     let api_function = match lang {
@@ -370,10 +386,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     Ok(api_function(ExternFn {
         lang,
         doc,
-        ident: Pair {
-            cxx: ident.clone(),
-            rust: ident,
-        },
+        ident,
         sig: Signature {
             unsafety,
             fn_token,

From 3bbcdbbbf62c846e2920daa615dbab0a9bc888db Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:22:23 +0000
Subject: [PATCH 1020/2232] Add test of cxx_/rust_name attributes


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cc07752..5cfd97b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -101,6 +101,15 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
         fn set_succeed(&mut self, n: usize) -> Result<usize>;
         fn get_fail(&mut self) -> Result<usize>;
+
+        #[rust_name = "i32_overloaded_method"]
+        fn cOverloadedMethod(&self, x: i32) -> String;
+        #[rust_name = "str_overloaded_method"]
+        fn cOverloadedMethod(&self, x: &str) -> String;
+        #[rust_name = "i32_overloaded_function"]
+        fn cOverloadedFunction(x: i32) -> String;
+        #[rust_name = "str_overloaded_function"]
+        fn cOverloadedFunction(x: &str) -> String;
     }
 
     extern "C" {
@@ -160,6 +169,9 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
+
+        #[cxx_name = "rAliasedFunction"]
+        fn r_aliased_function(x: i32) -> String;
     }
 }
 
@@ -358,3 +370,7 @@ fn r_fail_return_primitive() -> Result<usize, Error> {
 fn r_return_r2(n: usize) -> Box<R2> {
     Box::new(R2(n))
 }
+
+fn r_aliased_function(x: i32) -> String {
+    x.to_string()
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9cb6ed0..3a1a03f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -365,6 +365,22 @@ extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
   return std::unique_ptr<std::string>(new std::string("2020")).release();
 }
 
+rust::String C::cOverloadedMethod(int32_t x) const {
+  return rust::String(std::to_string(x));
+}
+
+rust::String C::cOverloadedMethod(rust::Str x) const {
+  return rust::String(std::string(x));
+}
+
+rust::String cOverloadedFunction(int x) {
+  return rust::String(std::to_string(x));
+}
+
+rust::String cOverloadedFunction(rust::Str x) {
+  return rust::String(std::string(x));
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
@@ -421,6 +437,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
 
+  ASSERT(std::string(rAliasedFunction(2020)) == "2020");
+
   cxx_test_suite_set_correct();
   return nullptr;
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index f3bc2dd..9affe7d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -20,6 +20,8 @@ public:
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
   std::vector<uint8_t> &get_v();
+  rust::String cOverloadedMethod(int32_t x) const;
+  rust::String cOverloadedMethod(rust::Str x) const;
 
 private:
   size_t n;
@@ -101,4 +103,7 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+rust::String cOverloadedFunction(int32_t x);
+rust::String cOverloadedFunction(rust::Str x);
+
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index 9c71bd5..ea29e62 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -181,3 +181,12 @@ extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
 unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
     *r == 2020
 }
+
+#[test]
+fn test_rust_name_attribute() {
+    assert_eq!("2020", ffi::i32_overloaded_function(2020));
+    assert_eq!("2020", ffi::str_overloaded_function("2020"));
+    let unique_ptr = ffi::c_return_unique_ptr();
+    assert_eq!("2020", unique_ptr.i32_overloaded_method(2020));
+    assert_eq!("2020", unique_ptr.str_overloaded_method("2020"));
+}

From df4b677abf6f3711e69f7b7027e7177a2627609f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:30:30 +0000
Subject: [PATCH 1021/2232] Merge pull request #349 from dtolnay/alias


Support functions having distinct Rust name and C++ name
---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 4c76641..4c8a3e5 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -10,6 +10,8 @@ pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,
     pub derives: Option<&'a mut Vec<Derive>>,
     pub repr: Option<&'a mut Option<Atom>>,
+    pub cxx_name: Option<&'a mut Option<Ident>>,
+    pub rust_name: Option<&'a mut Option<Ident>>,
 }
 
 pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
@@ -57,6 +59,26 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("cxx_name") {
+            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(cxx_name) = &mut parser.cxx_name {
+                        **cxx_name = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
+        } else if attr.path.is_ident("rust_name") {
+            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(rust_name) = &mut parser.rust_name {
+                        **rust_name = Some(attr);
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -99,3 +121,13 @@ fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
         "unrecognized repr",
     ))
 }
+
+fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
+    input.parse::<Token![=]>()?;
+    if input.peek(LitStr) {
+        let lit: LitStr = input.parse()?;
+        lit.parse()
+    } else {
+        input.parse()
+    }
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 142d063..367ad05 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -300,6 +300,20 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
         ));
     }
 
+    let mut doc = Doc::new();
+    let mut cxx_name = None;
+    let mut rust_name = None;
+    attrs::parse(
+        cx,
+        &foreign_fn.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
+            ..Default::default()
+        },
+    );
+
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -356,10 +370,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let doc = attrs::parse_doc(cx, &foreign_fn.attrs);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let ident = foreign_fn.sig.ident.clone();
+    let ident = Pair {
+        cxx: cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
+    };
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
     let api_function = match lang {
@@ -370,10 +386,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     Ok(api_function(ExternFn {
         lang,
         doc,
-        ident: Pair {
-            cxx: ident.clone(),
-            rust: ident,
-        },
+        ident,
         sig: Signature {
             unsafety,
             fn_token,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cc07752..5cfd97b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -101,6 +101,15 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
         fn set_succeed(&mut self, n: usize) -> Result<usize>;
         fn get_fail(&mut self) -> Result<usize>;
+
+        #[rust_name = "i32_overloaded_method"]
+        fn cOverloadedMethod(&self, x: i32) -> String;
+        #[rust_name = "str_overloaded_method"]
+        fn cOverloadedMethod(&self, x: &str) -> String;
+        #[rust_name = "i32_overloaded_function"]
+        fn cOverloadedFunction(x: i32) -> String;
+        #[rust_name = "str_overloaded_function"]
+        fn cOverloadedFunction(x: &str) -> String;
     }
 
     extern "C" {
@@ -160,6 +169,9 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
+
+        #[cxx_name = "rAliasedFunction"]
+        fn r_aliased_function(x: i32) -> String;
     }
 }
 
@@ -358,3 +370,7 @@ fn r_fail_return_primitive() -> Result<usize, Error> {
 fn r_return_r2(n: usize) -> Box<R2> {
     Box::new(R2(n))
 }
+
+fn r_aliased_function(x: i32) -> String {
+    x.to_string()
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9cb6ed0..3a1a03f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -365,6 +365,22 @@ extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
   return std::unique_ptr<std::string>(new std::string("2020")).release();
 }
 
+rust::String C::cOverloadedMethod(int32_t x) const {
+  return rust::String(std::to_string(x));
+}
+
+rust::String C::cOverloadedMethod(rust::Str x) const {
+  return rust::String(std::string(x));
+}
+
+rust::String cOverloadedFunction(int x) {
+  return rust::String(std::to_string(x));
+}
+
+rust::String cOverloadedFunction(rust::Str x) {
+  return rust::String(std::string(x));
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
@@ -421,6 +437,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
 
+  ASSERT(std::string(rAliasedFunction(2020)) == "2020");
+
   cxx_test_suite_set_correct();
   return nullptr;
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index f3bc2dd..9affe7d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -20,6 +20,8 @@ public:
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
   std::vector<uint8_t> &get_v();
+  rust::String cOverloadedMethod(int32_t x) const;
+  rust::String cOverloadedMethod(rust::Str x) const;
 
 private:
   size_t n;
@@ -101,4 +103,7 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+rust::String cOverloadedFunction(int32_t x);
+rust::String cOverloadedFunction(rust::Str x);
+
 } // namespace tests
diff --git a/tests/test.rs b/tests/test.rs
index 9c71bd5..ea29e62 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -181,3 +181,12 @@ extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
 unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
     *r == 2020
 }
+
+#[test]
+fn test_rust_name_attribute() {
+    assert_eq!("2020", ffi::i32_overloaded_function(2020));
+    assert_eq!("2020", ffi::str_overloaded_function("2020"));
+    let unique_ptr = ffi::c_return_unique_ptr();
+    assert_eq!("2020", unique_ptr.i32_overloaded_method(2020));
+    assert_eq!("2020", unique_ptr.str_overloaded_method("2020"));
+}

From 9e43a055b69cbdad396b634e057af5c6639c79cb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:30:52 +0000
Subject: [PATCH 1022/2232] Run clippy in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8ec4224..aa8d4a2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -96,3 +96,11 @@ jobs:
           cargo vendor --versioned-dirs --locked third-party/vendor
       - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@clippy
+      - run: cargo clippy --workspace -- -Dclippy::all

From 753b8f743af90feeb66a72ae8be6f31be290e5a3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:30:52 +0000
Subject: [PATCH 1023/2232] Suppress some currently triggering clippy lints


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 7148d7b..128d933 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -46,6 +46,7 @@
 //! ```
 
 #![allow(
+    clippy::drop_copy,
     clippy::inherent_to_string,
     clippy::needless_doctest_main,
     clippy::new_without_default,
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 6456200..dae7e78 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -8,6 +8,12 @@
 //! [https://github.com/google/autocxx]: https://github.com/google/autocxx
 
 #![allow(dead_code)]
+#![allow(
+    clippy::inherent_to_string,
+    clippy::new_without_default,
+    clippy::or_fun_call,
+    clippy::toplevel_ref_arg
+)]
 
 mod error;
 mod gen;

From 61863c637fd265ece9a7d0dc4a2aad39a587087a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:40:11 +0000
Subject: [PATCH 1024/2232] Merge pull request #350 from dtolnay/clippy


Run clippy in CI
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8ec4224..aa8d4a2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -96,3 +96,11 @@ jobs:
           cargo vendor --versioned-dirs --locked third-party/vendor
       - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
+
+  clippy:
+    name: Clippy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: dtolnay/rust-toolchain@clippy
+      - run: cargo clippy --workspace -- -Dclippy::all

From c4dcb91ae6a222173fb211e575c194660933f8ea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:40:42 +0000
Subject: [PATCH 1025/2232] Automatically run cargo vendor from bazel


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aa8d4a2..cf29d25 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,10 +90,6 @@ jobs:
           chmod +x install.sh
           ./install.sh --user
           echo ::add-path::$HOME/bin
-      - name: Vendor dependencies
-        run: |
-          cp third-party/Cargo.lock .
-          cargo vendor --versioned-dirs --locked third-party/vendor
       - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
 
diff --git a/WORKSPACE b/WORKSPACE
index d62b5dd..6093eee 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,4 +1,5 @@
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//tools/bazel:vendor.bzl", "vendor")
 
 http_archive(
     name = "io_bazel_rules_rust",
@@ -34,3 +35,8 @@ rust_repository_set(
     exec_triple = "x86_64-apple-darwin",
     version = "1.47.0",
 )
+
+vendor(
+    name = "third-party",
+    lockfile = "//third-party:Cargo.lock",
+)
diff --git a/third-party/BUILD b/third-party/BUILD
index 49bf512..6303eec 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,5 +1,6 @@
 load(
     "//tools/bazel:rust.bzl",
+    glob = "third_party_glob",
     rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
index 3ef4d91..b7b23e5 100644
--- a/tools/bazel/rust.bzl
+++ b/tools/bazel/rust.bzl
@@ -4,6 +4,10 @@ load(
     _rust_library = "rust_library",
     _rust_test = "rust_test",
 )
+load("@third-party//:vendor.bzl", "vendored")
+
+def third_party_glob(include):
+    return vendored and native.glob(include)
 
 def rust_binary(edition = "2018", **kwargs):
     _rust_binary(edition = edition, **kwargs)
diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
new file mode 100644
index 0000000..e9f10ac
--- /dev/null
+++ b/tools/bazel/vendor.bzl
@@ -0,0 +1,54 @@
+def _impl(repository_ctx):
+    # Link cxx repository into @third-party.
+    lockfile = repository_ctx.path(repository_ctx.attr.lockfile)
+    workspace = lockfile.dirname.dirname
+    repository_ctx.symlink(workspace, "workspace")
+
+    # Copy third-party/Cargo.lock since those are the crate versions that the
+    # BUILD file is written against.
+    vendor_lockfile = repository_ctx.path("workspace/third-party/Cargo.lock")
+    root_lockfile = repository_ctx.path("workspace/Cargo.lock")
+    _copy_file(repository_ctx, src = vendor_lockfile, dst = root_lockfile)
+
+    # Execute cargo vendor.
+    cmd = ["cargo", "vendor", "--versioned-dirs", "third-party/vendor"]
+    result = repository_ctx.execute(
+        cmd,
+        quiet = True,
+        working_directory = "workspace",
+    )
+    _log_cargo_vendor(repository_ctx, result)
+    if result.return_code != 0:
+        fail("failed to execute `{}`".format(" ".join(cmd)))
+
+    # Copy lockfile back to third-party/Cargo.lock to reflect any modification
+    # performed by Cargo.
+    _copy_file(repository_ctx, src = root_lockfile, dst = vendor_lockfile)
+
+    # Produce a token for third_party_glob to depend on so that the necessary
+    # sequencing is visible to Bazel.
+    repository_ctx.file("BUILD", executable = False)
+    repository_ctx.file("vendor.bzl", "vendored = True", executable = False)
+
+def _copy_file(repository_ctx, *, src, dst):
+    content = repository_ctx.read(src)
+    if not dst.exists or content != repository_ctx.read(dst):
+        repository_ctx.file(dst, content = content, executable = False)
+
+def _log_cargo_vendor(repository_ctx, result):
+    relevant = ""
+    for line in result.stderr.splitlines(True):
+        if line.strip() and not line.startswith("To use vendored sources,"):
+            relevant += line
+    if relevant:
+        # Render it as command output.
+        # If we just use print(), Bazel will cache and repeat the output even
+        # when not rerunning the command.
+        print = ["echo", relevant]
+        repository_ctx.execute(print, quiet = False)
+
+vendor = repository_rule(
+    attrs = {"lockfile": attr.label()},
+    local = True,
+    implementation = _impl,
+)

From ba97787b3c33bd126731ec8b57e0bdb6286629d5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 03:48:10 +0000
Subject: [PATCH 1026/2232] Merge pull request #352 from dtolnay/vendor


Automatically run cargo vendor from bazel
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aa8d4a2..cf29d25 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,10 +90,6 @@ jobs:
           chmod +x install.sh
           ./install.sh --user
           echo ::add-path::$HOME/bin
-      - name: Vendor dependencies
-        run: |
-          cp third-party/Cargo.lock .
-          cargo vendor --versioned-dirs --locked third-party/vendor
       - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
 
diff --git a/WORKSPACE b/WORKSPACE
index d62b5dd..6093eee 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,4 +1,5 @@
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("//tools/bazel:vendor.bzl", "vendor")
 
 http_archive(
     name = "io_bazel_rules_rust",
@@ -34,3 +35,8 @@ rust_repository_set(
     exec_triple = "x86_64-apple-darwin",
     version = "1.47.0",
 )
+
+vendor(
+    name = "third-party",
+    lockfile = "//third-party:Cargo.lock",
+)
diff --git a/third-party/BUILD b/third-party/BUILD
index 49bf512..6303eec 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,5 +1,6 @@
 load(
     "//tools/bazel:rust.bzl",
+    glob = "third_party_glob",
     rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
index 3ef4d91..b7b23e5 100644
--- a/tools/bazel/rust.bzl
+++ b/tools/bazel/rust.bzl
@@ -4,6 +4,10 @@ load(
     _rust_library = "rust_library",
     _rust_test = "rust_test",
 )
+load("@third-party//:vendor.bzl", "vendored")
+
+def third_party_glob(include):
+    return vendored and native.glob(include)
 
 def rust_binary(edition = "2018", **kwargs):
     _rust_binary(edition = edition, **kwargs)
diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
new file mode 100644
index 0000000..e9f10ac
--- /dev/null
+++ b/tools/bazel/vendor.bzl
@@ -0,0 +1,54 @@
+def _impl(repository_ctx):
+    # Link cxx repository into @third-party.
+    lockfile = repository_ctx.path(repository_ctx.attr.lockfile)
+    workspace = lockfile.dirname.dirname
+    repository_ctx.symlink(workspace, "workspace")
+
+    # Copy third-party/Cargo.lock since those are the crate versions that the
+    # BUILD file is written against.
+    vendor_lockfile = repository_ctx.path("workspace/third-party/Cargo.lock")
+    root_lockfile = repository_ctx.path("workspace/Cargo.lock")
+    _copy_file(repository_ctx, src = vendor_lockfile, dst = root_lockfile)
+
+    # Execute cargo vendor.
+    cmd = ["cargo", "vendor", "--versioned-dirs", "third-party/vendor"]
+    result = repository_ctx.execute(
+        cmd,
+        quiet = True,
+        working_directory = "workspace",
+    )
+    _log_cargo_vendor(repository_ctx, result)
+    if result.return_code != 0:
+        fail("failed to execute `{}`".format(" ".join(cmd)))
+
+    # Copy lockfile back to third-party/Cargo.lock to reflect any modification
+    # performed by Cargo.
+    _copy_file(repository_ctx, src = root_lockfile, dst = vendor_lockfile)
+
+    # Produce a token for third_party_glob to depend on so that the necessary
+    # sequencing is visible to Bazel.
+    repository_ctx.file("BUILD", executable = False)
+    repository_ctx.file("vendor.bzl", "vendored = True", executable = False)
+
+def _copy_file(repository_ctx, *, src, dst):
+    content = repository_ctx.read(src)
+    if not dst.exists or content != repository_ctx.read(dst):
+        repository_ctx.file(dst, content = content, executable = False)
+
+def _log_cargo_vendor(repository_ctx, result):
+    relevant = ""
+    for line in result.stderr.splitlines(True):
+        if line.strip() and not line.startswith("To use vendored sources,"):
+            relevant += line
+    if relevant:
+        # Render it as command output.
+        # If we just use print(), Bazel will cache and repeat the output even
+        # when not rerunning the command.
+        print = ["echo", relevant]
+        repository_ctx.execute(print, quiet = False)
+
+vendor = repository_rule(
+    attrs = {"lockfile": attr.label()},
+    local = True,
+    implementation = _impl,
+)

From 2e18e5855d6e8b6bb958ea86992cde8205aa1468 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 05:13:48 +0000
Subject: [PATCH 1027/2232] Replace ::add-path with using Environment Files


https://github.com/dtolnay/cxx/issues/351

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cf29d25..916b6da 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -68,7 +68,7 @@ jobs:
           mkdir bin
           wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex # dev branch from 2020.09.21
           chmod +x bin/buck
-          echo ::add-path::bin
+          echo bin >> $GITHUB_PATH
       - name: Install lld
         run: sudo apt install lld
       - name: Vendor dependencies
@@ -89,7 +89,7 @@ jobs:
           wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
-          echo ::add-path::$HOME/bin
+          echo $HOME/bin >> $GITHUB_PATH
       - run: bazel run demo --verbose_failures --noshow_progress
       - run: bazel test ... --verbose_failures --noshow_progress
 

From 957503360bdddce99e7c078ba0ba28ca7cecc859 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 05:17:10 +0000
Subject: [PATCH 1028/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index afc696b..93abbdc 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.42/src/**"]),
+    srcs = glob(["vendor/syn-1.0.43/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 6303eec..f798190 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.42/src/**"]),
+    srcs = glob(["vendor/syn-1.0.43/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6775e06..132a976 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -267,9 +267,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.42"
+version = "1.0.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228"
+checksum = "1e2e59c50ed8f6b050b071aa7b6865293957a9af6b58b94f97c1c9434ad440ea"
 dependencies = [
  "proc-macro2",
  "quote",

From 52830f59d618b670b4afd3f779777c683be13cd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 05:21:27 +0000
Subject: [PATCH 1029/2232] Release 0.5.1


---

diff --git a/Cargo.toml b/Cargo.toml
index 6ee9913..045ecc3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.0" # remember to update html_root_url
+version = "0.5.1" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.0", path = "macro" }
+cxxbridge-macro = { version = "=0.5.1", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.0", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.1", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.0", path = "gen/build" }
+cxx-build = { version = "=0.5.1", path = "gen/build" }
 cxx-gen = { version = "0.5", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index bfaec83..f8e5a7b 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index c6ef927..df6eea0 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b8354f9..99addee 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index ee4052f..18845f8 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9770a5e..1618b0d 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.0"
+version = "0.5.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index aaf4196..7157c0c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.0")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.1")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 132a976..54f250e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -88,7 +88,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -119,11 +119,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.0"
+version = "0.5.1"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.0"
+version = "0.5.1"
 dependencies = [
  "cxx",
  "proc-macro2",

From 121cca4a06788281738ff79ec376adeb5f1c8eb3 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 10 2020 23:01:26 +0000
Subject: [PATCH 1030/2232] Add tests for ExternType.


---

diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index e583944..4b2cbdf 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "module.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
new file mode 100644
index 0000000..cd6ffe8
--- /dev/null
+++ b/tests/ffi/extra.rs
@@ -0,0 +1,35 @@
+// Separate mod so that &self in the lib.rs mod
+// has an unambiguous receiver.
+// At the moment, the cxx C++ codegen can't convert
+// more than one cxx::bridge mod per file, so that's why
+// we need to put this outside of lib.rs.
+// All of this could go into module.rs instead, but
+// for now its purpose is narrowly scoped for testing
+// aliasing between cxx::bridge mods, so we'll keep it that
+// way and start a new mod here.
+
+// Rustfmt mangles the extern type alias.
+// https://github.com/rust-lang/rustfmt/issues/4159
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi2 {
+
+    impl UniquePtr<D> {}
+    impl UniquePtr<E> {}
+
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        type D = crate::other::D;
+        type E = crate::other::E;
+
+        fn c_take_trivial_ptr(d: UniquePtr<D>);
+        fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial(d: D);
+        fn c_take_opaque_ptr(e: UniquePtr<E>);
+        fn c_take_opaque_ref(e: &E);
+        fn c_return_trivial_ptr() -> UniquePtr<D>;
+        fn c_return_trivial() -> D;
+        fn c_return_opaque_ptr() -> UniquePtr<E>;
+    }
+}
\ No newline at end of file
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5cfd97b..a0a2a73 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -5,10 +5,37 @@
 )]
 
 pub mod module;
+pub mod extra;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
+mod other {
+    use cxx::kind::{Opaque, Trivial};
+    use cxx::{type_id, CxxString, ExternType};
+
+    #[repr(C)]
+    pub struct D {
+        d: u64,
+    }
+
+    #[repr(C)]
+    pub struct E {
+        e: u64,
+        e_str: CxxString,
+    }
+
+    unsafe impl ExternType for D {
+        type Id = type_id!("tests::D");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for E {
+        type Id = type_id!("tests::E");
+        type Kind = Opaque;
+    }
+}
+
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     #[derive(Clone)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3a1a03f..983cf95 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -4,6 +4,8 @@
 #include <iterator>
 #include <numeric>
 #include <stdexcept>
+#include <memory>
+#include <string>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -381,6 +383,54 @@ rust::String cOverloadedFunction(rust::Str x) {
   return rust::String(std::string(x));
 }
 
+void c_take_trivial_ptr(std::unique_ptr<D> d) {
+  if (d->d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ref(const D& d) {
+  if (d.d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+void c_take_trivial(D d) {
+  if (d.d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_opaque_ptr(std::unique_ptr<E> e) {
+  if (e->e == 40) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_opaque_ref(const E& e) {
+  if (e.e == 40 && e.e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+std::unique_ptr<D> c_return_trivial_ptr() {
+  auto d = std::unique_ptr<D>(new D());
+  d->d = 30;
+  return d;
+}
+
+D c_return_trivial() {
+  D d;
+  d.d = 30;
+  return d;
+}
+
+std::unique_ptr<E> c_return_opaque_ptr() {
+  auto e = std::unique_ptr<E>(new E());
+  e->e = 40;
+  e->e_str = std::string("hello");
+  return e;
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 9affe7d..b3f547e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -28,6 +28,15 @@ private:
   std::vector<uint8_t> v;
 };
 
+struct D {
+  uint64_t d;
+};
+
+struct E {
+  uint64_t e;
+  std::string e_str;
+};
+
 enum COwnedEnum {
   CVal1,
   CVal2,
@@ -103,6 +112,15 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+void c_take_trivial_ptr(std::unique_ptr<D> d);
+void c_take_trivial_ref(const D& d);
+void c_take_trivial(D d);
+void c_take_opaque_ptr(std::unique_ptr<E> e);
+void c_take_opaque_ref(const E& e);
+std::unique_ptr<D> c_return_trivial_ptr();
+D c_return_trivial();
+std::unique_ptr<E> c_return_opaque_ptr();
+
 rust::String cOverloadedFunction(int32_t x);
 rust::String cOverloadedFunction(rust::Str x);
 
diff --git a/tests/test.rs b/tests/test.rs
index ea29e62..9828429 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,4 +1,5 @@
 use cxx_test_suite::ffi;
+use cxx_test_suite::extra::ffi2;
 use std::cell::Cell;
 use std::ffi::CStr;
 
@@ -190,3 +191,19 @@ fn test_rust_name_attribute() {
     assert_eq!("2020", unique_ptr.i32_overloaded_method(2020));
     assert_eq!("2020", unique_ptr.str_overloaded_method("2020"));
 }
+
+#[test]
+fn test_extern_trivial() {
+    let d = ffi2::c_return_trivial();
+    check!(ffi2::c_take_trivial_ref(&d));
+    check!(ffi2::c_take_trivial(d));
+    let d = ffi2::c_return_trivial_ptr();
+    check!(ffi2::c_take_trivial_ptr(d));
+}
+
+#[test]
+fn test_extern_opaque() {
+    let e = ffi2::c_return_opaque_ptr();
+    check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
+    check!(ffi2::c_take_opaque_ptr(e));
+}

From 1931ccf65e1ff79376cba8276dbbe88c35ddc730 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 10 2020 23:19:20 +0000
Subject: [PATCH 1031/2232] Attempt at BUCK and BUILD files.


---

diff --git a/tests/BUCK b/tests/BUCK
index f066542..6ad9f90 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -9,6 +9,7 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
+        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -25,6 +26,7 @@ cxx_library(
         "ffi/tests.cc",
         ":bridge/source",
         ":module/source",
+        ":extra/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -42,3 +44,8 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
+
+rust_cxx_bridge(
+    name = "extra",
+    src = "ffi/extra.rs",
+)
diff --git a/tests/BUILD b/tests/BUILD
index 1345a7a..4dff0a0 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -12,6 +12,7 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
+        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -27,6 +28,7 @@ cc_library(
         "ffi/tests.cc",
         ":bridge/source",
         ":module/source",
+        ":extra/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -46,3 +48,9 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
+
+rust_cxx_bridge(
+    name = "extra",
+    src = "ffi/extra.rs",
+    deps = [":impl"],
+)

From 2fe955f4214a651af8ed76a0df94274d839d9cee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 23:26:58 +0000
Subject: [PATCH 1032/2232] Merge pull request #356 from adetaylor/add-some-tests


Add tests for ExternType.
---

diff --git a/tests/BUCK b/tests/BUCK
index f066542..6ad9f90 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -9,6 +9,7 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
+        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -25,6 +26,7 @@ cxx_library(
         "ffi/tests.cc",
         ":bridge/source",
         ":module/source",
+        ":extra/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -42,3 +44,8 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
+
+rust_cxx_bridge(
+    name = "extra",
+    src = "ffi/extra.rs",
+)
diff --git a/tests/BUILD b/tests/BUILD
index 1345a7a..4dff0a0 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -12,6 +12,7 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
+        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -27,6 +28,7 @@ cc_library(
         "ffi/tests.cc",
         ":bridge/source",
         ":module/source",
+        ":extra/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -46,3 +48,9 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
+
+rust_cxx_bridge(
+    name = "extra",
+    src = "ffi/extra.rs",
+    deps = [":impl"],
+)
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index e583944..4b2cbdf 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "module.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
new file mode 100644
index 0000000..cd6ffe8
--- /dev/null
+++ b/tests/ffi/extra.rs
@@ -0,0 +1,35 @@
+// Separate mod so that &self in the lib.rs mod
+// has an unambiguous receiver.
+// At the moment, the cxx C++ codegen can't convert
+// more than one cxx::bridge mod per file, so that's why
+// we need to put this outside of lib.rs.
+// All of this could go into module.rs instead, but
+// for now its purpose is narrowly scoped for testing
+// aliasing between cxx::bridge mods, so we'll keep it that
+// way and start a new mod here.
+
+// Rustfmt mangles the extern type alias.
+// https://github.com/rust-lang/rustfmt/issues/4159
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi2 {
+
+    impl UniquePtr<D> {}
+    impl UniquePtr<E> {}
+
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        type D = crate::other::D;
+        type E = crate::other::E;
+
+        fn c_take_trivial_ptr(d: UniquePtr<D>);
+        fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial(d: D);
+        fn c_take_opaque_ptr(e: UniquePtr<E>);
+        fn c_take_opaque_ref(e: &E);
+        fn c_return_trivial_ptr() -> UniquePtr<D>;
+        fn c_return_trivial() -> D;
+        fn c_return_opaque_ptr() -> UniquePtr<E>;
+    }
+}
\ No newline at end of file
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5cfd97b..a0a2a73 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -5,10 +5,37 @@
 )]
 
 pub mod module;
+pub mod extra;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
+mod other {
+    use cxx::kind::{Opaque, Trivial};
+    use cxx::{type_id, CxxString, ExternType};
+
+    #[repr(C)]
+    pub struct D {
+        d: u64,
+    }
+
+    #[repr(C)]
+    pub struct E {
+        e: u64,
+        e_str: CxxString,
+    }
+
+    unsafe impl ExternType for D {
+        type Id = type_id!("tests::D");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for E {
+        type Id = type_id!("tests::E");
+        type Kind = Opaque;
+    }
+}
+
 #[cxx::bridge(namespace = tests)]
 pub mod ffi {
     #[derive(Clone)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3a1a03f..983cf95 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -4,6 +4,8 @@
 #include <iterator>
 #include <numeric>
 #include <stdexcept>
+#include <memory>
+#include <string>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -381,6 +383,54 @@ rust::String cOverloadedFunction(rust::Str x) {
   return rust::String(std::string(x));
 }
 
+void c_take_trivial_ptr(std::unique_ptr<D> d) {
+  if (d->d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ref(const D& d) {
+  if (d.d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+void c_take_trivial(D d) {
+  if (d.d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_opaque_ptr(std::unique_ptr<E> e) {
+  if (e->e == 40) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_opaque_ref(const E& e) {
+  if (e.e == 40 && e.e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+std::unique_ptr<D> c_return_trivial_ptr() {
+  auto d = std::unique_ptr<D>(new D());
+  d->d = 30;
+  return d;
+}
+
+D c_return_trivial() {
+  D d;
+  d.d = 30;
+  return d;
+}
+
+std::unique_ptr<E> c_return_opaque_ptr() {
+  auto e = std::unique_ptr<E>(new E());
+  e->e = 40;
+  e->e_str = std::string("hello");
+  return e;
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 9affe7d..b3f547e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -28,6 +28,15 @@ private:
   std::vector<uint8_t> v;
 };
 
+struct D {
+  uint64_t d;
+};
+
+struct E {
+  uint64_t e;
+  std::string e_str;
+};
+
 enum COwnedEnum {
   CVal1,
   CVal2,
@@ -103,6 +112,15 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+void c_take_trivial_ptr(std::unique_ptr<D> d);
+void c_take_trivial_ref(const D& d);
+void c_take_trivial(D d);
+void c_take_opaque_ptr(std::unique_ptr<E> e);
+void c_take_opaque_ref(const E& e);
+std::unique_ptr<D> c_return_trivial_ptr();
+D c_return_trivial();
+std::unique_ptr<E> c_return_opaque_ptr();
+
 rust::String cOverloadedFunction(int32_t x);
 rust::String cOverloadedFunction(rust::Str x);
 
diff --git a/tests/test.rs b/tests/test.rs
index ea29e62..9828429 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,4 +1,5 @@
 use cxx_test_suite::ffi;
+use cxx_test_suite::extra::ffi2;
 use std::cell::Cell;
 use std::ffi::CStr;
 
@@ -190,3 +191,19 @@ fn test_rust_name_attribute() {
     assert_eq!("2020", unique_ptr.i32_overloaded_method(2020));
     assert_eq!("2020", unique_ptr.str_overloaded_method("2020"));
 }
+
+#[test]
+fn test_extern_trivial() {
+    let d = ffi2::c_return_trivial();
+    check!(ffi2::c_take_trivial_ref(&d));
+    check!(ffi2::c_take_trivial(d));
+    let d = ffi2::c_return_trivial_ptr();
+    check!(ffi2::c_take_trivial_ptr(d));
+}
+
+#[test]
+fn test_extern_opaque() {
+    let e = ffi2::c_return_opaque_ptr();
+    check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
+    check!(ffi2::c_take_opaque_ptr(e));
+}

From 362c9f92b0703cd205a55bb5b9d687df4cc3ad59 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 10 2020 23:30:04 +0000
Subject: [PATCH 1033/2232] Touch up PR 356


---

diff --git a/tests/BUCK b/tests/BUCK
index 6ad9f90..0ddf1a8 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -25,8 +25,8 @@ cxx_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":module/source",
         ":extra/source",
+        ":module/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -41,11 +41,11 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "module",
-    src = "ffi/module.rs",
+    name = "extra",
+    src = "ffi/extra.rs",
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
+    name = "module",
+    src = "ffi/module.rs",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 4dff0a0..233926b 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -27,8 +27,8 @@ cc_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":module/source",
         ":extra/source",
+        ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -44,13 +44,13 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "module",
-    src = "ffi/module.rs",
+    name = "extra",
+    src = "ffi/extra.rs",
     deps = [":impl"],
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
+    name = "module",
+    src = "ffi/module.rs",
     deps = [":impl"],
 )
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index cd6ffe8..a809ea4 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -1,19 +1,15 @@
-// Separate mod so that &self in the lib.rs mod
-// has an unambiguous receiver.
-// At the moment, the cxx C++ codegen can't convert
-// more than one cxx::bridge mod per file, so that's why
-// we need to put this outside of lib.rs.
-// All of this could go into module.rs instead, but
-// for now its purpose is narrowly scoped for testing
-// aliasing between cxx::bridge mods, so we'll keep it that
-// way and start a new mod here.
+// Separate mod so that &self in the lib.rs mod has an unambiguous receiver. At
+// the moment, the cxx C++ codegen can't convert more than one cxx::bridge mod
+// per file, so that's why we need to put this outside of lib.rs. All of this
+// could go into module.rs instead, but for now its purpose is narrowly scoped
+// for testing aliasing between cxx::bridge mods, so we'll keep it that way and
+// start a new mod here.
 
 // Rustfmt mangles the extern type alias.
 // https://github.com/rust-lang/rustfmt/issues/4159
 #[rustfmt::skip]
 #[cxx::bridge(namespace = tests)]
 pub mod ffi2 {
-
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
 
@@ -32,4 +28,4 @@ pub mod ffi2 {
         fn c_return_trivial() -> D;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index a0a2a73..7cffded 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,8 +4,8 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
-pub mod module;
 pub mod extra;
+pub mod module;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
diff --git a/tests/test.rs b/tests/test.rs
index 9828429..a9cd8e1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,5 +1,5 @@
-use cxx_test_suite::ffi;
 use cxx_test_suite::extra::ffi2;
+use cxx_test_suite::ffi;
 use std::cell::Cell;
 use std::ffi::CStr;
 

From 65b66f2091b144ca255bcad0bdf442d483e10a4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 09:36:16 +0000
Subject: [PATCH 1034/2232] Factor out common symlink check build script


---

diff --git a/gen/build/build.rs b/gen/build/build.rs
index b8ff9dd..c53bef7 100644
--- a/gen/build/build.rs
+++ b/gen/build/build.rs
@@ -1,29 +1 @@
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-const NOSYMLINK: &str = "
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When building `cxx` from a git clone, git's symlink support needs
-to be enabled on platforms that have it off by default (Windows).
-Either use:
-
-   $ git config --global core.symlinks true
-
-prior to cloning, or else use:
-
-   $ git clone -c core.symlinks=true ...
-
-for the clone.
-
-Symlinks are only required for local development, not for building
-`cxx` as a (possibly transitive) dependency from crates.io.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-";
-
-fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
-    }
-}
+include!("../../tools/cargo/build.rs");
diff --git a/gen/cmd/build.rs b/gen/cmd/build.rs
index b8ff9dd..c53bef7 100644
--- a/gen/cmd/build.rs
+++ b/gen/cmd/build.rs
@@ -1,29 +1 @@
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-const NOSYMLINK: &str = "
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When building `cxx` from a git clone, git's symlink support needs
-to be enabled on platforms that have it off by default (Windows).
-Either use:
-
-   $ git config --global core.symlinks true
-
-prior to cloning, or else use:
-
-   $ git clone -c core.symlinks=true ...
-
-for the clone.
-
-Symlinks are only required for local development, not for building
-`cxx` as a (possibly transitive) dependency from crates.io.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-";
-
-fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
-    }
-}
+include!("../../tools/cargo/build.rs");
diff --git a/gen/lib/build.rs b/gen/lib/build.rs
index b8ff9dd..c53bef7 100644
--- a/gen/lib/build.rs
+++ b/gen/lib/build.rs
@@ -1,29 +1 @@
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-const NOSYMLINK: &str = "
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When building `cxx` from a git clone, git's symlink support needs
-to be enabled on platforms that have it off by default (Windows).
-Either use:
-
-   $ git config --global core.symlinks true
-
-prior to cloning, or else use:
-
-   $ git clone -c core.symlinks=true ...
-
-for the clone.
-
-Symlinks are only required for local development, not for building
-`cxx` as a (possibly transitive) dependency from crates.io.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-";
-
-fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
-    }
-}
+include!("../../tools/cargo/build.rs");
diff --git a/macro/build.rs b/macro/build.rs
index b8ff9dd..927f72b 100644
--- a/macro/build.rs
+++ b/macro/build.rs
@@ -1,29 +1 @@
-use std::io::{self, Write};
-use std::path::Path;
-use std::process;
-
-const NOSYMLINK: &str = "
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When building `cxx` from a git clone, git's symlink support needs
-to be enabled on platforms that have it off by default (Windows).
-Either use:
-
-   $ git config --global core.symlinks true
-
-prior to cloning, or else use:
-
-   $ git clone -c core.symlinks=true ...
-
-for the clone.
-
-Symlinks are only required for local development, not for building
-`cxx` as a (possibly transitive) dependency from crates.io.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-";
-
-fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
-    }
-}
+include!("../tools/cargo/build.rs");
diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
new file mode 100644
index 0000000..b8ff9dd
--- /dev/null
+++ b/tools/cargo/build.rs
@@ -0,0 +1,29 @@
+use std::io::{self, Write};
+use std::path::Path;
+use std::process;
+
+const NOSYMLINK: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone, git's symlink support needs
+to be enabled on platforms that have it off by default (Windows).
+Either use:
+
+   $ git config --global core.symlinks true
+
+prior to cloning, or else use:
+
+   $ git clone -c core.symlinks=true ...
+
+for the clone.
+
+Symlinks are only required for local development, not for building
+`cxx` as a (possibly transitive) dependency from crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
+fn main() {
+    if !Path::new("src/syntax/mod.rs").exists() {
+        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
+        process::exit(1);
+    }
+}

From 188d9f1256e6a46b4088599ed8bcbf6999479dce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 09:37:51 +0000
Subject: [PATCH 1035/2232] Display usable clone command on symlink error


---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index b8ff9dd..c0a94bc 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -12,7 +12,7 @@ Either use:
 
 prior to cloning, or else use:
 
-   $ git clone -c core.symlinks=true ...
+   $ git clone -c core.symlinks=true https://github.com/dtolnay/cxx
 
 for the clone.
 

From a00021934eebadf240862946bac9e75d52ea0d0c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 10:10:34 +0000
Subject: [PATCH 1036/2232] Emphasize difference between git builds vs crates.io


---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index c0a94bc..4f2eb8e 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -16,8 +16,10 @@ prior to cloning, or else use:
 
 for the clone.
 
-Symlinks are only required for local development, not for building
-`cxx` as a (possibly transitive) dependency from crates.io.
+Symlinks are only required when compiling locally from a clone of
+the git repository---they are NOT required when building `cxx` as
+a Cargo-managed (possibly transitive) build dependency downloaded
+through crates.io.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ";
 

From c9c197bff912456f1cb09a047cb2b0960e891458 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 10:49:37 +0000
Subject: [PATCH 1037/2232] Try to detect symlinking disabled on Windows


---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index 4f2eb8e..f6ec026 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -1,8 +1,12 @@
 use std::io::{self, Write};
+#[cfg(windows)]
+use std::os::windows::fs as windows;
 use std::path::Path;
 use std::process;
+#[cfg(windows)]
+use std::{env, fs};
 
-const NOSYMLINK: &str = "
+const MISSING: &str = "
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 When building `cxx` from a git clone, git's symlink support needs
 to be enabled on platforms that have it off by default (Windows).
@@ -23,9 +27,46 @@ through crates.io.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ";
 
+#[cfg(windows)]
+const DENIED: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone on Windows we need Developer
+Mode enabled for symlink support.
+
+To enable Developer Mode: go under Settings to Update & Security,
+then 'For developers', and turn on the toggle for Developer Mode.
+
+For more explanation of symlinks in Windows, see these resources:
+> https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/
+> https://docs.microsoft.com/windows/uwp/get-started/enable-your-device-for-development
+
+Symlinks are only required when compiling locally from a clone of
+the git repository---they are NOT required when building `cxx` as
+a Cargo-managed (possibly transitive) build dependency downloaded
+through crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
 fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
+    if Path::new("src/syntax/mod.rs").exists() {
+        return;
     }
+
+    #[allow(unused_mut)]
+    let mut message = MISSING;
+
+    #[cfg(windows)]
+    if let Some(out_dir) = env::var_os("OUT_DIR") {
+        let parent_dir = Path::new(&out_dir).join("symlink");
+        let from_dir = parent_dir.join("from");
+        let to_dir = parent_dir.join("to");
+        if fs::create_dir_all(&from_dir).is_ok()
+            && windows::symlink_dir(&from_dir, &to_dir).is_err()
+        {
+            message = DENIED;
+        }
+    }
+
+    let _ = io::stderr().write_all(message.as_bytes());
+    process::exit(1);
 }

From 2a0a80a260527d509b827107bdb41624c29d2996 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 10:49:37 +0000
Subject: [PATCH 1038/2232] Raise minimum supported Rust version to 1.43


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 916b6da..b7cad53 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -45,14 +45,6 @@ jobs:
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
 
-  msrv:
-    name: Rust 1.42.0
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@1.42.0
-      - run: cargo run --manifest-path demo/Cargo.toml
-
   buck:
     name: Buck
     runs-on: ubuntu-latest
diff --git a/README.md b/README.md
index 7171724..7906020 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ cxx = "0.5"
 cxx-build = "0.5"
 ```
 
-*Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
+*Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
 *[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
diff --git a/src/lib.rs b/src/lib.rs
index 7157c0c..efd3fbc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.42+ and c++11 or newer*<br>
+//! *Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
 //! *[Release notes](https://github.com/dtolnay/cxx/releases)*
 //!
 //! <br>

From 251e99384f0ebe98150b24b907af346a41b0453e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 11 2020 10:56:41 +0000
Subject: [PATCH 1039/2232] Merge pull request #358 from dtolnay/symlink


Try to detect symlinking disabled on Windows
---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index 4f2eb8e..f6ec026 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -1,8 +1,12 @@
 use std::io::{self, Write};
+#[cfg(windows)]
+use std::os::windows::fs as windows;
 use std::path::Path;
 use std::process;
+#[cfg(windows)]
+use std::{env, fs};
 
-const NOSYMLINK: &str = "
+const MISSING: &str = "
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 When building `cxx` from a git clone, git's symlink support needs
 to be enabled on platforms that have it off by default (Windows).
@@ -23,9 +27,46 @@ through crates.io.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ";
 
+#[cfg(windows)]
+const DENIED: &str = "
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When building `cxx` from a git clone on Windows we need Developer
+Mode enabled for symlink support.
+
+To enable Developer Mode: go under Settings to Update & Security,
+then 'For developers', and turn on the toggle for Developer Mode.
+
+For more explanation of symlinks in Windows, see these resources:
+> https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/
+> https://docs.microsoft.com/windows/uwp/get-started/enable-your-device-for-development
+
+Symlinks are only required when compiling locally from a clone of
+the git repository---they are NOT required when building `cxx` as
+a Cargo-managed (possibly transitive) build dependency downloaded
+through crates.io.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+";
+
 fn main() {
-    if !Path::new("src/syntax/mod.rs").exists() {
-        let _ = io::stderr().lock().write_all(NOSYMLINK.as_bytes());
-        process::exit(1);
+    if Path::new("src/syntax/mod.rs").exists() {
+        return;
     }
+
+    #[allow(unused_mut)]
+    let mut message = MISSING;
+
+    #[cfg(windows)]
+    if let Some(out_dir) = env::var_os("OUT_DIR") {
+        let parent_dir = Path::new(&out_dir).join("symlink");
+        let from_dir = parent_dir.join("from");
+        let to_dir = parent_dir.join("to");
+        if fs::create_dir_all(&from_dir).is_ok()
+            && windows::symlink_dir(&from_dir, &to_dir).is_err()
+        {
+            message = DENIED;
+        }
+    }
+
+    let _ = io::stderr().write_all(message.as_bytes());
+    process::exit(1);
 }

From ccde860981e865972c458371b6de1d756ebeb0fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 12 2020 00:53:50 +0000
Subject: [PATCH 1040/2232] Tweak target dir finding heuristic


---

diff --git a/gen/build/src/cargo.rs b/gen/build/src/cargo.rs
deleted file mode 100644
index 18b6b6f..0000000
--- a/gen/build/src/cargo.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-use crate::paths::TargetDir;
-use std::env;
-use std::path::{Path, PathBuf};
-use std::process::Command;
-use std::str;
-
-pub(crate) fn target_dir(out_dir: &Path) -> TargetDir {
-    try_target_dir(out_dir).map_or(TargetDir::Unknown, TargetDir::Path)
-}
-
-fn try_target_dir(out_dir: &Path) -> Option<PathBuf> {
-    if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
-        let target_dir = PathBuf::from(target_dir);
-        if target_dir.is_absolute() {
-            return Some(target_dir);
-        } else {
-            return None;
-        };
-    }
-
-    let cargo = option_env!("CARGO").unwrap_or("cargo");
-    let output = Command::new(cargo)
-        .current_dir(out_dir)
-        .arg("metadata")
-        .arg("--no-deps")
-        .arg("--format-version=1")
-        .output()
-        .ok()?;
-
-    // Cargo only outputs utf8 encoded JSON.
-    let mut metadata = str::from_utf8(&output.stdout).ok()?;
-
-    let key_pattern = "\"target_directory\":";
-    let key_index = metadata.rfind(key_pattern)?;
-    metadata = &metadata[key_index + key_pattern.len()..];
-    let open_quote_index = metadata.find('"')?;
-    metadata = &metadata[open_quote_index + 1..];
-    let close_quote_index = metadata.find('"')?;
-    let string = &metadata[..close_quote_index];
-    let target_directory = string.replace("\\\\", "\\");
-    Some(PathBuf::from(target_directory))
-}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 128d933..e6de985 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -54,18 +54,19 @@
     clippy::toplevel_ref_arg
 )]
 
-mod cargo;
 mod cfg;
 mod error;
 mod gen;
 mod out;
 mod paths;
 mod syntax;
+mod target;
 
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
-use crate::paths::{PathExt, TargetDir};
+use crate::paths::PathExt;
+use crate::target::TargetDir;
 use cc::Build;
 use std::collections::BTreeMap;
 use std::env;
@@ -135,13 +136,7 @@ impl Project {
         let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
-        let target_dir = match cargo::target_dir(&out_dir) {
-            target_dir @ TargetDir::Path(_) => target_dir,
-            // Fallback if Cargo did not work.
-            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
-        };
-
-        let shared_dir = match target_dir {
+        let shared_dir = match target::find_target_dir(&out_dir) {
             TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
             TargetDir::Unknown => scratch::path("cxxbridge"),
         };
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 56c0018..4459363 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -3,11 +3,6 @@ use crate::gen::fs;
 use std::ffi::OsStr;
 use std::path::{Component, Path, PathBuf};
 
-pub(crate) enum TargetDir {
-    Path(PathBuf),
-    Unknown,
-}
-
 pub(crate) fn manifest_dir() -> Result<PathBuf> {
     crate::env_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
 }
@@ -44,34 +39,6 @@ impl PathExt for Path {
     }
 }
 
-pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
-    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
-    // handle in includes.
-    // https://github.com/rust-lang/rust/issues/42869
-    // https://github.com/alexcrichton/cc-rs/issues/169
-    let mut also_try_canonical = cfg!(not(windows));
-
-    let mut dir = out_dir.to_owned();
-    loop {
-        let is_target = dir.ends_with("target");
-        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
-        if is_target && parent_contains_cargo_toml {
-            return TargetDir::Path(dir);
-        }
-        if dir.pop() {
-            continue;
-        }
-        if also_try_canonical {
-            if let Ok(canonical_dir) = out_dir.canonicalize() {
-                dir = canonical_dir;
-                also_try_canonical = false;
-                continue;
-            }
-        }
-        return TargetDir::Unknown;
-    }
-}
-
 #[cfg(unix)]
 pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
diff --git a/gen/build/src/target.rs b/gen/build/src/target.rs
new file mode 100644
index 0000000..58ada3a
--- /dev/null
+++ b/gen/build/src/target.rs
@@ -0,0 +1,42 @@
+use std::env;
+use std::path::{Path, PathBuf};
+
+pub(crate) enum TargetDir {
+    Path(PathBuf),
+    Unknown,
+}
+
+pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
+    if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") {
+        let target_dir = PathBuf::from(target_dir);
+        if target_dir.is_absolute() {
+            return TargetDir::Path(target_dir);
+        } else {
+            return TargetDir::Unknown;
+        };
+    }
+
+    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
+    // handle in includes.
+    // https://github.com/rust-lang/rust/issues/42869
+    // https://github.com/alexcrichton/cc-rs/issues/169
+    let mut also_try_canonical = cfg!(not(windows));
+
+    let mut dir = out_dir.to_owned();
+    loop {
+        if dir.join(".rustc_info.json").exists() || dir.join("CACHEDIR.TAG").exists() {
+            return TargetDir::Path(dir);
+        }
+        if dir.pop() {
+            continue;
+        }
+        if also_try_canonical {
+            if let Ok(canonical_dir) = out_dir.canonicalize() {
+                dir = canonical_dir;
+                also_try_canonical = false;
+                continue;
+            }
+        }
+        return TargetDir::Unknown;
+    }
+}

From 9e457018915999ca26b372e9291a0793f0b5fdaa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 12 2020 04:55:48 +0000
Subject: [PATCH 1041/2232] Set default flavor of buck rust library build operations


Previously e.g. `buck build :cxx` was surprisingly a no-op, requiring
one to build `:cxx#check` or `:cxx#rlib-pic` in order to perform any
compiler invocation at all.

defaults.rust_library.type is a recent feature (landed in facebook/buck@c425eb93e1d4aa7768e40a7bccf8601698c5cddd),
hence the bump of the Buck commit pulled in for CI.

---

diff --git a/.buckconfig b/.buckconfig
index 3e5092d..5c6c995 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -18,3 +18,6 @@
       -Clink-arg=-fuse-ld=lld \
       -Crelocation-model=dynamic-no-pic \
       --cap-lints=allow
+
+[defaults.rust_library]
+  type = check
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b7cad53..50c9b65 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -58,7 +58,7 @@ jobs:
       - name: Install Buck
         run: |
           mkdir bin
-          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex # dev branch from 2020.09.21
+          wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex # dev branch from 2020.10.11
           chmod +x bin/buck
           echo bin >> $GITHUB_PATH
       - name: Install lld

From bd03ae4cd1d9e75ba611e1a02761a50f26335b97 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 12 2020 05:30:28 +0000
Subject: [PATCH 1042/2232] Update buck in devcontainer to match Actions


---

diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
index d4ab609..6085459 100644
--- a/.devcontainer/build.Dockerfile
+++ b/.devcontainer/build.Dockerfile
@@ -6,7 +6,7 @@ RUN apt-get update \
     && rustup default nightly 2>&1 \
     && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
     && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
-    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/891556d066/buck-891556d066-java11.pex \
+    && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex \
     && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
     && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
     && chmod +x bin/install-bazel bin/buck bin/buildifier \

From e35673d7debe16222c1667131e51969c093e225c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 12 2020 05:31:51 +0000
Subject: [PATCH 1043/2232] Add VS Code C++ tools


---

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index fef25d4..b8deba2 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -14,6 +14,7 @@
     "extensions": [
         "BazelBuild.vscode-bazel",
         "matklad.rust-analyzer",
+        "ms-vscode.cpptools",
         "vadimcn.vscode-lldb"
     ]
 }

From d75f7e2911f761ee792bc631fac70da18eff0bbd Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 12 2020 23:16:19 +0000
Subject: [PATCH 1044/2232] Allow creation of UniquePtrs to trivial aliased types.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5d47c63..3cd94d1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1245,7 +1245,12 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     let instance = to_mangled(&out.namespace, ty);
 
     let can_construct_from_value = match ty {
-        Type::Ident(ident) => types.structs.contains_key(ident),
+        // Some aliases are to opaque types; some are to trivial types.
+        // We can't know at code generation time, so we generate both C++
+        // and Rust side bindings for a "new" method anyway. But that
+        // Rust code will explode at runtime if anyone tries to call it on
+        // an opaque type.
+        Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
         _ => false,
     };
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6fa7ea7..4213b4d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -814,13 +814,22 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) {
+    let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
+        let trivial_assertion: Option<syn::Stmt> = if types.aliases.contains_key(ident) {
+            Some(parse_quote! {
+               < < #ident as :: cxx :: ExternType > :: Kind as :: cxx :: kind :: Kind > :: assert_trivial();
+            })
+        } else {
+            None
+        };
+
         Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
                     fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
                 }
+                #trivial_assertion
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 unsafe { __new(&mut repr, &mut value) }
                 repr
diff --git a/src/extern_type.rs b/src/extern_type.rs
index b9c5386..45414c8 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -165,9 +165,17 @@ pub mod kind {
     /// indirection.
     pub enum Trivial {}
 
-    pub trait Kind: private::Sealed {}
-    impl Kind for Opaque {}
-    impl Kind for Trivial {}
+    pub trait Kind: private::Sealed {
+        fn assert_trivial();
+    }
+    impl Kind for Opaque {
+        fn assert_trivial() {
+            panic!("Type not trivial");
+        }
+    }
+    impl Kind for Trivial {
+        fn assert_trivial() {}
+    }
 }
 
 mod private {
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index a809ea4..6209702 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -12,12 +12,14 @@
 pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
+    impl UniquePtr<F> {}
 
     extern "C" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
         type E = crate::other::E;
+        type F = crate::other::F;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7cffded..f80cda7 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -14,15 +14,23 @@ mod other {
     use cxx::kind::{Opaque, Trivial};
     use cxx::{type_id, CxxString, ExternType};
 
+    // Trivial.
     #[repr(C)]
     pub struct D {
-        d: u64,
+        pub d: u64,
     }
 
+    // Opaque, and has realistic complexity.
     #[repr(C)]
     pub struct E {
-        e: u64,
         e_str: CxxString,
+        e: u64,
+    }
+
+    // Opaque, but simple enough that bad code can try to create it.
+    #[repr(C)]
+    pub struct F {
+        pub f: u64,
     }
 
     unsafe impl ExternType for D {
@@ -34,6 +42,11 @@ mod other {
         type Id = type_id!("tests::E");
         type Kind = Opaque;
     }
+
+    unsafe impl ExternType for F {
+        type Id = type_id!("tests::F");
+        type Kind = Opaque;
+    }
 }
 
 #[cxx::bridge(namespace = tests)]
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index b3f547e..ff1fbd3 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -37,6 +37,10 @@ struct E {
   std::string e_str;
 };
 
+struct F {
+  uint64_t f;
+};
+
 enum COwnedEnum {
   CVal1,
   CVal2,
diff --git a/tests/test.rs b/tests/test.rs
index a9cd8e1..3ea02fa 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -199,6 +199,7 @@ fn test_extern_trivial() {
     check!(ffi2::c_take_trivial(d));
     let d = ffi2::c_return_trivial_ptr();
     check!(ffi2::c_take_trivial_ptr(d));
+    cxx::UniquePtr::new(ffi2::D { d: 42 });
 }
 
 #[test]
@@ -206,4 +207,7 @@ fn test_extern_opaque() {
     let e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ptr(e));
+    assert!(std::panic::catch_unwind(|| {
+        cxx::UniquePtr::new(ffi2::F { f: 42 })
+    }).is_err());
 }

From 117d3baac74bd577833ab09656bd294a212a7755 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 12 2020 23:33:30 +0000
Subject: [PATCH 1045/2232] Bazel/Buck test build fixups.


Sacrifices to satisfy the PR builder guardians.

---

diff --git a/tests/BUCK b/tests/BUCK
index 0ddf1a8..5bbe500 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -3,7 +3,10 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 rust_test(
     name = "test",
     srcs = ["test.rs"],
-    deps = [":ffi"],
+    deps = [
+        ":ffi",
+        "//:cxx",
+    ],
 )
 
 rust_library(
diff --git a/tests/BUILD b/tests/BUILD
index 233926b..57ffab9 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -6,7 +6,10 @@ rust_test(
     name = "test",
     size = "small",
     srcs = ["test.rs"],
-    deps = [":cxx_test_suite"],
+    deps = [
+        ":cxx_test_suite",
+        "//:cxx",
+    ],
 )
 
 rust_library(

From 9f7ff2e3a619089a6ae6ff8cc83425e5c1f493e0 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 13 2020 03:14:17 +0000
Subject: [PATCH 1046/2232] Switch to build-time squashing of 'new' method.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3cd94d1..9b4e120 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1247,9 +1247,9 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types.
         // We can't know at code generation time, so we generate both C++
-        // and Rust side bindings for a "new" method anyway. But that
-        // Rust code will explode at runtime if anyone tries to call it on
-        // an opaque type.
+        // and Rust side bindings for a "new" method anyway. But the Rust
+        // code can't be called for Opaque types because the 'new'
+        // method is not implemented.
         Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
         _ => false,
     };
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4213b4d..4a4ec64 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -815,21 +815,12 @@ fn expand_unique_ptr(
     let link_drop = format!("{}drop", prefix);
 
     let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
-        let trivial_assertion: Option<syn::Stmt> = if types.aliases.contains_key(ident) {
-            Some(parse_quote! {
-               < < #ident as :: cxx :: ExternType > :: Kind as :: cxx :: kind :: Kind > :: assert_trivial();
-            })
-        } else {
-            None
-        };
-
         Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_new]
                     fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
                 }
-                #trivial_assertion
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 unsafe { __new(&mut repr, &mut value) }
                 repr
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 45414c8..b9c5386 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -165,17 +165,9 @@ pub mod kind {
     /// indirection.
     pub enum Trivial {}
 
-    pub trait Kind: private::Sealed {
-        fn assert_trivial();
-    }
-    impl Kind for Opaque {
-        fn assert_trivial() {
-            panic!("Type not trivial");
-        }
-    }
-    impl Kind for Trivial {
-        fn assert_trivial() {}
-    }
+    pub trait Kind: private::Sealed {}
+    impl Kind for Opaque {}
+    impl Kind for Trivial {}
 }
 
 mod private {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 477c716..4bb5d67 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,5 +1,7 @@
 use crate::cxx_string::CxxString;
 use crate::cxx_vector::{self, CxxVector, VectorElement};
+use crate::ExternType;
+use crate::kind::Trivial;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
@@ -32,7 +34,9 @@ where
     }
 
     /// Allocates memory on the heap and makes a UniquePtr pointing to it.
-    pub fn new(value: T) -> Self {
+    pub fn new(value: T) -> Self
+    where
+    T: ExternType<Kind = Trivial> {
         UniquePtr {
             repr: T::__new(value),
             ty: PhantomData,
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 6209702..a809ea4 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -12,14 +12,12 @@
 pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
-    impl UniquePtr<F> {}
 
     extern "C" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
         type E = crate::other::E;
-        type F = crate::other::F;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index f80cda7..b3c2330 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -14,25 +14,17 @@ mod other {
     use cxx::kind::{Opaque, Trivial};
     use cxx::{type_id, CxxString, ExternType};
 
-    // Trivial.
     #[repr(C)]
     pub struct D {
         pub d: u64,
     }
 
-    // Opaque, and has realistic complexity.
     #[repr(C)]
     pub struct E {
         e_str: CxxString,
         e: u64,
     }
 
-    // Opaque, but simple enough that bad code can try to create it.
-    #[repr(C)]
-    pub struct F {
-        pub f: u64,
-    }
-
     unsafe impl ExternType for D {
         type Id = type_id!("tests::D");
         type Kind = Trivial;
@@ -42,11 +34,6 @@ mod other {
         type Id = type_id!("tests::E");
         type Kind = Opaque;
     }
-
-    unsafe impl ExternType for F {
-        type Id = type_id!("tests::F");
-        type Kind = Opaque;
-    }
 }
 
 #[cxx::bridge(namespace = tests)]
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index ff1fbd3..b3f547e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -37,10 +37,6 @@ struct E {
   std::string e_str;
 };
 
-struct F {
-  uint64_t f;
-};
-
 enum COwnedEnum {
   CVal1,
   CVal2,
diff --git a/tests/test.rs b/tests/test.rs
index 3ea02fa..b92eebf 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -207,7 +207,4 @@ fn test_extern_opaque() {
     let e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ptr(e));
-    assert!(std::panic::catch_unwind(|| {
-        cxx::UniquePtr::new(ffi2::F { f: 42 })
-    }).is_err());
 }
diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
new file mode 100644
index 0000000..6f3bf8c
--- /dev/null
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -0,0 +1,26 @@
+mod outside {
+    #[repr(C)]
+    pub struct C {
+        pub a: u8,
+    }
+    unsafe impl cxx::ExternType for C {
+        type Id = cxx::type_id!("C");
+        type Kind = cxx::kind::Opaque;
+    }
+}
+
+
+#[cxx::bridge]
+mod ffi {
+    impl UniquePtr<C> {}
+
+    extern "C" {
+        type C = crate::outside::C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+fn main() {
+    cxx::UniquePtr::new(outside::C { a: 4 } );
+}
diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr
new file mode 100644
index 0000000..5525a05
--- /dev/null
+++ b/tests/ui/unique_ptr_to_opaque.stderr
@@ -0,0 +1,7 @@
+error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial`
+  --> $DIR/unique_ptr_to_opaque.rs:25:5
+   |
+25 |     cxx::UniquePtr::new(outside::C { a: 4 } );
+   |     ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
+   |
+   = note: required by `UniquePtr::<T>::new`

From 595ac276322c056d093805dab9f559bad1234dd6 Mon Sep 17 00:00:00 2001
From: Jan Haller <bromeon@gmail.com>
Date: Oct 13 2020 20:48:08 +0000
Subject: [PATCH 1047/2232] Fix Windows symlink test to give reproducible error messages


After a `git clone -c core.symlinks=false` and `cargo test`, the script outputs a Git error as expected.
When running `cargo test` again, the error message changes to "symlink support needs to be enabled".

The test is done for an already existing directory, and the Windows mklink command _fails_ when the symlink exists already.
This commit deletes the link prior to the symlink creation.

---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index f6ec026..6c9d22d 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -61,6 +61,7 @@ fn main() {
         let from_dir = parent_dir.join("from");
         let to_dir = parent_dir.join("to");
         if fs::create_dir_all(&from_dir).is_ok()
+            && fs::remove_dir(&to_dir).is_ok()
             && windows::symlink_dir(&from_dir, &to_dir).is_err()
         {
             message = DENIED;

From 1137642ce4360b3d8832ab5c469fb7e95faaa256 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 13 2020 21:17:31 +0000
Subject: [PATCH 1048/2232] Merge pull request #362 from Bromeon/bugfix/symlink-check


Fix Windows symlink test to give reproducible error messages
---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index f6ec026..6c9d22d 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -61,6 +61,7 @@ fn main() {
         let from_dir = parent_dir.join("from");
         let to_dir = parent_dir.join("to");
         if fs::create_dir_all(&from_dir).is_ok()
+            && fs::remove_dir(&to_dir).is_ok()
             && windows::symlink_dir(&from_dir, &to_dir).is_err()
         {
             message = DENIED;

From c904f8a74f7a8c37e7dffab47a68433dba9ae4de Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 16 2020 17:47:58 +0000
Subject: [PATCH 1049/2232] Make cxx.h available to high level code generators.


At present, this file is available only from the git repository,
but higher level code generators may wish to ensure that they supply
a version of cxx.h corresponding precisely to the version of cxx
in use.

Specifically, such higher level code generators may wish to use
rust::Str and similar types in code which _they_ autogenerate,
and thus need a way to include definitions of such types. As
this code is autogenerated, it can't reasonably rummage around
the cxx git repository to find the correct cxx.h header.

To be even more specific, higher level code generators may wish
to pass rust::Str and/or rust::String types into C++, in order
to create UniquePtr<CxxString>s from Rust strings during function
calls.

---

diff --git a/gen/README.md b/gen/README.md
index 9786911..50adeca 100644
--- a/gen/README.md
+++ b/gen/README.md
@@ -2,3 +2,6 @@ This directory contains CXX's C++ code generator. This code generator has two
 public frontends, one a command-line application (binary) in the *cmd* directory
 and the other a library intended to be used from a build.rs in the *build*
 directory.
+
+There's also a 'lib' frontend which is intended to allow higher level code generators
+to embed cxx. This is not yet recommended for general use.
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index dae7e78..e4d9e71 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -22,6 +22,7 @@ mod syntax;
 pub use crate::error::Error;
 pub use crate::gen::{GeneratedCode, Opt};
 use proc_macro2::TokenStream;
+use gen::include::HEADER;
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
@@ -31,3 +32,8 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
         .map_err(Error::from)?;
     gen::generate(syntax, opt).map_err(Error::from)
 }
+
+/// Returns the complete contents of the cxx.h header.
+pub fn get_cxx_header_contents() -> &'static str {
+    HEADER
+}

From 0e01d6406f3591147c1b05de66180d6bc118d3a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:06:48 +0000
Subject: [PATCH 1050/2232] Expose cxx_gen::HEADER as a static &'static str


---

diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index e4d9e71..ecfa436 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -20,9 +20,9 @@ mod gen;
 mod syntax;
 
 pub use crate::error::Error;
+pub use crate::gen::include::HEADER;
 pub use crate::gen::{GeneratedCode, Opt};
 use proc_macro2::TokenStream;
-use gen::include::HEADER;
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
 /// token stream which somewhere contains a `#[cxx::bridge] mod {}`.
@@ -32,8 +32,3 @@ pub fn generate_header_and_cc(rust_source: TokenStream, opt: &Opt) -> Result<Gen
         .map_err(Error::from)?;
     gen::generate(syntax, opt).map_err(Error::from)
 }
-
-/// Returns the complete contents of the cxx.h header.
-pub fn get_cxx_header_contents() -> &'static str {
-    HEADER
-}
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 1688a4e..3255902 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,6 +1,7 @@
 use crate::gen::out::OutFile;
 use std::fmt::{self, Display};
 
+/// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
 
 pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {

From 33b1ae956497b2f4d320c1e26ce8e31fd4d52fc5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:11:56 +0000
Subject: [PATCH 1051/2232] Merge pull request 364 from adetaylor/make-cxx-h-available


---

diff --git a/gen/README.md b/gen/README.md
index 9786911..d00b98f 100644
--- a/gen/README.md
+++ b/gen/README.md
@@ -2,3 +2,6 @@ This directory contains CXX's C++ code generator. This code generator has two
 public frontends, one a command-line application (binary) in the *cmd* directory
 and the other a library intended to be used from a build.rs in the *build*
 directory.
+
+There's also a 'lib' frontend which is intended to allow higher level code
+generators to embed cxx. This is not yet recommended for general use.
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index dae7e78..ecfa436 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -20,6 +20,7 @@ mod gen;
 mod syntax;
 
 pub use crate::error::Error;
+pub use crate::gen::include::HEADER;
 pub use crate::gen::{GeneratedCode, Opt};
 use proc_macro2::TokenStream;
 
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 1688a4e..3255902 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,6 +1,7 @@
 use crate::gen::out::OutFile;
 use std::fmt::{self, Display};
 
+/// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
 
 pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {

From 35b3cd359b976138c9ad5c08a7459b8068d047a0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:15:40 +0000
Subject: [PATCH 1052/2232] Merge pull request #361 from adetaylor/trivial-alias-uniqueptr


Allow creation of UniquePtrs to trivial aliased types.
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5d47c63..9b4e120 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1245,7 +1245,12 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     let instance = to_mangled(&out.namespace, ty);
 
     let can_construct_from_value = match ty {
-        Type::Ident(ident) => types.structs.contains_key(ident),
+        // Some aliases are to opaque types; some are to trivial types.
+        // We can't know at code generation time, so we generate both C++
+        // and Rust side bindings for a "new" method anyway. But the Rust
+        // code can't be called for Opaque types because the 'new'
+        // method is not implemented.
+        Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
         _ => false,
     };
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6fa7ea7..4a4ec64 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -814,7 +814,7 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) {
+    let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
         Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 477c716..4bb5d67 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,5 +1,7 @@
 use crate::cxx_string::CxxString;
 use crate::cxx_vector::{self, CxxVector, VectorElement};
+use crate::ExternType;
+use crate::kind::Trivial;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
@@ -32,7 +34,9 @@ where
     }
 
     /// Allocates memory on the heap and makes a UniquePtr pointing to it.
-    pub fn new(value: T) -> Self {
+    pub fn new(value: T) -> Self
+    where
+    T: ExternType<Kind = Trivial> {
         UniquePtr {
             repr: T::__new(value),
             ty: PhantomData,
diff --git a/tests/BUCK b/tests/BUCK
index 0ddf1a8..5bbe500 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -3,7 +3,10 @@ load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge")
 rust_test(
     name = "test",
     srcs = ["test.rs"],
-    deps = [":ffi"],
+    deps = [
+        ":ffi",
+        "//:cxx",
+    ],
 )
 
 rust_library(
diff --git a/tests/BUILD b/tests/BUILD
index 233926b..57ffab9 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -6,7 +6,10 @@ rust_test(
     name = "test",
     size = "small",
     srcs = ["test.rs"],
-    deps = [":cxx_test_suite"],
+    deps = [
+        ":cxx_test_suite",
+        "//:cxx",
+    ],
 )
 
 rust_library(
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7cffded..b3c2330 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -16,13 +16,13 @@ mod other {
 
     #[repr(C)]
     pub struct D {
-        d: u64,
+        pub d: u64,
     }
 
     #[repr(C)]
     pub struct E {
-        e: u64,
         e_str: CxxString,
+        e: u64,
     }
 
     unsafe impl ExternType for D {
diff --git a/tests/test.rs b/tests/test.rs
index a9cd8e1..b92eebf 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -199,6 +199,7 @@ fn test_extern_trivial() {
     check!(ffi2::c_take_trivial(d));
     let d = ffi2::c_return_trivial_ptr();
     check!(ffi2::c_take_trivial_ptr(d));
+    cxx::UniquePtr::new(ffi2::D { d: 42 });
 }
 
 #[test]
diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
new file mode 100644
index 0000000..6f3bf8c
--- /dev/null
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -0,0 +1,26 @@
+mod outside {
+    #[repr(C)]
+    pub struct C {
+        pub a: u8,
+    }
+    unsafe impl cxx::ExternType for C {
+        type Id = cxx::type_id!("C");
+        type Kind = cxx::kind::Opaque;
+    }
+}
+
+
+#[cxx::bridge]
+mod ffi {
+    impl UniquePtr<C> {}
+
+    extern "C" {
+        type C = crate::outside::C;
+    }
+
+    impl UniquePtr<C> {}
+}
+
+fn main() {
+    cxx::UniquePtr::new(outside::C { a: 4 } );
+}
diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr
new file mode 100644
index 0000000..5525a05
--- /dev/null
+++ b/tests/ui/unique_ptr_to_opaque.stderr
@@ -0,0 +1,7 @@
+error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial`
+  --> $DIR/unique_ptr_to_opaque.rs:25:5
+   |
+25 |     cxx::UniquePtr::new(outside::C { a: 4 } );
+   |     ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
+   |
+   = note: required by `UniquePtr::<T>::new`

From ca0f9da8320fe77a4044f9a9d0a4e69047dd9789 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:18:54 +0000
Subject: [PATCH 1053/2232] Format PR 361 with rustfmt


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9b4e120..3184604 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1245,12 +1245,13 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     let instance = to_mangled(&out.namespace, ty);
 
     let can_construct_from_value = match ty {
-        // Some aliases are to opaque types; some are to trivial types.
-        // We can't know at code generation time, so we generate both C++
-        // and Rust side bindings for a "new" method anyway. But the Rust
-        // code can't be called for Opaque types because the 'new'
-        // method is not implemented.
-        Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
+        // Some aliases are to opaque types; some are to trivial types. We can't
+        // know at code generation time, so we generate both C++ and Rust side
+        // bindings for a "new" method anyway. But the Rust code can't be called
+        // for Opaque types because the 'new' method is not implemented.
+        Type::Ident(ident) => {
+            types.structs.contains_key(ident) || types.aliases.contains_key(ident)
+        }
         _ => false,
     };
 
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 4bb5d67..3a5fc66 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,7 +1,7 @@
 use crate::cxx_string::CxxString;
 use crate::cxx_vector::{self, CxxVector, VectorElement};
-use crate::ExternType;
 use crate::kind::Trivial;
+use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
@@ -36,7 +36,8 @@ where
     /// Allocates memory on the heap and makes a UniquePtr pointing to it.
     pub fn new(value: T) -> Self
     where
-    T: ExternType<Kind = Trivial> {
+        T: ExternType<Kind = Trivial>,
+    {
         UniquePtr {
             repr: T::__new(value),
             ty: PhantomData,
diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
index 6f3bf8c..5ae03f8 100644
--- a/tests/ui/unique_ptr_to_opaque.rs
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -9,7 +9,6 @@ mod outside {
     }
 }
 
-
 #[cxx::bridge]
 mod ffi {
     impl UniquePtr<C> {}
@@ -22,5 +21,5 @@ mod ffi {
 }
 
 fn main() {
-    cxx::UniquePtr::new(outside::C { a: 4 } );
+    cxx::UniquePtr::new(outside::C { a: 4 });
 }
diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr
index 5525a05..f0e4aa0 100644
--- a/tests/ui/unique_ptr_to_opaque.stderr
+++ b/tests/ui/unique_ptr_to_opaque.stderr
@@ -1,7 +1,7 @@
 error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial`
-  --> $DIR/unique_ptr_to_opaque.rs:25:5
+  --> $DIR/unique_ptr_to_opaque.rs:24:5
    |
-25 |     cxx::UniquePtr::new(outside::C { a: 4 } );
+24 |     cxx::UniquePtr::new(outside::C { a: 4 });
    |     ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
    |
    = note: required by `UniquePtr::<T>::new`

From 441956e803c1070c85ecd14d61c443311905ef8f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:21:51 +0000
Subject: [PATCH 1054/2232] Match layout of C++ tests::E and struct E in Rust


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index b3c2330..4078b37 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -21,8 +21,8 @@ mod other {
 
     #[repr(C)]
     pub struct E {
-        e_str: CxxString,
         e: u64,
+        e_str: CxxString,
     }
 
     unsafe impl ExternType for D {

From 743caa283ced87d021e67c65ced1860fe0a11ecc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:22:47 +0000
Subject: [PATCH 1055/2232] Remove duplicated UniquePtr<C> impl in ui test


---

diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
index 5ae03f8..720ca69 100644
--- a/tests/ui/unique_ptr_to_opaque.rs
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -11,8 +11,6 @@ mod outside {
 
 #[cxx::bridge]
 mod ffi {
-    impl UniquePtr<C> {}
-
     extern "C" {
         type C = crate::outside::C;
     }
diff --git a/tests/ui/unique_ptr_to_opaque.stderr b/tests/ui/unique_ptr_to_opaque.stderr
index f0e4aa0..19d76a3 100644
--- a/tests/ui/unique_ptr_to_opaque.stderr
+++ b/tests/ui/unique_ptr_to_opaque.stderr
@@ -1,7 +1,7 @@
 error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial`
-  --> $DIR/unique_ptr_to_opaque.rs:24:5
+  --> $DIR/unique_ptr_to_opaque.rs:22:5
    |
-24 |     cxx::UniquePtr::new(outside::C { a: 4 });
+22 |     cxx::UniquePtr::new(outside::C { a: 4 });
    |     ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
    |
    = note: required by `UniquePtr::<T>::new`

From a32ca3080b0289fd26aa12cb4870b9f6e11663bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:31:09 +0000
Subject: [PATCH 1056/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 93abbdc..d07cda2 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.43/src/**"]),
+    srcs = glob(["vendor/syn-1.0.44/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index f798190..a539bd2 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.43/src/**"]),
+    srcs = glob(["vendor/syn-1.0.44/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 54f250e..b85924f 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -230,18 +230,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.116"
+version = "1.0.117"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
+checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.116"
+version = "1.0.117"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
+checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -250,9 +250,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.58"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4"
+checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
 dependencies = [
  "itoa",
  "ryu",
@@ -267,9 +267,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.43"
+version = "1.0.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e2e59c50ed8f6b050b071aa7b6865293957a9af6b58b94f97c1c9434ad440ea"
+checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -296,9 +296,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.5.6"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
+checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
 dependencies = [
  "serde",
 ]

From e37ce2f4ee65a261ee64189585a5615a459c6403 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 16 2020 20:32:07 +0000
Subject: [PATCH 1057/2232] Release 0.5.2


---

diff --git a/Cargo.toml b/Cargo.toml
index 045ecc3..4e01e1a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.1" # remember to update html_root_url
+version = "0.5.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.1", path = "macro" }
+cxxbridge-macro = { version = "=0.5.2", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.1", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.2", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.1", path = "gen/build" }
+cxx-build = { version = "=0.5.2", path = "gen/build" }
 cxx-gen = { version = "0.5", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index f8e5a7b..2f4c512 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.1"
+version = "0.5.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index df6eea0..b1954b4 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.1"
+version = "0.5.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 99addee..f1c977c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.1"
+version = "0.5.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 18845f8..ee62e14 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.5.1"
+version = "0.5.2"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1618b0d..3d12d20 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.1"
+version = "0.5.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index efd3fbc..9cd3adf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.1")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.2")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b85924f..3a32f05 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -88,7 +88,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -119,11 +119,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.1"
+version = "0.5.2"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.1"
+version = "0.5.2"
 dependencies = [
  "cxx",
  "proc-macro2",

From cca5215060cb472902d52fba9414fdd0ea9009d9 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 23 2020 00:56:53 +0000
Subject: [PATCH 1058/2232] Diagnostic improvement.


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2f3c334..ced1570 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -67,7 +67,7 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
-        cx.error(ident, "unsupported type");
+        cx.error(ident, &format!("unsupported type: {}", ident));
     }
 }
 

From 9a158e408fc916255be0dbf88cf39d1d6176d548 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1059/2232] Adding tests for types in namespaces.


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4078b37..621608e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -49,6 +49,32 @@ pub mod ffi {
         CVal,
     }
 
+    #[namespace(namespace = A)]
+    #[derive(Clone)]
+    struct AShared {
+        z: usize,
+    }
+
+    #[namespace(namespace = A)]
+    enum AEnum {
+        AAVal,
+        ABVal = 2020,
+        ACVal,
+    }
+
+    #[namespace(namespace = A::B)]
+    enum ABEnum {
+        ABAVal,
+        ABBVal = 2020,
+        ABCVal,
+    }
+
+    #[namespace(namespace = A::B)]
+    #[derive(Clone)]
+    struct ABShared {
+        z: usize,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 
@@ -78,6 +104,10 @@ pub mod ffi {
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
+        fn c_return_ns_ref(shared: &AShared) -> &usize;
+        fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
+        fn c_return_ns_enum(n: u16) -> AEnum;
+        fn c_return_nested_ns_enum(n: u16) -> ABEnum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -108,6 +138,12 @@ pub mod ffi {
         fn c_take_callback(callback: fn(String) -> usize);
         */
         fn c_take_enum(e: Enum);
+        fn c_take_ns_enum(e: AEnum);
+        fn c_take_nested_ns_enum(e: ABEnum);
+        fn c_take_ns_shared(shared: AShared);
+        fn c_take_nested_ns_shared(shared: ABShared);
+        fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
+        fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 983cf95..2c37397 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -43,6 +43,10 @@ size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
 
+::A::AShared c_return_ns_shared() { return ::A::AShared{2020}; }
+
+::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; }
+
 rust::Box<R> c_return_box() {
   return rust::Box<R>::from_raw(cxx_test_suite_get_box());
 }
@@ -53,6 +57,10 @@ std::unique_ptr<C> c_return_unique_ptr() {
 
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
+const size_t &c_return_ns_ref(const ::A::AShared &shared) { return shared.z; }
+
+const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { return shared.z; }
+
 size_t &c_return_mut(Shared &shared) { return shared.z; }
 
 rust::Str c_return_str(const Shared &shared) {
@@ -144,6 +152,26 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+::A::AEnum c_return_ns_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(::A::AEnum::AAVal)) {
+    return ::A::AEnum::AAVal;
+  } else if (n <= static_cast<uint16_t>(::A::AEnum::ABVal)) {
+    return ::A::AEnum::ABVal;
+  } else {
+    return ::A::AEnum::ACVal;
+  }
+}
+
+::A::B::ABEnum c_return_nested_ns_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABAVal)) {
+    return ::A::B::ABEnum::ABAVal;
+  } else if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABBVal)) {
+    return ::A::B::ABEnum::ABBVal;
+  } else {
+    return ::A::B::ABEnum::ABCVal;
+  }
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -156,6 +184,18 @@ void c_take_shared(Shared shared) {
   }
 }
 
+void c_take_ns_shared(::A::AShared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_nested_ns_shared(::A::B::ABShared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_box(rust::Box<R> r) {
   if (cxx_test_suite_r_is_correct(&*r)) {
     cxx_test_suite_set_correct();
@@ -258,6 +298,26 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v) {
+  uint32_t sum = 0;
+  for (auto i : v) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v) {
+  uint32_t sum = 0;
+  for (auto i : v) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_vec_string(rust::Vec<rust::String> v) {
   (void)v;
   cxx_test_suite_set_correct();
@@ -326,6 +386,18 @@ void c_take_enum(Enum e) {
   }
 }
 
+void c_take_ns_enum(::A::AEnum e) {
+  if (e == ::A::AEnum::AAVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_nested_ns_enum(::A::B::ABEnum e) {
+  if (e == ::A::B::ABEnum::ABAVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index b3f547e..70d0a43 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -3,6 +3,15 @@
 #include <memory>
 #include <string>
 
+namespace A {
+  struct AShared;
+  enum class AEnum : uint16_t;
+  namespace B {
+    struct ABShared;
+    enum class ABEnum : uint16_t;
+  } // namespace B
+} // namespace A
+
 namespace tests {
 
 struct R;
@@ -44,9 +53,13 @@ enum COwnedEnum {
 
 size_t c_return_primitive();
 Shared c_return_shared();
+::A::AShared c_return_ns_shared();
+::A::B::ABShared c_return_nested_ns_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
+const size_t &c_return_ns_ref(const ::A::AShared &shared);
+const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
@@ -66,9 +79,13 @@ rust::Vec<rust::String> c_return_rust_vec_string();
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
+::A::AEnum c_return_ns_enum(uint16_t n);
+::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
+void c_take_ns_shared(::A::AShared shared);
+void c_take_nested_ns_shared(::A::B::ABShared shared);
 void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
@@ -86,6 +103,8 @@ void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
 void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v);
+void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v);
 void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
@@ -98,6 +117,8 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 */
 void c_take_enum(Enum e);
+void c_take_ns_enum(::A::AEnum e);
+void c_take_nested_ns_enum(::A::B::ABEnum e);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index b92eebf..eece7ff 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -23,12 +23,16 @@ macro_rules! check {
 #[test]
 fn test_c_return() {
     let shared = ffi::Shared { z: 2020 };
+    let ns_shared = ffi::AShared { z: 2020 };
+    let nested_ns_shared = ffi::ABShared { z: 2020 };
 
     assert_eq!(2020, ffi::c_return_primitive());
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, *ffi::c_return_box());
     ffi::c_return_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
+    assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
+    assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
@@ -64,6 +68,14 @@ fn test_c_return() {
         enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
+    match ffi::c_return_ns_enum(0) {
+        enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr),
+        _ => assert!(false),
+    }
+    match ffi::c_return_nested_ns_enum(0) {
+        enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr),
+        _ => assert!(false),
+    }
 }
 
 #[test]
@@ -88,6 +100,8 @@ fn test_c_take() {
 
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
+    check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 }));
+    check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
@@ -119,7 +133,16 @@ fn test_c_take() {
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }];
+    check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec));
+    let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }];
+    check!(ffi::c_take_rust_vec_nested_ns_shared(
+        nested_ns_shared_test_vec
+    ));
+
     check!(ffi::c_take_enum(ffi::Enum::AVal));
+    check!(ffi::c_take_ns_enum(ffi::AEnum::AAVal));
+    check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
 }
 
 /*

From 5e79c647696e55934e108397b2e1c3e824ce8079 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1060/2232] Tests for namespaced opaque extern types.


---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index a809ea4..1faf375 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -12,20 +12,26 @@
 pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
+    impl UniquePtr<F> {}
 
     extern "C" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
         type E = crate::other::E;
+        #[namespace (namespace = F)]
+        type F = crate::other::f::F;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
         fn c_take_trivial(d: D);
         fn c_take_opaque_ptr(e: UniquePtr<E>);
         fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
+        fn c_take_opaque_ns_ref(e: &F);
         fn c_return_trivial_ptr() -> UniquePtr<D>;
         fn c_return_trivial() -> D;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 621608e..f25fd2a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -25,6 +25,22 @@ mod other {
         e_str: CxxString,
     }
 
+    pub mod f {
+        use cxx::kind::Opaque;
+        use cxx::{type_id, CxxString, ExternType};
+
+        #[repr(C)]
+        pub struct F {
+            e: u64,
+            e_str: CxxString,
+        }
+
+        unsafe impl ExternType for F {
+            type Id = type_id!("F::F");
+            type Kind = Opaque;
+        }
+    }
+
     unsafe impl ExternType for D {
         type Id = type_id!("tests::D");
         type Kind = Trivial;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2c37397..db51435 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -478,12 +478,25 @@ void c_take_opaque_ptr(std::unique_ptr<E> e) {
   }
 }
 
+void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f) {
+  if (f->f == 40) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ref(const E& e) {
   if (e.e == 40 && e.e_str == "hello") {
     cxx_test_suite_set_correct();
   }
 }
 
+void c_take_opaque_ns_ref(const ::F::F& f) {
+  if (f.f == 40 && f.f_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+
 std::unique_ptr<D> c_return_trivial_ptr() {
   auto d = std::unique_ptr<D>(new D());
   d->d = 30;
@@ -503,6 +516,13 @@ std::unique_ptr<E> c_return_opaque_ptr() {
   return e;
 }
 
+std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
+  auto f = std::unique_ptr<::F::F>(new ::F::F());
+  f->f = 40;
+  f->f_str = std::string("hello");
+  return f;
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 70d0a43..4bdf69e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -12,6 +12,13 @@ namespace A {
   } // namespace B
 } // namespace A
 
+namespace F {
+  struct F {
+    uint64_t f;
+    std::string f_str;
+  };
+}
+
 namespace tests {
 
 struct R;
@@ -137,10 +144,13 @@ void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D& d);
 void c_take_trivial(D d);
 void c_take_opaque_ptr(std::unique_ptr<E> e);
+void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f);
 void c_take_opaque_ref(const E& e);
+void c_take_opaque_ns_ref(const ::F::F& f);
 std::unique_ptr<D> c_return_trivial_ptr();
 D c_return_trivial();
 std::unique_ptr<E> c_return_opaque_ptr();
+std::unique_ptr<::F::F> c_return_ns_opaque_ptr();
 
 rust::String cOverloadedFunction(int32_t x);
 rust::String cOverloadedFunction(rust::Str x);
diff --git a/tests/test.rs b/tests/test.rs
index eece7ff..73bb084 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -230,4 +230,8 @@ fn test_extern_opaque() {
     let e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ptr(e));
+
+    let f = ffi2::c_return_ns_opaque_ptr();
+    check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap()));
+    check!(ffi2::c_take_opaque_ns_ptr(f));
 }

From 585bb0bc5605ccf28b5a814b5727967b8ee67c83 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1061/2232] Tests for namespaced extern trivial types


---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 1faf375..0921724 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -13,6 +13,7 @@ pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
     impl UniquePtr<F> {}
+    impl UniquePtr<G> {}
 
     extern "C" {
         include!("tests/ffi/tests.h");
@@ -21,16 +22,23 @@ pub mod ffi2 {
         type E = crate::other::E;
         #[namespace (namespace = F)]
         type F = crate::other::f::F;
+        #[namespace (namespace = G)]
+        type G = crate::other::G;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
         fn c_take_trivial(d: D);
+        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
+        fn c_take_trivial_ns_ref(g: &G);
+        fn c_take_trivial_ns(g: G);
         fn c_take_opaque_ptr(e: UniquePtr<E>);
         fn c_take_opaque_ref(e: &E);
         fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
         fn c_take_opaque_ns_ref(e: &F);
         fn c_return_trivial_ptr() -> UniquePtr<D>;
         fn c_return_trivial() -> D;
+        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
+        fn c_return_trivial_ns() -> G;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
         fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index f25fd2a..1cd92f9 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -41,6 +41,16 @@ mod other {
         }
     }
 
+    #[repr(C)]
+    pub struct G {
+        pub g: u64,
+    }
+
+    unsafe impl ExternType for G {
+        type Id = type_id!("G::G");
+        type Kind = Trivial;
+    }
+
     unsafe impl ExternType for D {
         type Id = type_id!("tests::D");
         type Kind = Trivial;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index db51435..017cb82 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -466,12 +466,32 @@ void c_take_trivial_ref(const D& d) {
     cxx_test_suite_set_correct();
   }
 }
+
 void c_take_trivial(D d) {
   if (d.d == 30) {
     cxx_test_suite_set_correct();
   }
 }
 
+
+void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g) {
+  if (g->g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ns_ref(const ::G::G& g) {
+  if (g.g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ns(::G::G g) {
+  if (g.g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ptr(std::unique_ptr<E> e) {
   if (e->e == 40) {
     cxx_test_suite_set_correct();
@@ -496,7 +516,6 @@ void c_take_opaque_ns_ref(const ::F::F& f) {
   }
 }
 
-
 std::unique_ptr<D> c_return_trivial_ptr() {
   auto d = std::unique_ptr<D>(new D());
   d->d = 30;
@@ -509,6 +528,18 @@ D c_return_trivial() {
   return d;
 }
 
+std::unique_ptr<::G::G> c_return_trivial_ns_ptr() {
+  auto g = std::unique_ptr<::G::G>(new ::G::G());
+  g->g = 30;
+  return g;
+}
+
+::G::G c_return_trivial_ns() {
+  ::G::G g;
+  g.g = 30;
+  return g;
+}
+
 std::unique_ptr<E> c_return_opaque_ptr() {
   auto e = std::unique_ptr<E>(new E());
   e->e = 40;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 4bdf69e..7f62672 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -19,6 +19,12 @@ namespace F {
   };
 }
 
+namespace G {
+  struct G {
+    uint64_t g;
+  };
+}
+
 namespace tests {
 
 struct R;
@@ -143,12 +149,18 @@ const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D& d);
 void c_take_trivial(D d);
+
+void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g);
+void c_take_trivial_ns_ref(const ::G::G& g);
+void c_take_trivial_ns(::G::G g);
 void c_take_opaque_ptr(std::unique_ptr<E> e);
 void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f);
 void c_take_opaque_ref(const E& e);
 void c_take_opaque_ns_ref(const ::F::F& f);
 std::unique_ptr<D> c_return_trivial_ptr();
 D c_return_trivial();
+std::unique_ptr<::G::G> c_return_trivial_ns_ptr();
+::G::G c_return_trivial_ns();
 std::unique_ptr<E> c_return_opaque_ptr();
 std::unique_ptr<::F::F> c_return_ns_opaque_ptr();
 
diff --git a/tests/test.rs b/tests/test.rs
index 73bb084..02cb494 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -223,6 +223,13 @@ fn test_extern_trivial() {
     let d = ffi2::c_return_trivial_ptr();
     check!(ffi2::c_take_trivial_ptr(d));
     cxx::UniquePtr::new(ffi2::D { d: 42 });
+
+    let g = ffi2::c_return_trivial_ns();
+    check!(ffi2::c_take_trivial_ns_ref(&g));
+    check!(ffi2::c_take_trivial_ns(g));
+    let g = ffi2::c_return_trivial_ns_ptr();
+    check!(ffi2::c_take_trivial_ns_ptr(g));
+    cxx::UniquePtr::new(ffi2::G { g: 42 });
 }
 
 #[test]

From d47af7a9d3640438e3d1371a739297b789296cfb Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1062/2232] Tests for opaque C types in namepsaces


---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 0921724..aa83cc2 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -25,6 +25,9 @@ pub mod ffi2 {
         #[namespace (namespace = G)]
         type G = crate::other::G;
 
+        #[namespace(namespace = H)]
+        type H;
+
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
         fn c_take_trivial(d: D);
@@ -41,5 +44,7 @@ pub mod ffi2 {
         fn c_return_trivial_ns() -> G;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
         fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
+        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
+        fn c_take_ref_ns_c(h: &H);
     }
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 017cb82..585a99b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -55,6 +55,10 @@ std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
 
+std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
+  return std::unique_ptr<::H::H>(new ::H::H{"hello"});
+}
+
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
 const size_t &c_return_ns_ref(const ::A::AShared &shared) { return shared.z; }
@@ -220,6 +224,12 @@ void c_take_ref_c(const C &c) {
   }
 }
 
+void c_take_ref_ns_c(const ::H::H &h) {
+  if (h.h == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_str(rust::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7f62672..dfedb3c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -25,6 +25,13 @@ namespace G {
   };
 }
 
+namespace H {
+  class H {
+  public:
+    std::string h;
+  };
+}
+
 namespace tests {
 
 struct R;
@@ -70,6 +77,7 @@ Shared c_return_shared();
 ::A::B::ABShared c_return_nested_ns_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
+std::unique_ptr<::H::H> c_return_ns_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 const size_t &c_return_ns_ref(const ::A::AShared &shared);
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
@@ -103,6 +111,7 @@ void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
+void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
diff --git a/tests/test.rs b/tests/test.rs
index 02cb494..39a700e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -30,6 +30,7 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, *ffi::c_return_box());
     ffi::c_return_unique_ptr();
+    ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
     assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
@@ -97,6 +98,7 @@ fn test_c_try_return() {
 #[test]
 fn test_c_take() {
     let unique_ptr = ffi::c_return_unique_ptr();
+    let unique_ptr_ns = ffi2::c_return_ns_unique_ptr();
 
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
@@ -104,6 +106,7 @@ fn test_c_take() {
     check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
+    check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));

From ddc146ef9f4d67ddf75bf7174fdc1e2a95a2ced5 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1063/2232] Adding tests for functions in other namespaces.


---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index aa83cc2..633cf93 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -46,5 +46,10 @@ pub mod ffi2 {
         fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
         fn c_return_ns_unique_ptr() -> UniquePtr<H>;
         fn c_take_ref_ns_c(h: &H);
+
+        #[namespace (namespace = other)]
+        fn ns_c_take_trivial(d: D);
+        #[namespace (namespace = other)]
+        fn ns_c_return_trivial() -> D;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 1cd92f9..a491ae2 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -199,6 +199,9 @@ pub mod ffi {
         fn cOverloadedFunction(x: i32) -> String;
         #[rust_name = "str_overloaded_function"]
         fn cOverloadedFunction(x: &str) -> String;
+
+        #[namespace (namespace = other)]
+        fn ns_c_take_ns_shared(shared: AShared);
     }
 
     extern "C" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 585a99b..1f0f8ff 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -627,3 +627,24 @@ extern "C" const char *cxx_run_test() noexcept {
 }
 
 } // namespace tests
+
+namespace other {
+
+  void ns_c_take_trivial(::tests::D d) {
+    if (d.d == 30) {
+      cxx_test_suite_set_correct();
+    }
+  }
+
+  ::tests::D ns_c_return_trivial() {
+    ::tests::D d;
+    d.d = 30;
+    return d;
+  }
+
+  void ns_c_take_ns_shared(::A::AShared shared) {
+    if (shared.z == 2020) {
+      cxx_test_suite_set_correct();
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index dfedb3c..40bc802 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -177,3 +177,9 @@ rust::String cOverloadedFunction(int32_t x);
 rust::String cOverloadedFunction(rust::Str x);
 
 } // namespace tests
+
+namespace other {
+  void ns_c_take_trivial(::tests::D d);
+  ::tests::D ns_c_return_trivial();
+  void ns_c_take_ns_shared(::A::AShared shared);
+} // namespace other
\ No newline at end of file
diff --git a/tests/test.rs b/tests/test.rs
index 39a700e..21f8a8c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -103,6 +103,7 @@ fn test_c_take() {
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
     check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 }));
+    check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 }));
     check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
@@ -226,6 +227,8 @@ fn test_extern_trivial() {
     let d = ffi2::c_return_trivial_ptr();
     check!(ffi2::c_take_trivial_ptr(d));
     cxx::UniquePtr::new(ffi2::D { d: 42 });
+    let d = ffi2::ns_c_return_trivial();
+    check!(ffi2::ns_c_take_trivial(d));
 
     let g = ffi2::c_return_trivial_ns();
     check!(ffi2::c_take_trivial_ns_ref(&g));

From 0fac32193904fdd75dcff71e5e4bd846b6e560b7 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:17:02 +0000
Subject: [PATCH 1064/2232] Adding tests for method calls in foreign namespaces


---

diff --git a/tests/BUCK b/tests/BUCK
index 5bbe500..f51be09 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -15,6 +15,7 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
+        "ffi/class_in_ns.rs",
     ],
     crate = "cxx_test_suite",
     deps = [
@@ -30,6 +31,7 @@ cxx_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
+        ":class_in_ns/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -52,3 +54,8 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
+
+rust_cxx_bridge(
+    name = "class_in_ns",
+    src = "ffi/class_in_ns.rs",
+)
diff --git a/tests/BUILD b/tests/BUILD
index 57ffab9..a400f47 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -18,6 +18,7 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
+        "ffi/class_in_ns.rs",
     ],
     deps = [
         ":impl",
@@ -32,6 +33,7 @@ cc_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
+        ":class_in_ns/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -57,3 +59,9 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
+
+rust_cxx_bridge(
+    name = "class_in_ns",
+    src = "ffi/class_in_ns.rs",
+    deps = [":impl"],
+)
\ No newline at end of file
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 4b2cbdf..9bdb711 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs", "class_in_ns.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
new file mode 100644
index 0000000..8b50561
--- /dev/null
+++ b/tests/ffi/class_in_ns.rs
@@ -0,0 +1,21 @@
+// To test receivers on a type in a namespace outide
+// the default. cxx::bridge blocks can only have a single
+// receiver type, and there can only be one such block per,
+// which is why this is outside.
+
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi3 {
+
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        #[namespace (namespace = I)]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace (namespace = I)]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
+    }
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index a491ae2..be145f3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,6 +4,7 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
+pub mod class_in_ns;
 pub mod extra;
 pub mod module;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 1f0f8ff..05bf5fb 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -647,4 +647,14 @@ namespace other {
       cxx_test_suite_set_correct();
     }
   }
-}
\ No newline at end of file
+} // namespace other
+
+namespace I {
+  uint32_t I::get() const {
+    return a;
+  }
+
+  std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
+    return std::unique_ptr<I>(new I());
+  }
+} // namespace I
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 40bc802..3835660 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -182,4 +182,16 @@ namespace other {
   void ns_c_take_trivial(::tests::D d);
   ::tests::D ns_c_return_trivial();
   void ns_c_take_ns_shared(::A::AShared shared);
-} // namespace other
\ No newline at end of file
+} // namespace other
+
+namespace I {
+  class I {
+  private:
+    uint32_t a;
+  public:
+    I() : a(1000) {}
+    uint32_t get() const;
+  };
+
+  std::unique_ptr<I> ns_c_return_unique_ptr_ns();
+} // namespace I
diff --git a/tests/test.rs b/tests/test.rs
index 21f8a8c..20b23ac 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,3 +1,4 @@
+use cxx_test_suite::class_in_ns::ffi3;
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;
@@ -194,6 +195,14 @@ fn test_c_method_calls() {
 }
 
 #[test]
+fn test_c_ns_method_calls() {
+    let unique_ptr = ffi3::ns_c_return_unique_ptr_ns();
+
+    let old_value = unique_ptr.get();
+    assert_eq!(1000, old_value);
+}
+
+#[test]
 fn test_enum_representations() {
     assert_eq!(0, ffi::Enum::AVal.repr);
     assert_eq!(2020, ffi::Enum::BVal.repr);

From c871343ac270f073fd4790269da267e8cb91dbde Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 26 2020 22:23:34 +0000
Subject: [PATCH 1065/2232] Allow namespace override.


This change allows a

 #[namespace (namespace = A::B)]

attribute for each item in a cxx::bridge.

We now have a fair number of different types of name floating
around:
* C++ identifiers
* C++ fully-qualified names
* Rust identifiers
* Rust fully-qualified names (future, when we support sub-modules)
* Items with both a Rust and C++ name (a 'Pair')
* Types with only a known Rust name, which can be resolved to a
  C++ name.

This change attempts to put some sensible names for all these
things in syntax/mod.rs, and so that would be a good place to start
review.

At the moment, the Namespace (included in each CppName)
is ruthlessly cloned all over the place. As a given namespace is
likely to be applicable to many types and functions, it may
save significant memory in future to use Rc<> here. But let's not
optimise too early.

---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 2fee0e9..92e8ec8 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -5,6 +5,7 @@ pub(super) mod error;
 mod file;
 pub(super) mod fs;
 pub(super) mod include;
+mod namespace_organizer;
 pub(super) mod out;
 mod write;
 
@@ -109,22 +110,22 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
         .ok_or(Error::NoBridgeMod)?;
     let ref namespace = bridge.namespace;
     let trusted = bridge.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, bridge.content, trusted);
+    let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
-    check::typecheck(errors, namespace, apis, types);
+    check::typecheck(errors, apis, types);
     errors.propagate()?;
     // Some callers may wish to generate both header and C++
     // from the same token stream to avoid parsing twice. But others
     // only need to generate one or the other.
     Ok(GeneratedCode {
         header: if opt.gen_header {
-            write::gen(namespace, apis, types, opt, true).content()
+            write::gen(apis, types, opt, true).content()
         } else {
             Vec::new()
         },
         implementation: if opt.gen_implementation {
-            write::gen(namespace, apis, types, opt, false).content()
+            write::gen(apis, types, opt, false).content()
         } else {
             Vec::new()
         },
diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
new file mode 100644
index 0000000..c54e784
--- /dev/null
+++ b/gen/src/namespace_organizer.rs
@@ -0,0 +1,40 @@
+use crate::syntax::Api;
+use proc_macro2::Ident;
+use std::collections::BTreeMap;
+
+pub(crate) struct NamespaceEntries<'a> {
+    pub(crate) entries: Vec<&'a Api>,
+    pub(crate) children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+}
+
+pub(crate) fn sort_by_namespace(apis: &[Api]) -> NamespaceEntries {
+    let api_refs = apis.iter().collect::<Vec<_>>();
+    sort_by_inner_namespace(api_refs, 0)
+}
+
+fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
+    let mut root = NamespaceEntries {
+        entries: Vec::new(),
+        children: BTreeMap::new(),
+    };
+
+    let mut kids_by_child_ns = BTreeMap::new();
+    for api in apis {
+        if let Some(ns) = api.get_namespace() {
+            let first_ns_elem = ns.iter().nth(depth);
+            if let Some(first_ns_elem) = first_ns_elem {
+                let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
+                list.push(api);
+                continue;
+            }
+        }
+        root.entries.push(api);
+    }
+
+    for (k, v) in kids_by_child_ns.into_iter() {
+        root.children
+            .insert(k, sort_by_inner_namespace(v, depth + 1));
+    }
+
+    root
+}
diff --git a/gen/src/out.rs b/gen/src/out.rs
index d42ea74..8a6bd86 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,10 +1,8 @@
 use crate::gen::include::Includes;
-use crate::syntax::namespace::Namespace;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
-    pub namespace: Namespace,
     pub header: bool,
     pub include: Includes,
     pub front: Content,
@@ -18,9 +16,8 @@ pub struct Content {
 }
 
 impl OutFile {
-    pub fn new(namespace: Namespace, header: bool) -> Self {
+    pub fn new(header: bool) -> Self {
         OutFile {
-            namespace,
             header,
             include: Includes::new(),
             front: Content::new(),
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3184604..2ff5b47 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,20 +1,17 @@
+use crate::gen::namespace_organizer::{sort_by_namespace, NamespaceEntries};
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
+    Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
-pub(super) fn gen(
-    namespace: &Namespace,
-    apis: &[Api],
-    types: &Types,
-    opt: &Opt,
-    header: bool,
-) -> OutFile {
-    let mut out_file = OutFile::new(namespace.clone(), header);
+pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> OutFile {
+    let mut out_file = OutFile::new(header);
     let out = &mut out_file;
 
     if header {
@@ -32,16 +29,36 @@ pub(super) fn gen(
     write_include_cxxbridge(out, apis, types);
 
     out.next_section();
-    for name in namespace {
-        writeln!(out, "namespace {} {{", name);
+
+    let apis_by_namespace = sort_by_namespace(apis);
+
+    gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
+
+    if !header {
+        out.next_section();
+        write_generic_instantiations(out, types);
     }
 
+    write!(out.front, "{}", out.include);
+
+    out_file
+}
+
+fn gen_namespace_contents(
+    ns_entries: &NamespaceEntries,
+    types: &Types,
+    opt: &Opt,
+    header: bool,
+    out: &mut OutFile,
+) {
+    let apis = &ns_entries.entries;
+
     out.next_section();
     for api in apis {
         match api {
-            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
-            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
             _ => {}
         }
     }
@@ -51,7 +68,7 @@ pub(super) fn gen(
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
-                    .entry(&receiver.ty)
+                    .entry(&receiver.ty.rust)
                     .or_insert_with(Vec::new)
                     .push(efn);
             }
@@ -62,22 +79,22 @@ pub(super) fn gen(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                if !types.cxx.contains(&strct.ident) {
-                    write_struct(out, strct);
+                if !types.cxx.contains(&strct.ident.rust) {
+                    write_struct(out, strct, types);
                 }
             }
             Api::Enum(enm) => {
                 out.next_section();
-                if types.cxx.contains(&enm.ident) {
+                if types.cxx.contains(&enm.ident.rust) {
                     check_enum(out, enm);
                 } else {
                     write_enum(out, enm);
                 }
             }
             Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.ident) {
+                if let Some(methods) = methods_for_type.get(&ety.ident.rust) {
                     out.next_section();
-                    write_struct_with_methods(out, ety, methods);
+                    write_struct_with_methods(out, ety, methods, types);
                 }
             }
             _ => {}
@@ -87,8 +104,8 @@ pub(super) fn gen(
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if types.required_trivial.contains_key(&ety.ident) {
-                check_trivial_extern_type(out, &ety.ident)
+            if types.required_trivial.contains_key(&ety.ident.rust) {
+                check_trivial_extern_type(out, &ety.ident.cxx)
             }
         }
     }
@@ -116,24 +133,18 @@ pub(super) fn gen(
     }
 
     out.next_section();
-    for name in namespace.iter().rev() {
-        writeln!(out, "}} // namespace {}", name);
-    }
 
-    if !header {
-        out.next_section();
-        write_generic_instantiations(out, types);
+    for (child_ns, child_ns_entries) in &ns_entries.children {
+        writeln!(out, "namespace {} {{", child_ns);
+        gen_namespace_contents(&child_ns_entries, types, opt, header, out);
+        writeln!(out, "}} // namespace {}", child_ns);
     }
-
-    write!(out.front, "{}", out.include);
-
-    out_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
+            Type::Ident(ident) => match Atom::from(&ident.rust) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
                 | Some(I64) => out.include.cstdint = true,
                 Some(Usize) => out.include.cstddef = true,
@@ -332,17 +343,17 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct) {
-    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, strct.ident);
+fn write_struct(out: &mut OutFile, strct: &Struct, types: &Types) {
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.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);
+    writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
     for field in &strct.fields {
         write!(out, "  ");
-        write_type_space(out, &field.ty);
+        write_type_space(out, &field.ty, types);
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
@@ -353,25 +364,39 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "struct {};", ident);
 }
 
-fn write_struct_using(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "using {} = {};", ident, ident);
+fn write_struct_using(out: &mut OutFile, ident: &CppName) {
+    writeln!(
+        out,
+        "using {} = {};",
+        ident.ident,
+        ident.to_fully_qualified()
+    );
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, ety.ident);
+fn write_struct_with_methods(
+    out: &mut OutFile,
+    ety: &ExternType,
+    methods: &[&ExternFn],
+    types: &Types,
+) {
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.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);
-    writeln!(out, "  {}() = delete;", ety.ident);
-    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
+    writeln!(out, "struct {} final {{", ety.ident.cxx.ident);
+    writeln!(out, "  {}() = delete;", ety.ident.cxx.ident);
+    writeln!(
+        out,
+        "  {}(const {} &) = delete;",
+        ety.ident.cxx.ident, ety.ident.cxx.ident
+    );
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.cxx.to_string();
-        write_rust_function_shim_decl(out, &local_name, sig, false);
+        let local_name = method.ident.cxx.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false, types);
         writeln!(out, ";");
     }
     writeln!(out, "}};");
@@ -379,13 +404,13 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    let guard = format!("CXXBRIDGE05_ENUM_{}{}", out.namespace, enm.ident);
+    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.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);
+    write!(out, "enum class {} : ", enm.ident.cxx.ident);
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
@@ -396,7 +421,11 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {
-    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident);
+    write!(
+        out,
+        "static_assert(sizeof({}) == sizeof(",
+        enm.ident.cxx.ident
+    );
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
@@ -405,12 +434,12 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident, variant.ident, variant.discriminant,
+            enm.ident.cxx.ident, variant.ident, variant.discriminant,
         );
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
     // 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:
@@ -429,6 +458,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     // not being recognized as such by the C++ type system due to a move
     // constructor or destructor.
 
+    let id = &id.to_fully_qualified();
     out.include.type_traits = true;
     writeln!(out, "static_assert(");
     writeln!(
@@ -450,7 +480,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     );
 }
 
-fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
         if let Api::CxxFunction(efn) = api {
@@ -486,13 +516,17 @@ fn write_cxx_function_shim(
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    let mangled = mangle::extern_fn(&out.namespace, efn);
+    let mangled = mangle::extern_fn(efn, types);
     write!(out, "{}(", mangled);
     if let Some(receiver) = &efn.receiver {
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ty);
+        write!(
+            out,
+            "{} &self",
+            types.resolve(&receiver.ty).to_fully_qualified()
+        );
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -510,21 +544,26 @@ fn write_cxx_function_shim(
         if !efn.args.is_empty() || efn.receiver.is_some() {
             write!(out, ", ");
         }
-        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap(), types);
         write!(out, "*return$");
     }
     writeln!(out, ") noexcept {{");
     write!(out, "  ");
-    write_return_type(out, &efn.ret);
+    write_return_type(out, &efn.ret, types);
     match &efn.receiver {
         None => write!(out, "(*{}$)(", efn.ident.rust),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident.rust),
+        Some(receiver) => write!(
+            out,
+            "({}::*{}$)(",
+            types.resolve(&receiver.ty).to_fully_qualified(),
+            efn.ident.rust
+        ),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
-        write_type(out, &arg.ty);
+        write_type(out, &arg.ty, types);
     }
     write!(out, ")");
     if let Some(receiver) = &efn.receiver {
@@ -534,8 +573,13 @@ fn write_cxx_function_shim(
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident.cxx),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident.cxx),
+        None => write!(out, "{}", efn.ident.cxx.to_fully_qualified()),
+        Some(receiver) => write!(
+            out,
+            "&{}::{}",
+            types.resolve(&receiver.ty).to_fully_qualified(),
+            efn.ident.cxx.ident
+        ),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -548,7 +592,7 @@ fn write_cxx_function_shim(
     if indirect_return {
         out.include.new = true;
         write!(out, "new (return$) ");
-        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap(), types);
         write!(out, "(");
     } else if efn.ret.is_some() {
         write!(out, "return ");
@@ -570,10 +614,10 @@ fn write_cxx_function_shim(
             write!(out, ", ");
         }
         if let Type::RustBox(_) = &arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "::from_raw({})", arg.ident);
         } else if let Type::UniquePtr(_) = &arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "({})", arg.ident);
         } else if arg.ty == RustString {
             write!(
@@ -582,7 +626,7 @@ fn write_cxx_function_shim(
                 arg.ident,
             );
         } else if let Type::RustVec(_) = arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
@@ -632,17 +676,17 @@ fn write_function_pointer_trampoline(
     types: &Types,
 ) {
     out.next_section();
-    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
+    let r_trampoline = mangle::r_trampoline(efn, var, types);
     let indirect_call = true;
     write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
 
     out.next_section();
-    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
+    let c_trampoline = mangle::c_trampoline(efn, var, types).to_string();
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
-    let link_name = mangle::extern_fn(&out.namespace, efn);
+    let link_name = mangle::extern_fn(efn, types);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -665,7 +709,11 @@ fn write_rust_function_decl_impl(
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ty);
+        write!(
+            out,
+            "{} &self",
+            types.resolve(&receiver.ty).to_fully_qualified()
+        );
         needs_comma = true;
     }
     for arg in &sig.args {
@@ -679,7 +727,7 @@ fn write_rust_function_decl_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &sig.ret);
+        write_return_type(out, &sig.ret, types);
         write!(out, "*return$");
         needs_comma = true;
     }
@@ -697,10 +745,14 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.cxx.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
+        None => efn.ident.cxx.ident.to_string(),
+        Some(receiver) => format!(
+            "{}::{}",
+            types.resolve(&receiver.ty).ident,
+            efn.ident.cxx.ident
+        ),
     };
-    let invoke = mangle::extern_fn(&out.namespace, efn);
+    let invoke = mangle::extern_fn(efn, types);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
@@ -710,14 +762,15 @@ fn write_rust_function_shim_decl(
     local_name: &str,
     sig: &Signature,
     indirect_call: bool,
+    types: &Types,
 ) {
-    write_return_type(out, &sig.ret);
+    write_return_type(out, &sig.ret, types);
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
-        write_type_space(out, &arg.ty);
+        write_type_space(out, &arg.ty, types);
         write!(out, "{}", arg.ident);
     }
     if indirect_call {
@@ -749,7 +802,7 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call, types);
     if out.header {
         writeln!(out, ";");
         return;
@@ -759,7 +812,7 @@ fn write_rust_function_shim_impl(
         if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "  ::rust::ManuallyDrop<");
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             writeln!(out, "> {}$(::std::move({0}));", arg.ident);
         }
     }
@@ -767,18 +820,18 @@ fn write_rust_function_shim_impl(
     let indirect_return = indirect_return(sig, types);
     if indirect_return {
         write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
+        write_type(out, sig.ret.as_ref().unwrap(), types);
         writeln!(out, "> return$;");
         write!(out, "  ");
     } else if let Some(ret) = &sig.ret {
         write!(out, "return ");
         match ret {
             Type::RustBox(_) => {
-                write_type(out, ret);
+                write_type(out, ret, types);
                 write!(out, "::from_raw(");
             }
             Type::UniquePtr(_) => {
-                write_type(out, ret);
+                write_type(out, ret, types);
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
@@ -844,10 +897,10 @@ fn write_rust_function_shim_impl(
     writeln!(out, "}}");
 }
 
-fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
+fn write_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         None => write!(out, "void "),
-        Some(ty) => write_type_space(out, ty),
+        Some(ty) => write_type_space(out, ty, types),
     }
 }
 
@@ -857,27 +910,27 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type, types: &Types) {
     match ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Type::Ref(ty) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, " *");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr"),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
-        _ => write_type(out, ty),
+        _ => write_type(out, ty, types),
     }
 }
 
-fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
-    write_indirect_return_type(out, ty);
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
+    write_indirect_return_type(out, ty, types);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
         Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
@@ -888,32 +941,32 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
 fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Some(Type::Ref(ty)) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, " *");
         }
         Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
-        _ => write_return_type(out, ty),
+        _ => write_return_type(out, ty, types),
     }
 }
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        _ => write_type_space(out, &arg.ty),
+        _ => write_type_space(out, &arg.ty, types),
     }
     if types.needs_indirect_abi(&arg.ty) {
         write!(out, "*");
@@ -921,37 +974,37 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     write!(out, "{}", arg.ident);
 }
 
-fn write_type(out: &mut OutFile, ty: &Type) {
+fn write_type(out: &mut OutFile, ty: &Type, types: &Types) {
     match ty {
-        Type::Ident(ident) => match Atom::from(ident) {
+        Type::Ident(ident) => match Atom::from(&ident.rust) {
             Some(atom) => write_atom(out, atom),
-            None => write!(out, "{}", ident),
+            None => write!(out, "{}", types.resolve(ident).to_fully_qualified()),
         },
         Type::RustBox(ty) => {
             write!(out, "::rust::Box<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::RustVec(ty) => {
             write!(out, "::rust::Vec<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::UniquePtr(ptr) => {
             write!(out, "::std::unique_ptr<");
-            write_type(out, &ptr.inner);
+            write_type(out, &ptr.inner, types);
             write!(out, ">");
         }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::Ref(r) => {
             if r.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &r.inner);
+            write_type(out, &r.inner, types);
             write!(out, " &");
         }
         Type::Slice(_) => {
@@ -967,7 +1020,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
             match &f.ret {
-                Some(ret) => write_type(out, ret),
+                Some(ret) => write_type(out, ret, types),
                 None => write!(out, "void"),
             }
             write!(out, "(");
@@ -975,7 +1028,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
                 if i > 0 {
                     write!(out, ", ");
                 }
-                write_type(out, &arg.ty);
+                write_type(out, &arg.ty, types);
             }
             write!(out, ")>");
         }
@@ -1003,8 +1056,8 @@ fn write_atom(out: &mut OutFile, atom: Atom) {
     }
 }
 
-fn write_type_space(out: &mut OutFile, ty: &Type) {
-    write_type(out, ty);
+fn write_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
+    write_type(out, ty, types);
     write_space_after_type(out, ty);
 }
 
@@ -1025,28 +1078,20 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 // Only called for legal referent types of unique_ptr and element types of
 // std::vector and Vec.
-fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+fn to_typename(ty: &Type, types: &Types) -> String {
     match ty {
-        Type::Ident(ident) => {
-            let mut path = String::new();
-            for name in namespace {
-                path += &name.to_string();
-                path += "::";
-            }
-            path += &ident.to_string();
-            path
-        }
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
         _ => unreachable!(),
     }
 }
 
 // Only called for legal referent types of unique_ptr and element types of
 // std::vector and Vec.
-fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+fn to_mangled(ty: &Type, types: &Types) -> Symbol {
     match ty {
-        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
-        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        Type::Ident(ident) => ident.to_symbol(types),
+        Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
         _ => unreachable!(),
     }
 }
@@ -1057,19 +1102,20 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
                 out.next_section();
-                write_rust_box_extern(out, inner);
+                write_rust_box_extern(out, &types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
+                if Atom::from(&inner.rust).is_none() {
                     out.next_section();
-                    write_rust_vec_extern(out, inner);
+                    write_rust_vec_extern(out, inner, types);
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none()
-                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                if Atom::from(&inner.rust).is_none()
+                    && (!types.aliases.contains_key(&inner.rust)
+                        || types.explicit_impls.contains(ty))
                 {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
@@ -1077,8 +1123,9 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none()
-                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                if Atom::from(&inner.rust).is_none()
+                    && (!types.aliases.contains_key(&inner.rust)
+                        || types.explicit_impls.contains(ty))
                 {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
@@ -1093,12 +1140,12 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, inner);
+                write_rust_box_impl(out, &types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    write_rust_vec_impl(out, inner);
+                if Atom::from(&inner.rust).is_none() {
+                    write_rust_vec_impl(out, inner, types);
                 }
             }
         }
@@ -1107,14 +1154,9 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += &name.to_string();
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
+    let inner = ident.to_fully_qualified();
+    let instance = ident.to_symbol();
 
     writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
@@ -1131,10 +1173,10 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
@@ -1166,14 +1208,9 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += &name.to_string();
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
+    let inner = ident.to_fully_qualified();
+    let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
@@ -1186,10 +1223,10 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
@@ -1225,9 +1262,9 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName, types: &Types) {
     let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&out.namespace, &ty);
+    let instance = to_mangled(&ty, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
@@ -1241,8 +1278,8 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
 fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.new = true;
     out.include.utility = true;
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
+    let inner = to_typename(ty, types);
+    let instance = to_mangled(ty, types);
 
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types. We can't
@@ -1250,7 +1287,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         Type::Ident(ident) => {
-            types.structs.contains_key(ident) || types.aliases.contains_key(ident)
+            types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust)
         }
         _ => false,
     };
@@ -1315,10 +1352,10 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4a4ec64..1bcaa1e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,11 @@
 use crate::derive::DeriveAttribute;
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::file::Module;
-use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Signature, Struct, Type, TypeAlias,
-    Types,
+    self, check, mangle, Api, CppName, Enum, ExternFn, ExternType, Impl, ResolvableName, Signature,
+    Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -17,11 +16,11 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
     let content = mem::take(&mut ffi.content);
     let trusted = ffi.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, content, trusted);
+    let namespace = &ffi.namespace;
+    let ref apis = syntax::parse_items(errors, content, trusted, namespace);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
-    let namespace = &ffi.namespace;
-    check::typecheck(errors, namespace, apis, types);
+    check::typecheck(errors, apis, types);
     errors.propagate()?;
 
     Ok(expand(ffi, apis, types))
@@ -30,7 +29,6 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
 fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
-    let namespace = &ffi.namespace;
 
     for api in apis {
         if let Api::RustType(ety) = api {
@@ -42,23 +40,23 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(namespace, strct)),
-            Api::Enum(enm) => expanded.extend(expand_enum(namespace, enm)),
+            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.ident;
-                if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
-                    expanded.extend(expand_cxx_type(namespace, ety));
+                if !types.structs.contains_key(&ident.rust)
+                    && !types.enums.contains_key(&ident.rust)
+                {
+                    expanded.extend(expand_cxx_type(ety));
                 }
             }
             Api::CxxFunction(efn) => {
-                expanded.extend(expand_cxx_function_shim(namespace, efn, types));
-            }
-            Api::RustFunction(efn) => {
-                hidden.extend(expand_rust_function_shim(namespace, efn, types))
+                expanded.extend(expand_cxx_function_shim(efn, types));
             }
+            Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
-                hidden.extend(expand_type_alias_verify(namespace, alias, types));
+                hidden.extend(expand_type_alias_verify(alias, types));
             }
         }
     }
@@ -67,33 +65,33 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(ident).is_none() {
-                    hidden.extend(expand_rust_box(namespace, ident));
+                if Atom::from(&ident.rust).is_none() {
+                    hidden.extend(expand_rust_box(ident, types));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(ident).is_none() {
-                    hidden.extend(expand_rust_vec(namespace, ident));
+                if Atom::from(&ident.rust).is_none() {
+                    hidden.extend(expand_rust_vec(ident, types));
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types, explicit_impl));
+                    expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
-                    expanded.extend(expand_cxx_vector(namespace, ident, explicit_impl));
+                    expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
                 }
             }
         }
@@ -126,11 +124,12 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 }
 
-fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
-    let ident = &strct.ident;
+fn expand_struct(strct: &Struct) -> TokenStream {
+    let ident = &strct.ident.rust;
+    let cxx_ident = &strct.ident.cxx;
     let doc = &strct.doc;
     let derives = DeriveAttribute(&strct.derives);
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(cxx_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,12 @@ fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
     }
 }
 
-fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
-    let ident = &enm.ident;
+fn expand_enum(enm: &Enum) -> TokenStream {
+    let ident = &enm.ident.rust;
+    let cxx_ident = &enm.ident.cxx;
     let doc = &enm.doc;
     let repr = enm.repr;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(cxx_ident);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -186,10 +186,11 @@ fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
     }
 }
 
-fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
-    let ident = &ety.ident;
+fn expand_cxx_type(ety: &ExternType) -> TokenStream {
+    let ident = &ety.ident.rust;
+    let cxx_ident = &ety.ident.cxx;
     let doc = &ety.doc;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(&cxx_ident);
 
     quote! {
         #doc
@@ -205,7 +206,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
     }
 }
 
-fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
+fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
         quote!(_: #receiver_type)
@@ -236,7 +237,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = mangle::extern_fn(namespace, efn);
+    let link_name = mangle::extern_fn(efn, types);
     let local_name = format_ident!("__{}", efn.ident.rust);
     quote! {
         #[link_name = #link_name]
@@ -244,9 +245,9 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     }
 }
 
-fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
+fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
-    let decl = expand_cxx_function_decl(namespace, efn, types);
+    let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
         let ampersand = receiver.ampersand;
         let mutability = receiver.mutability;
@@ -272,14 +273,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let arg_vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
-            Type::Ident(ident) if ident == RustString => {
+            Type::Ident(ident) if ident.rust == RustString => {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => quote!(::cxx::private::RustString::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
                 },
@@ -306,9 +307,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         .filter_map(|arg| {
             if let Type::Fn(f) = &arg.ty {
                 let var = &arg.ident;
-                Some(expand_function_pointer_trampoline(
-                    namespace, efn, var, f, types,
-                ))
+                Some(expand_function_pointer_trampoline(efn, var, f, types))
             } else {
                 None
             }
@@ -355,7 +354,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     };
     let expr = if efn.throws {
         efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => {
+            Type::Ident(ident) if ident.rust == RustString => {
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
@@ -368,7 +367,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_string()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
                 },
@@ -388,7 +387,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     } else {
         efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
+            Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
             Type::RustVec(vec) => {
                 if vec.inner == RustString {
@@ -399,7 +398,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => Some(quote!(#call.as_string())),
                     Some(_) => Some(quote!(#call.as_mut_string())),
                 },
@@ -445,14 +444,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
 }
 
 fn expand_function_pointer_trampoline(
-    namespace: &Namespace,
     efn: &ExternFn,
     var: &Ident,
     sig: &Signature,
     types: &Types,
 ) -> TokenStream {
-    let c_trampoline = mangle::c_trampoline(namespace, efn, var);
-    let r_trampoline = mangle::r_trampoline(namespace, efn, var);
+    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.ident.rust, var);
     let shim = expand_rust_function_shim_impl(
@@ -500,7 +498,7 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     let sized = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Sized
     };
-    quote_spanned! {ident.span()=>
+    quote_spanned! {ident.rust.span()=>
         let _ = {
             fn __AssertSized<T: ?#sized + #sized>() {}
             __AssertSized::<#ident>
@@ -508,8 +506,8 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     }
 }
 
-fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let link_name = mangle::extern_fn(namespace, efn);
+fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
+    let link_name = mangle::extern_fn(efn, types);
     let local_name = format_ident!("__{}", efn.ident.rust);
     let catch_unwind_label = format!("::{}", efn.ident.rust);
     let invoke = Some(&efn.ident.rust);
@@ -553,7 +551,7 @@ fn expand_rust_function_shim_impl(
     let arg_vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
-            Type::Ident(i) if i == RustString => {
+            Type::Ident(i) if i.rust == RustString => {
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
@@ -566,7 +564,7 @@ fn expand_rust_function_shim_impl(
             }
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i == RustString => match ty.mutability {
+                Type::Ident(i) if i.rust == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
                     Some(_) => quote!(#ident.as_mut_string()),
                 },
@@ -601,7 +599,9 @@ fn expand_rust_function_shim_impl(
     call.extend(quote! { (#(#vars),*) });
 
     let conversion = sig.ret.as_ref().and_then(|ret| match ret {
-        Type::Ident(ident) if ident == RustString => Some(quote!(::cxx::private::RustString::from)),
+        Type::Ident(ident) if ident.rust == RustString => {
+            Some(quote!(::cxx::private::RustString::from))
+        }
         Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw)),
         Type::RustVec(vec) => {
             if vec.inner == RustString {
@@ -612,7 +612,7 @@ fn expand_rust_function_shim_impl(
         }
         Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
         Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident == RustString => match ty.mutability {
+            Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                 None => Some(quote!(::cxx::private::RustString::from_ref)),
                 Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
             },
@@ -686,13 +686,9 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     }
 }
 
-fn expand_type_alias_verify(
-    namespace: &Namespace,
-    alias: &TypeAlias,
-    types: &Types,
-) -> TokenStream {
+fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
     let ident = &alias.ident;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(&ident.cxx);
     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::<);
@@ -702,7 +698,7 @@ fn expand_type_alias_verify(
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial.contains_key(&alias.ident) {
+    if types.required_trivial.contains_key(&alias.ident.rust) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
@@ -712,25 +708,19 @@ fn expand_type_alias_verify(
     verify
 }
 
-fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let mut path = String::new();
-    for name in namespace {
-        path += &name.to_string();
-        path += "::";
-    }
-    path += &ident.to_string();
-
+fn type_id(ident: &CppName) -> TokenStream {
+    let path = ident.to_fully_qualified();
     quote! {
         ::cxx::type_id!(#path)
     }
 }
 
-fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$box${}{}$", namespace, ident);
+fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
+    let link_prefix = format!("cxxbridge05$box${}$", types.resolve(ident).to_symbol());
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
-    let local_prefix = format_ident!("{}__box_", ident);
+    let local_prefix = format_ident!("{}__box_", &ident.rust);
     let local_uninit = format_ident!("{}uninit", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
@@ -754,15 +744,15 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$rust_vec${}{}$", namespace, elem);
+fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
+    let link_prefix = format!("cxxbridge05$rust_vec${}$", elem.to_symbol(types));
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", elem);
+    let local_prefix = format_ident!("{}__vec_", elem.rust);
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
@@ -800,13 +790,12 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
 }
 
 fn expand_unique_ptr(
-    namespace: &Namespace,
-    ident: &Ident,
+    ident: &ResolvableName,
     types: &Types,
     explicit_impl: Option<&Impl>,
 ) -> TokenStream {
-    let name = ident.to_string();
-    let prefix = format!("cxxbridge05$unique_ptr${}{}$", namespace, ident);
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge05$unique_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -814,21 +803,22 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
-        Some(quote! {
-            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
-                extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+    let new_method =
+        if types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust) {
+            Some(quote! {
+                fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+                    extern "C" {
+                        #[link_name = #link_new]
+                        fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+                    }
+                    let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                    unsafe { __new(&mut repr, &mut value) }
+                    repr
                 }
-                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __new(&mut repr, &mut value) }
-                repr
-            }
-        })
-    } else {
-        None
-    };
+            })
+        } else {
+            None
+        };
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -883,16 +873,19 @@ fn expand_unique_ptr(
 }
 
 fn expand_cxx_vector(
-    namespace: &Namespace,
-    elem: &Ident,
+    elem: &ResolvableName,
     explicit_impl: Option<&Impl>,
+    types: &Types,
 ) -> TokenStream {
     let _ = explicit_impl;
-    let name = elem.to_string();
-    let prefix = format!("cxxbridge05$std$vector${}{}$", namespace, elem);
+    let name = elem.rust.to_string();
+    let prefix = format!("cxxbridge05$std$vector${}$", elem.to_symbol(types));
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge05$unique_ptr$std$vector${}{}$", namespace, elem);
+    let unique_ptr_prefix = format!(
+        "cxxbridge05$unique_ptr$std$vector${}$",
+        elem.to_symbol(types)
+    );
     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);
@@ -979,7 +972,7 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
     match ty {
-        Type::Ident(ident) if ident == RustString => quote!(::cxx::private::RustString),
+        Type::Ident(ident) if ident.rust == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
             let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
@@ -991,7 +984,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
         Type::Ref(ty) => {
             let mutability = ty.mutability;
             match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
+                Type::Ident(ident) if ident.rust == RustString => {
                     quote!(&#mutability ::cxx::private::RustString)
                 }
                 Type::RustVec(ty) => {
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 6e5fa88..7d0ef6b 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -81,7 +81,7 @@ impl AsRef<str> for Atom {
 impl PartialEq<Atom> for Type {
     fn eq(&self, atom: &Atom) -> bool {
         match self {
-            Type::Ident(ident) => ident == atom,
+            Type::Ident(ident) => ident.rust == atom,
             _ => false,
         }
     }
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 4c8a3e5..25af229 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,3 +1,4 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
@@ -12,19 +13,7 @@ pub struct Parser<'a> {
     pub repr: Option<&'a mut Option<Atom>>,
     pub cxx_name: Option<&'a mut Option<Ident>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
-}
-
-pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
-    let mut doc = Doc::new();
-    parse(
-        cx,
-        attrs,
-        Parser {
-            doc: Some(&mut doc),
-            ..Parser::default()
-        },
-    );
-    doc
+    pub namespace: Option<&'a mut Namespace>,
 }
 
 pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
@@ -79,6 +68,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("namespace") {
+            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(namespace) = &mut parser.namespace {
+                        **namespace = attr;
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -131,3 +130,10 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
         input.parse()
     }
 }
+
+fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
+    let content;
+    syn::parenthesized!(content in input);
+    let namespace = content.parse::<Namespace>()?;
+    Ok(namespace)
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index ced1570..9aba9ac 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,4 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
@@ -11,15 +10,13 @@ use quote::{quote, ToTokens};
 use std::fmt::Display;
 
 pub(crate) struct Check<'a> {
-    namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
     errors: &'a mut Errors,
 }
 
-pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], types: &Types) {
+pub(crate) fn typecheck(cx: &mut Errors, apis: &[Api], types: &Types) {
     do_typecheck(&mut Check {
-        namespace,
         apis,
         types,
         errors: cx,
@@ -27,11 +24,11 @@ pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], ty
 }
 
 fn do_typecheck(cx: &mut Check) {
-    ident::check_all(cx, cx.namespace, cx.apis);
+    ident::check_all(cx, cx.apis);
 
     for ty in cx.types {
         match ty {
-            Type::Ident(ident) => check_type_ident(cx, ident),
+            Type::Ident(ident) => check_type_ident(cx, &ident.rust),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
@@ -67,20 +64,20 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
-        cx.error(ident, &format!("unsupported type: {}", ident));
+        cx.error(ident, &format!("unsupported type: {}", ident.to_string()));
     }
 }
 
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
+        if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.structs.contains_key(&ident.rust)
+            && !cx.types.enums.contains_key(&ident.rust)
         {
             cx.error(ptr, error::BOX_CXX_TYPE.msg);
         }
 
-        if Atom::from(ident).is_none() {
+        if Atom::from(&ident.rust).is_none() {
             return;
         }
     }
@@ -90,15 +87,15 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
+        if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.structs.contains_key(&ident.rust)
+            && !cx.types.enums.contains_key(&ident.rust)
         {
             cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(RustString) => return,
@@ -112,11 +109,11 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
 
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.rust.contains(ident) {
+        if cx.types.rust.contains(&ident.rust) {
             cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(CxxString) => return,
             _ => {}
         }
@@ -129,14 +126,14 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.rust.contains(ident) {
+        if cx.types.rust.contains(&ident.rust) {
             cx.error(
                 ptr,
                 "C++ vector containing a Rust type is not supported yet",
             );
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(CxxString) => return,
@@ -170,15 +167,15 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
     let ident = &strct.ident;
-    check_reserved_name(cx, ident);
+    check_reserved_name(cx, &ident.rust);
 
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
     }
 
-    if cx.types.cxx.contains(ident) {
-        if let Some(ety) = cx.types.untrusted.get(ident) {
+    if cx.types.cxx.contains(&ident.rust) {
+        if let Some(ety) = cx.types.untrusted.get(&ident.rust) {
             let msg = "extern shared struct must be declared in an `unsafe extern` block";
             cx.error(ety, msg);
         }
@@ -200,7 +197,7 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 }
 
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
-    check_reserved_name(cx, &enm.ident);
+    check_reserved_name(cx, &enm.ident.rust);
 
     if enm.variants.is_empty() {
         let span = span_for_enum_error(enm);
@@ -209,11 +206,13 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 }
 
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
-    check_reserved_name(cx, &ety.ident);
+    check_reserved_name(cx, &ety.ident.rust);
 
-    if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
+    if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
         let what = match reason {
-            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
+            TrivialReason::StructField(strct) => {
+                format!("a field of `{}`", strct.ident.cxx.to_fully_qualified())
+            }
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
@@ -229,7 +228,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
         let ref span = span_for_receiver_error(receiver);
 
-        if receiver.ty == "Self" {
+        if receiver.ty.is_self() {
             let mutability = match receiver.mutability {
                 Some(_) => "mut ",
                 None => "",
@@ -241,9 +240,9 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 mutability = mutability,
             );
             cx.error(span, msg);
-        } else if !cx.types.structs.contains_key(&receiver.ty)
-            && !cx.types.cxx.contains(&receiver.ty)
-            && !cx.types.rust.contains(&receiver.ty)
+        } else if !cx.types.structs.contains_key(&receiver.ty.rust)
+            && !cx.types.cxx.contains(&receiver.ty.rust)
+            && !cx.types.rust.contains(&receiver.ty.rust)
         {
             cx.error(span, "unrecognized receiver type");
         }
@@ -290,7 +289,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
     if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
         if let Type::Ident(inner) = &ty.inner {
-            if Atom::from(inner).is_none() {
+            if Atom::from(&inner.rust).is_none() {
                 return;
             }
         }
@@ -357,7 +356,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
-        Type::Ident(ident) => ident,
+        Type::Ident(ident) => &ident.rust,
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
@@ -400,20 +399,20 @@ fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
 fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
-            if cx.types.structs.contains_key(ident) {
+            if cx.types.structs.contains_key(&ident.rust) {
                 "struct".to_owned()
-            } else if cx.types.enums.contains_key(ident) {
+            } else if cx.types.enums.contains_key(&ident.rust) {
                 "enum".to_owned()
-            } else if cx.types.aliases.contains_key(ident) {
+            } else if cx.types.aliases.contains_key(&ident.rust) {
                 "C++ type".to_owned()
-            } else if cx.types.cxx.contains(ident) {
+            } else if cx.types.cxx.contains(&ident.rust) {
                 "opaque C++ type".to_owned()
-            } else if cx.types.rust.contains(ident) {
+            } else if cx.types.rust.contains(&ident.rust) {
                 "opaque Rust type".to_owned()
-            } else if Atom::from(ident) == Some(CxxString) {
+            } else if Atom::from(&ident.rust) == Some(CxxString) {
                 "C++ string".to_owned()
             } else {
-                ident.to_string()
+                ident.rust.to_string()
             }
         }
         Type::RustBox(_) => "Box".to_owned(),
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 66f7365..354790a 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,6 +1,5 @@
 use crate::syntax::check::Check;
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{error, Api};
+use crate::syntax::{error, Api, CppName};
 use proc_macro2::Ident;
 
 fn check(cx: &mut Check, ident: &Ident) {
@@ -13,28 +12,31 @@ fn check(cx: &mut Check, ident: &Ident) {
     }
 }
 
-pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
-    for segment in namespace {
+fn check_ident(cx: &mut Check, ident: &CppName) {
+    for segment in &ident.ns {
         check(cx, segment);
     }
+    check(cx, &ident.ident);
+}
 
+pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
     for api in apis {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
-                check(cx, &strct.ident);
+                check_ident(cx, &strct.ident.cxx);
                 for field in &strct.fields {
                     check(cx, &field.ident);
                 }
             }
             Api::Enum(enm) => {
-                check(cx, &enm.ident);
+                check_ident(cx, &enm.ident.cxx);
                 for variant in &enm.variants {
                     check(cx, &variant.ident);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                check(cx, &ety.ident);
+                check_ident(cx, &ety.ident.cxx);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                 check(cx, &efn.ident.rust);
@@ -43,7 +45,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                 }
             }
             Api::TypeAlias(alias) => {
-                check(cx, &alias.ident);
+                check_ident(cx, &alias.ident.cxx);
             }
         }
     }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6a177d5..a83ce74 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,8 +1,13 @@
-use crate::syntax::{ExternFn, Impl, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{
+    Api, CppName, ExternFn, Impl, Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice,
+    Symbol, Ty1, Type, Types,
+};
+use proc_macro2::{Ident, Span};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
+use syn::Token;
 
 impl Deref for ExternFn {
     type Target = Signature;
@@ -274,3 +279,84 @@ impl Borrow<Type> for &Impl {
         &self.ty
     }
 }
+
+impl Pair {
+    /// Use this constructor when the item can't have a different
+    /// name in Rust and C++. For cases where #[rust_name] and similar
+    /// attributes can be used, construct the object by hand.
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self {
+            rust: ident.clone(),
+            cxx: CppName::new(ns, ident),
+        }
+    }
+}
+
+impl ResolvableName {
+    pub fn new(ident: Ident) -> Self {
+        Self { rust: ident }
+    }
+
+    pub fn from_pair(pair: Pair) -> Self {
+        Self { rust: pair.rust }
+    }
+
+    pub fn make_self(span: Span) -> Self {
+        Self {
+            rust: Token![Self](span).into(),
+        }
+    }
+
+    pub fn is_self(&self) -> bool {
+        self.rust == "Self"
+    }
+
+    pub fn span(&self) -> Span {
+        self.rust.span()
+    }
+
+    pub fn to_symbol(&self, types: &Types) -> Symbol {
+        types.resolve(self).to_symbol()
+    }
+}
+
+impl Api {
+    pub fn get_namespace(&self) -> Option<&Namespace> {
+        match self {
+            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
+            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
+            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
+            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
+            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
+            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
+            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
+        }
+    }
+}
+
+impl CppName {
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self { ns, ident }
+    }
+
+    fn iter_all_segments(
+        &self,
+    ) -> std::iter::Chain<std::slice::Iter<Ident>, std::iter::Once<&Ident>> {
+        self.ns.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/mangle.rs b/syntax/mangle.rs
index e461887..9255feb 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,6 +1,5 @@
-use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::{self, Symbol};
-use crate::syntax::ExternFn;
+use crate::syntax::{ExternFn, Types};
 use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge05";
@@ -11,19 +10,27 @@ macro_rules! join {
     };
 }
 
-pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
+pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
     match &efn.receiver {
-        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident.rust),
-        None => join!(namespace, CXXBRIDGE, efn.ident.rust),
+        Some(receiver) => {
+            let receiver_ident = types.resolve(&receiver.ty);
+            join!(
+                efn.ident.cxx.ns,
+                CXXBRIDGE,
+                receiver_ident.ident,
+                efn.ident.rust
+            )
+        }
+        None => join!(efn.ident.cxx.ns, CXXBRIDGE, efn.ident.rust),
     }
 }
 
 // The C half of a function pointer trampoline.
-pub fn c_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
-    join!(extern_fn(namespace, efn), var, 0)
+pub fn c_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var, 0)
 }
 
 // The Rust half of a function pointer trampoline.
-pub fn r_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
-    join!(extern_fn(namespace, efn), var, 1)
+pub fn r_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var, 1)
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c8dea67..bb9566d 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -21,7 +21,9 @@ mod tokens;
 pub mod types;
 
 use self::discriminant::Discriminant;
+use self::namespace::Namespace;
 use self::parse::kw;
+use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
@@ -33,6 +35,29 @@ pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
+/// A Rust identifier will forver == a proc_macro2::Ident,
+/// but for completeness here's a type alias.
+pub type RsIdent = Ident;
+
+/// At the moment, a Rust name is simply a proc_macro2::Ident.
+/// In the future, it may become namespaced based on a mod path.
+pub type RsName = RsIdent;
+
+/// At the moment, a C++ identifier is also a proc_macro2::Ident.
+/// In the future, we may wish to make a newtype wrapper here
+/// to avoid confusion between C++ and Rust identifiers.
+pub type CppIdent = Ident;
+
+#[derive(Clone)]
+/// 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 unqualfiied name.
+pub struct CppName {
+    pub ns: Namespace,
+    pub ident: CppIdent,
+}
+
 pub enum Api {
     Include(String),
     Struct(Struct),
@@ -48,7 +73,7 @@ pub enum Api {
 pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Ident,
+    pub ident: Pair,
     pub semi_token: Token![;],
     pub trusted: bool,
 }
@@ -57,7 +82,7 @@ pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub struct_token: Token![struct],
-    pub ident: Ident,
+    pub ident: Pair,
     pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
@@ -65,15 +90,18 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub enum_token: Token![enum],
-    pub ident: Ident,
+    pub ident: Pair,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
 }
 
+/// A type with a defined Rust name and a fully resolved,
+/// qualified, namespaced, C++ name.
+#[derive(Clone)]
 pub struct Pair {
-    pub cxx: Ident,
-    pub rust: Ident,
+    pub cxx: CppName,
+    pub rust: RsName,
 }
 
 pub struct ExternFn {
@@ -87,7 +115,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Ident,
+    pub ident: Pair,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
@@ -112,7 +140,7 @@ pub struct Signature {
 
 #[derive(Eq, PartialEq, Hash)]
 pub struct Var {
-    pub ident: Ident,
+    pub ident: RsIdent, // fields and variables are not namespaced
     pub ty: Type,
 }
 
@@ -121,18 +149,18 @@ pub struct Receiver {
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
-    pub ty: Ident,
+    pub ty: ResolvableName,
     pub shorthand: bool,
 }
 
 pub struct Variant {
-    pub ident: Ident,
+    pub ident: RsIdent,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
 }
 
 pub enum Type {
-    Ident(Ident),
+    Ident(ResolvableName),
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
@@ -146,7 +174,7 @@ pub enum Type {
 }
 
 pub struct Ty1 {
-    pub name: Ident,
+    pub name: ResolvableName,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
@@ -169,3 +197,10 @@ pub enum Lang {
     Cxx,
     Rust,
 }
+
+/// Wrapper for a type which needs to be resolved
+/// before it can be printed in C++.
+#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
+pub struct ResolvableName {
+    pub rust: RsName,
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 367ad05..0a86b6c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,8 +3,8 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
-    Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, CppName, Doc, Enum, ExternFn, ExternType, Impl, Lang, Namespace, Pair,
+    Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -20,20 +20,22 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api> {
+pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool, ns: &Namespace) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(cx, item) {
+            Item::Struct(item) => match parse_struct(cx, item, ns.clone()) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item) {
+            Item::Enum(item) => match parse_enum(cx, item, ns.clone()) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
-            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
-            Item::Impl(item) => match parse_impl(item) {
+            Item::ForeignMod(foreign_mod) => {
+                parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, ns)
+            }
+            Item::Impl(item) => match parse_impl(item, ns) {
                 Ok(imp) => apis.push(imp),
                 Err(err) => cx.push(err),
             },
@@ -44,7 +46,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api>
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -65,6 +67,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -81,7 +84,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         doc,
         derives,
         struct_token: item.struct_token,
-        ident: item.ident,
+        ident: Pair::new(ns.clone(), item.ident),
         brace_token: fields.brace_token,
         fields: fields
             .named
@@ -89,14 +92,14 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
             .map(|field| {
                 Ok(Var {
                     ident: field.ident.unwrap(),
-                    ty: parse_type(&field.ty)?,
+                    ty: parse_type(&field.ty, &ns)?,
                 })
             })
             .collect::<Result<_>>()?,
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, mut ns: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -117,6 +120,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             repr: Some(&mut repr),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -167,7 +171,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
-        ident: item.ident,
+        ident: Pair::new(ns, item.ident),
         brace_token,
         variants,
         repr,
@@ -179,6 +183,7 @@ fn parse_foreign_mod(
     foreign_mod: ItemForeignMod,
     out: &mut Vec<Api>,
     trusted: bool,
+    ns: &Namespace,
 ) {
     let lang = match parse_lang(&foreign_mod.abi) {
         Ok(lang) => lang,
@@ -202,11 +207,13 @@ fn parse_foreign_mod(
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang, trusted) {
-                Ok(ety) => items.push(ety),
-                Err(err) => cx.push(err),
-            },
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang) {
+            ForeignItem::Type(foreign) => {
+                match parse_extern_type(cx, foreign, lang, trusted, ns.clone()) {
+                    Ok(ety) => items.push(ety),
+                    Err(err) => cx.push(err),
+                }
+            }
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, ns.clone()) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -216,10 +223,12 @@ fn parse_foreign_mod(
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(cx, tokens, lang) {
-                Ok(api) => items.push(api),
-                Err(err) => cx.push(err),
-            },
+            ForeignItem::Verbatim(tokens) => {
+                match parse_extern_verbatim(cx, tokens, lang, ns.clone()) {
+                    Ok(api) => items.push(api),
+                    Err(err) => cx.push(err),
+                }
+            }
             _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
@@ -234,8 +243,8 @@ fn parse_foreign_mod(
         for item in &mut items {
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
-                    if receiver.ty == "Self" {
-                        receiver.ty = single_type.clone();
+                    if receiver.ty.is_self() {
+                        receiver.ty = ResolvableName::from_pair(single_type.clone());
                     }
                 }
             }
@@ -267,8 +276,18 @@ fn parse_extern_type(
     foreign_type: &ForeignItemType,
     lang: Lang,
     trusted: bool,
+    mut ns: Namespace,
 ) -> Result<Api> {
-    let doc = attrs::parse_doc(cx, &foreign_type.attrs);
+    let mut doc = Doc::new();
+    attrs::parse(
+        cx,
+        &foreign_type.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            namespace: Some(&mut ns),
+            ..Default::default()
+        },
+    );
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
     let semi_token = foreign_type.semi_token;
@@ -279,13 +298,18 @@ fn parse_extern_type(
     Ok(api_type(ExternType {
         doc,
         type_token,
-        ident,
+        ident: Pair::new(ns, ident),
         semi_token,
         trusted,
     }))
 }
 
-fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
+fn parse_extern_fn(
+    cx: &mut Errors,
+    foreign_fn: &ForeignItemFn,
+    lang: Lang,
+    mut ns: Namespace,
+) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -310,6 +334,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -326,7 +351,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                         lifetime: lifetime.clone(),
                         mutability: arg.mutability,
                         var: arg.self_token,
-                        ty: Token![Self](arg.self_token.span).into(),
+                        ty: ResolvableName::make_self(arg.self_token.span),
                         shorthand: true,
                     });
                     continue;
@@ -341,7 +366,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
-                let ty = parse_type(&arg.ty)?;
+                let ty = parse_type(&arg.ty, &ns)?;
                 if ident != "self" {
                     args.push_value(Var { ident, ty });
                     if let Some(comma) = comma {
@@ -355,7 +380,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                             ampersand: reference.ampersand,
                             lifetime: reference.lifetime,
                             mutability: reference.mutability,
-                            var: Token![self](ident.span()),
+                            var: Token![self](ident.rust.span()),
                             ty: ident,
                             shorthand: false,
                         });
@@ -368,12 +393,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     }
 
     let mut throws_tokens = None;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &ns)?;
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = Pair {
-        cxx: cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        cxx: CppName::new(ns, cxx_name.unwrap_or(foreign_fn.sig.ident.clone())),
         rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
     };
     let paren_token = foreign_fn.sig.paren_token;
@@ -401,7 +426,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     }))
 }
 
-fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> Result<Api> {
+fn parse_extern_verbatim(
+    cx: &mut Errors,
+    tokens: &TokenStream,
+    lang: Lang,
+    mut ns: Namespace,
+) -> Result<Api> {
     // type Alias = crate::path::to::Type;
     let parse = |input: ParseStream| -> Result<TypeAlias> {
         let attrs = input.call(Attribute::parse_outer)?;
@@ -416,12 +446,21 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        let doc = attrs::parse_doc(cx, &attrs);
+        let mut doc = Doc::new();
+        attrs::parse(
+            cx,
+            &attrs,
+            attrs::Parser {
+                doc: Some(&mut doc),
+                namespace: Some(&mut ns),
+                ..Default::default()
+            },
+        );
 
         Ok(TypeAlias {
             doc,
             type_token,
-            ident,
+            ident: Pair::new(ns, ident),
             eq_token,
             ty,
             semi_token,
@@ -440,7 +479,7 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
-fn parse_impl(imp: ItemImpl) -> Result<Api> {
+fn parse_impl(imp: ItemImpl, ns: &Namespace) -> Result<Api> {
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -466,7 +505,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
 
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
-        ty: parse_type(&self_ty)?,
+        ty: parse_type(&self_ty, ns)?,
         brace_token: imp.brace_token,
     }))
 }
@@ -503,21 +542,21 @@ fn parse_include(input: ParseStream) -> Result<String> {
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
 }
 
-fn parse_type(ty: &RustType) -> Result<Type> {
+fn parse_type(ty: &RustType, ns: &Namespace) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => parse_type_reference(ty),
-        RustType::Path(ty) => parse_type_path(ty),
-        RustType::Slice(ty) => parse_type_slice(ty),
-        RustType::BareFn(ty) => parse_type_fn(ty),
+        RustType::Reference(ty) => parse_type_reference(ty, ns),
+        RustType::Path(ty) => parse_type_path(ty, ns),
+        RustType::Slice(ty) => parse_type_slice(ty, ns),
+        RustType::BareFn(ty) => parse_type_fn(ty, ns),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
+fn parse_type_reference(ty: &TypeReference, ns: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, ns)?;
     let which = match &inner {
-        Type::Ident(ident) if ident == "str" => {
+        Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
                 return Err(Error::new_spanned(ty, "unsupported type"));
             } else {
@@ -525,7 +564,7 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
             }
         }
         Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
             _ => Type::Ref,
         },
         _ => Type::Ref,
@@ -538,19 +577,20 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     })))
 }
 
-fn parse_type_path(ty: &TypePath) -> Result<Type> {
+fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
         let ident = segment.ident.clone();
+        let maybe_resolved_ident = ResolvableName::new(ident.clone());
         match &segment.arguments {
-            PathArguments::None => return Ok(Type::Ident(ident)),
+            PathArguments::None => return Ok(Type::Ident(maybe_resolved_ident)),
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -558,9 +598,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -568,9 +608,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -578,9 +618,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -594,15 +634,15 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
+fn parse_type_slice(ty: &TypeSlice, ns: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, ns)?;
     Ok(Type::Slice(Box::new(Slice {
         bracket: ty.bracket_token,
         inner,
     })))
 }
 
-fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
+fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
             ty,
@@ -620,7 +660,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
         .iter()
         .enumerate()
         .map(|(i, arg)| {
-            let ty = parse_type(&arg.ty)?;
+            let ty = parse_type(&arg.ty, ns)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("_{}", i),
@@ -629,7 +669,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
         })
         .collect::<Result<_>>()?;
     let mut throws_tokens = None;
-    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens, ns)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
@@ -646,6 +686,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
 fn parse_return_type(
     ty: &ReturnType,
     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
+    ns: &Namespace,
 ) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
@@ -667,7 +708,7 @@ fn parse_return_type(
             }
         }
     }
-    match parse_type(ret)? {
+    match parse_type(ret, ns)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),
     }
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index be9bceb..5eefb8d 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -10,6 +10,7 @@ impl QualifiedName {
     pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
         let mut segments = Vec::new();
         let mut trailing_punct = true;
+        input.parse::<Option<Token![::]>>()?;
         while trailing_punct && input.peek(Ident::peek_any) {
             let ident = Ident::parse_any(input)?;
             segments.push(ident);
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 1e5b513..0b79d5f 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -1,4 +1,5 @@
 use crate::syntax::namespace::Namespace;
+use crate::syntax::CppName;
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use std::fmt::{self, Display, Write};
@@ -19,12 +20,6 @@ impl ToTokens for Symbol {
     }
 }
 
-impl From<&Ident> for Symbol {
-    fn from(ident: &Ident) -> Self {
-        Symbol(ident.to_string())
-    }
-}
-
 impl Symbol {
     fn push(&mut self, segment: &dyn Display) {
         let len_before = self.0.len();
@@ -34,18 +29,47 @@ impl Symbol {
         self.0.write_fmt(format_args!("{}", segment)).unwrap();
         assert!(self.0.len() > len_before);
     }
+
+    pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
+        let mut symbol = Symbol(String::new());
+        for segment in it {
+            segment.write(&mut symbol);
+        }
+        assert!(!symbol.0.is_empty());
+        symbol
+    }
+
+    /// For example, for taking a symbol and then making a new symbol
+    /// for a vec of that symbol.
+    pub fn prefix_with(&self, prefix: &str) -> Symbol {
+        Symbol(format!("{}{}", prefix, self.to_string()))
+    }
+}
+
+pub trait Segment {
+    fn write(&self, symbol: &mut Symbol);
 }
 
-pub trait Segment: Display {
+impl Segment for str {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for usize {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for Ident {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for Symbol {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
-
-impl Segment for str {}
-impl Segment for usize {}
-impl Segment for Ident {}
-impl Segment for Symbol {}
 
 impl Segment for Namespace {
     fn write(&self, symbol: &mut Symbol) {
@@ -55,9 +79,16 @@ impl Segment for Namespace {
     }
 }
 
+impl Segment for CppName {
+    fn write(&self, symbol: &mut Symbol) {
+        self.ns.write(symbol);
+        self.ident.write(symbol);
+    }
+}
+
 impl<T> Segment for &'_ T
 where
-    T: ?Sized + Segment,
+    T: ?Sized + Segment + Display,
 {
     fn write(&self, symbol: &mut Symbol) {
         (**self).write(symbol);
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7618e99..57db8eb 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, Signature, Slice, Struct, Ty1,
-    Type, TypeAlias, Var,
+    Atom, Derive, Enum, ExternFn, ExternType, Impl, Pair, Receiver, Ref, ResolvableName, Signature,
+    Slice, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -11,11 +11,11 @@ impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
             Type::Ident(ident) => {
-                if ident == CxxString {
-                    let span = ident.span();
+                if ident.rust == CxxString {
+                    let span = ident.rust.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }
-                ident.to_tokens(tokens);
+                ident.rust.to_tokens(tokens);
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                 ty.to_tokens(tokens)
@@ -39,7 +39,7 @@ impl ToTokens for Var {
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
-        let name = self.name.to_string();
+        let name = self.name.rust.to_string();
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
@@ -121,6 +121,12 @@ impl ToTokens for ExternFn {
     }
 }
 
+impl ToTokens for Pair {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.rust.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.impl_token.to_tokens(tokens);
@@ -149,6 +155,12 @@ impl ToTokens for Signature {
     }
 }
 
+impl ToTokens for ResolvableName {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.rust.to_tokens(tokens);
+    }
+}
+
 pub struct ReceiverType<'a>(&'a Receiver);
 
 impl Receiver {
diff --git a/syntax/types.rs b/syntax/types.rs
index 5bac76e..178da3e 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,10 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Impl, Struct, Type, TypeAlias};
+use crate::syntax::{
+    Api, CppName, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    TypeAlias,
+};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -16,6 +19,7 @@ pub struct Types<'a> {
     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>,
 }
 
 impl<'a> Types<'a> {
@@ -28,6 +32,7 @@ impl<'a> Types<'a> {
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
         let mut explicit_impls = Set::new();
+        let mut resolutions = Map::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -50,6 +55,10 @@ impl<'a> Types<'a> {
             }
         }
 
+        let mut add_resolution = |pair: &'a Pair| {
+            resolutions.insert(&pair.rust, &pair.cxx);
+        };
+
         let mut type_names = UnorderedSet::new();
         let mut function_names = UnorderedSet::new();
         for api in apis {
@@ -62,7 +71,7 @@ impl<'a> Types<'a> {
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
-                    let ident = &strct.ident;
+                    let ident = &strct.ident.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -73,13 +82,14 @@ impl<'a> Types<'a> {
                         // type, then error.
                         duplicate_name(cx, strct, ident);
                     }
-                    structs.insert(ident, strct);
+                    structs.insert(&strct.ident.rust, strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
+                    add_resolution(&strct.ident);
                 }
                 Api::Enum(enm) => {
-                    let ident = &enm.ident;
+                    let ident = &enm.ident.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -91,9 +101,10 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, enm, ident);
                     }
                     enums.insert(ident, enm);
+                    add_resolution(&enm.ident);
                 }
                 Api::CxxType(ety) => {
-                    let ident = &ety.ident;
+                    let ident = &ety.ident.rust;
                     if !type_names.insert(ident)
                         && (cxx.contains(ident)
                             || !structs.contains_key(ident) && !enums.contains_key(ident))
@@ -107,13 +118,15 @@ impl<'a> Types<'a> {
                     if !ety.trusted {
                         untrusted.insert(ident, ety);
                     }
+                    add_resolution(&ety.ident);
                 }
                 Api::RustType(ety) => {
-                    let ident = &ety.ident;
+                    let ident = &ety.ident.rust;
                     if !type_names.insert(ident) {
                         duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
+                    add_resolution(&ety.ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     // Note: duplication of the C++ name is fine because C++ has
@@ -130,11 +143,12 @@ impl<'a> Types<'a> {
                 }
                 Api::TypeAlias(alias) => {
                     let ident = &alias.ident;
-                    if !type_names.insert(ident) {
-                        duplicate_name(cx, alias, ident);
+                    if !type_names.insert(&ident.rust) {
+                        duplicate_name(cx, alias, &ident.rust);
                     }
-                    cxx.insert(ident);
-                    aliases.insert(ident, alias);
+                    cxx.insert(&ident.rust);
+                    aliases.insert(&ident.rust, alias);
+                    add_resolution(&alias.ident);
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
@@ -150,8 +164,8 @@ impl<'a> Types<'a> {
         let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if cxx.contains(ident) {
-                    required_trivial.entry(ident).or_insert(reason);
+                if cxx.contains(&ident.rust) {
+                    required_trivial.entry(&ident.rust).or_insert(reason);
                 }
             }
         };
@@ -187,16 +201,17 @@ impl<'a> Types<'a> {
             untrusted,
             required_trivial,
             explicit_impls,
+            resolutions,
         }
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
         match ty {
             Type::Ident(ident) => {
-                if let Some(strct) = self.structs.get(ident) {
+                if let Some(strct) = self.structs.get(&ident.rust) {
                     !self.is_pod(strct)
                 } else {
-                    Atom::from(ident) == Some(RustString)
+                    Atom::from(&ident.rust) == Some(RustString)
                 }
             }
             Type::RustVec(_) => true,
@@ -212,6 +227,12 @@ impl<'a> Types<'a> {
         }
         false
     }
+
+    pub fn resolve(&self, ident: &ResolvableName) -> &CppName {
+        self.resolutions
+            .get(&ident.rust)
+            .expect("Unable to resolve type")
+    }
 }
 
 impl<'t, 'a> IntoIterator for &'t Types<'a> {
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 0a56dd4..a860f3d 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,7 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `S`
+error: needs a cxx::ExternType impl in order to be used as a field of `::S`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;

From b0cd3270b65ce4531c9a50d3b229d558fa1dffa3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 19:36:02 +0000
Subject: [PATCH 1066/2232] Track span information of include statements


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3184604..a354ae4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,9 @@ use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, Enum, ExternFn, ExternType, IncludeKind, Signature, Struct, Type, Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -24,7 +26,10 @@ pub(super) fn gen(
     out.include.extend(opt.include.clone());
     for api in apis {
         if let Api::Include(include) = api {
-            out.include.insert(include);
+            match include.kind {
+                IncludeKind::Quoted => out.include.insert(&include.path),
+                IncludeKind::Bracketed => out.include.insert(format!("<{}>", include.path)),
+            }
         }
     }
 
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6a177d5..a4b393a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,9 +1,27 @@
-use crate::syntax::{ExternFn, Impl, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+impl PartialEq for Include {
+    fn eq(&self, other: &Include) -> bool {
+        let Include {
+            path,
+            kind,
+            begin_span: _,
+            end_span: _,
+        } = self;
+        let Include {
+            path: path2,
+            kind: kind2,
+            begin_span: _,
+            end_span: _,
+        } = other;
+        path == path2 && kind == kind2
+    }
+}
+
 impl Deref for ExternFn {
     type Target = Signature;
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c8dea67..2eccdb6 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -34,7 +34,7 @@ pub use self::parse::parse_items;
 pub use self::types::Types;
 
 pub enum Api {
-    Include(String),
+    Include(Include),
     Struct(Struct),
     Enum(Enum),
     CxxType(ExternType),
@@ -45,6 +45,19 @@ pub enum Api {
     Impl(Impl),
 }
 
+pub struct Include {
+    pub path: String,
+    pub kind: IncludeKind,
+    pub begin_span: Span,
+    pub end_span: Span,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum IncludeKind {
+    Quoted,    // #include "quoted/path/to"
+    Bracketed, // #include <bracketed/path/to>
+}
+
 pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 367ad05..5b6abbb 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,10 +3,10 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
-    Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang, Pair,
+    Receiver, Ref, Signature, Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
@@ -471,17 +471,28 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
     }))
 }
 
-fn parse_include(input: ParseStream) -> Result<String> {
+fn parse_include(input: ParseStream) -> Result<Include> {
     if input.peek(LitStr) {
-        return Ok(input.parse::<LitStr>()?.value());
+        let lit: LitStr = input.parse()?;
+        let span = lit.span();
+        return Ok(Include {
+            path: lit.value(),
+            kind: IncludeKind::Quoted,
+            begin_span: span,
+            end_span: span,
+        });
     }
 
     if input.peek(Token![<]) {
         let mut path = String::new();
+        let mut begin_span = None;
+        let mut end_span = Span::call_site();
+
         input.parse::<Token![<]>()?;
-        path.push('<');
         while !input.is_empty() && !input.peek(Token![>]) {
             let token: TokenTree = input.parse()?;
+            end_span = token.span();
+            begin_span = Some(begin_span.unwrap_or(end_span));
             match token {
                 TokenTree::Ident(token) => path += &token.to_string(),
                 TokenTree::Literal(token)
@@ -495,9 +506,16 @@ fn parse_include(input: ParseStream) -> Result<String> {
                 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
             }
         }
-        input.parse::<Token![>]>()?;
-        path.push('>');
-        return Ok(path);
+        let rangle: Token![>] = input.parse()?;
+        let begin_span =
+            begin_span.ok_or_else(|| Error::new(rangle.span, "empty filename in #include"))?;
+
+        return Ok(Include {
+            path,
+            kind: IncludeKind::Bracketed,
+            begin_span,
+            end_span,
+        });
     }
 
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))

From d927633b8a24cc04a996b119a0c976ddb51f9851 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:22:51 +0000
Subject: [PATCH 1067/2232] Merge pull request #372 from dtolnay/include


Track span information of include statements
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3184604..a354ae4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,9 @@ use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, Enum, ExternFn, ExternType, IncludeKind, Signature, Struct, Type, Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -24,7 +26,10 @@ pub(super) fn gen(
     out.include.extend(opt.include.clone());
     for api in apis {
         if let Api::Include(include) = api {
-            out.include.insert(include);
+            match include.kind {
+                IncludeKind::Quoted => out.include.insert(&include.path),
+                IncludeKind::Bracketed => out.include.insert(format!("<{}>", include.path)),
+            }
         }
     }
 
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6a177d5..a4b393a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,9 +1,27 @@
-use crate::syntax::{ExternFn, Impl, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+impl PartialEq for Include {
+    fn eq(&self, other: &Include) -> bool {
+        let Include {
+            path,
+            kind,
+            begin_span: _,
+            end_span: _,
+        } = self;
+        let Include {
+            path: path2,
+            kind: kind2,
+            begin_span: _,
+            end_span: _,
+        } = other;
+        path == path2 && kind == kind2
+    }
+}
+
 impl Deref for ExternFn {
     type Target = Signature;
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c8dea67..2eccdb6 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -34,7 +34,7 @@ pub use self::parse::parse_items;
 pub use self::types::Types;
 
 pub enum Api {
-    Include(String),
+    Include(Include),
     Struct(Struct),
     Enum(Enum),
     CxxType(ExternType),
@@ -45,6 +45,19 @@ pub enum Api {
     Impl(Impl),
 }
 
+pub struct Include {
+    pub path: String,
+    pub kind: IncludeKind,
+    pub begin_span: Span,
+    pub end_span: Span,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum IncludeKind {
+    Quoted,    // #include "quoted/path/to"
+    Bracketed, // #include <bracketed/path/to>
+}
+
 pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 367ad05..5b6abbb 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,10 +3,10 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Pair, Receiver, Ref, Signature,
-    Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang, Pair,
+    Receiver, Ref, Signature, Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
@@ -471,17 +471,28 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
     }))
 }
 
-fn parse_include(input: ParseStream) -> Result<String> {
+fn parse_include(input: ParseStream) -> Result<Include> {
     if input.peek(LitStr) {
-        return Ok(input.parse::<LitStr>()?.value());
+        let lit: LitStr = input.parse()?;
+        let span = lit.span();
+        return Ok(Include {
+            path: lit.value(),
+            kind: IncludeKind::Quoted,
+            begin_span: span,
+            end_span: span,
+        });
     }
 
     if input.peek(Token![<]) {
         let mut path = String::new();
+        let mut begin_span = None;
+        let mut end_span = Span::call_site();
+
         input.parse::<Token![<]>()?;
-        path.push('<');
         while !input.is_empty() && !input.peek(Token![>]) {
             let token: TokenTree = input.parse()?;
+            end_span = token.span();
+            begin_span = Some(begin_span.unwrap_or(end_span));
             match token {
                 TokenTree::Ident(token) => path += &token.to_string(),
                 TokenTree::Literal(token)
@@ -495,9 +506,16 @@ fn parse_include(input: ParseStream) -> Result<String> {
                 _ => return Err(Error::new(token.span(), "unexpected token in include path")),
             }
         }
-        input.parse::<Token![>]>()?;
-        path.push('>');
-        return Ok(path);
+        let rangle: Token![>] = input.parse()?;
+        let begin_span =
+            begin_span.ok_or_else(|| Error::new(rangle.span, "empty filename in #include"))?;
+
+        return Ok(Include {
+            path,
+            kind: IncludeKind::Bracketed,
+            begin_span,
+            end_span,
+        });
     }
 
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))

From 4aae7c09b72bfb4299c44468f95bb6d140015900 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:23:21 +0000
Subject: [PATCH 1068/2232] Distinguish quoted vs bracketed includes in gen::include


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 3255902..959b029 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,4 +1,5 @@
 use crate::gen::out::OutFile;
+use crate::syntax::IncludeKind;
 use std::fmt::{self, Display};
 
 /// The complete contents of the "rust/cxx.h" header.
@@ -48,9 +49,15 @@ fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     }
 }
 
+#[derive(PartialEq)]
+pub struct Include {
+    pub path: String,
+    pub kind: IncludeKind,
+}
+
 #[derive(Default, PartialEq)]
 pub struct Includes {
-    custom: Vec<String>,
+    custom: Vec<Include>,
     pub array: bool,
     pub cstddef: bool,
     pub cstdint: bool,
@@ -70,24 +77,30 @@ impl Includes {
         Includes::default()
     }
 
-    pub fn insert(&mut self, include: impl AsRef<str>) {
-        self.custom.push(include.as_ref().to_owned());
+    pub fn insert(&mut self, include: Include) {
+        self.custom.push(include);
     }
 }
 
-impl Extend<String> for Includes {
-    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
-        self.custom.extend(iter);
+impl<'a> Extend<&'a String> for Includes {
+    fn extend<I: IntoIterator<Item = &'a String>>(&mut self, iter: I) {
+        self.custom.extend(iter.into_iter().map(|path| Include {
+            path: path.clone(),
+            kind: IncludeKind::Quoted,
+        }));
     }
 }
 
 impl Display for Includes {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for include in &self.custom {
-            if include.starts_with('<') && include.ends_with('>') {
-                writeln!(f, "#include {}", include)?;
-            } else {
-                writeln!(f, "#include \"{}\"", include.escape_default())?;
+            match include.kind {
+                IncludeKind::Quoted => {
+                    writeln!(f, "#include \"{}\"", include.path.escape_default())?;
+                }
+                IncludeKind::Bracketed => {
+                    writeln!(f, "#include <{}>", include.path)?;
+                }
             }
         }
         if self.array {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a354ae4..f1c7a11 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,11 +1,10 @@
+use crate::gen::include::Include;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{
-    mangle, Api, Enum, ExternFn, ExternType, IncludeKind, Signature, Struct, Type, Types, Var,
-};
+use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -23,13 +22,12 @@ pub(super) fn gen(
         writeln!(out.front, "#pragma once");
     }
 
-    out.include.extend(opt.include.clone());
+    out.include.extend(&opt.include);
     for api in apis {
         if let Api::Include(include) = api {
-            match include.kind {
-                IncludeKind::Quoted => out.include.insert(&include.path),
-                IncludeKind::Bracketed => out.include.insert(format!("<{}>", include.path)),
-            }
+            let path = include.path.clone();
+            let kind = include.kind;
+            out.include.insert(Include { path, kind });
         }
     }
 

From 36b1dbac2f746ab3a8a5344a836639dabd2eb818 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:33:33 +0000
Subject: [PATCH 1069/2232] Merge pull request #373 from dtolnay/include


Distinguish quoted vs bracketed includes in gen::include
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 3255902..959b029 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,4 +1,5 @@
 use crate::gen::out::OutFile;
+use crate::syntax::IncludeKind;
 use std::fmt::{self, Display};
 
 /// The complete contents of the "rust/cxx.h" header.
@@ -48,9 +49,15 @@ fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     }
 }
 
+#[derive(PartialEq)]
+pub struct Include {
+    pub path: String,
+    pub kind: IncludeKind,
+}
+
 #[derive(Default, PartialEq)]
 pub struct Includes {
-    custom: Vec<String>,
+    custom: Vec<Include>,
     pub array: bool,
     pub cstddef: bool,
     pub cstdint: bool,
@@ -70,24 +77,30 @@ impl Includes {
         Includes::default()
     }
 
-    pub fn insert(&mut self, include: impl AsRef<str>) {
-        self.custom.push(include.as_ref().to_owned());
+    pub fn insert(&mut self, include: Include) {
+        self.custom.push(include);
     }
 }
 
-impl Extend<String> for Includes {
-    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
-        self.custom.extend(iter);
+impl<'a> Extend<&'a String> for Includes {
+    fn extend<I: IntoIterator<Item = &'a String>>(&mut self, iter: I) {
+        self.custom.extend(iter.into_iter().map(|path| Include {
+            path: path.clone(),
+            kind: IncludeKind::Quoted,
+        }));
     }
 }
 
 impl Display for Includes {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for include in &self.custom {
-            if include.starts_with('<') && include.ends_with('>') {
-                writeln!(f, "#include {}", include)?;
-            } else {
-                writeln!(f, "#include \"{}\"", include.escape_default())?;
+            match include.kind {
+                IncludeKind::Quoted => {
+                    writeln!(f, "#include \"{}\"", include.path.escape_default())?;
+                }
+                IncludeKind::Bracketed => {
+                    writeln!(f, "#include <{}>", include.path)?;
+                }
             }
         }
         if self.array {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a354ae4..f1c7a11 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,11 +1,10 @@
+use crate::gen::include::Include;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{
-    mangle, Api, Enum, ExternFn, ExternType, IncludeKind, Signature, Struct, Type, Types, Var,
-};
+use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
@@ -23,13 +22,12 @@ pub(super) fn gen(
         writeln!(out.front, "#pragma once");
     }
 
-    out.include.extend(opt.include.clone());
+    out.include.extend(&opt.include);
     for api in apis {
         if let Api::Include(include) = api {
-            match include.kind {
-                IncludeKind::Quoted => out.include.insert(&include.path),
-                IncludeKind::Bracketed => out.include.insert(format!("<{}>", include.path)),
-            }
+            let path = include.path.clone();
+            let kind = include.kind;
+            out.include.insert(Include { path, kind });
         }
     }
 

From 700cd0c1df3ae50d125f366c57c5c21ccc604139 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:33:41 +0000
Subject: [PATCH 1070/2232] Expose IncludeKind to cxx_gen library


---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index bd3bcfd..e2945a1 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -3,6 +3,8 @@
 mod test;
 
 use super::{Opt, Output};
+use crate::gen::include::Include;
+use crate::syntax::IncludeKind;
 use clap::AppSettings;
 use std::ffi::{OsStr, OsString};
 use std::path::PathBuf;
@@ -63,7 +65,19 @@ pub(super) fn from_args() -> Opt {
     let include = matches
         .values_of(INCLUDE)
         .unwrap_or_default()
-        .map(str::to_owned)
+        .map(|include| {
+            if include.starts_with('<') && include.ends_with('>') {
+                Include {
+                    path: include[1..include.len() - 1].to_owned(),
+                    kind: IncludeKind::Bracketed,
+                }
+            } else {
+                Include {
+                    path: include.to_owned(),
+                    kind: IncludeKind::Quoted,
+                }
+            }
+        })
         .collect();
 
     let mut outputs = Vec::new();
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index f0fd9b4..cd58307 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -13,7 +13,8 @@ mod output;
 mod syntax;
 
 use crate::gen::error::{report, Result};
-use crate::gen::{fs, include};
+use crate::gen::fs;
+use crate::gen::include::{self, Include};
 use crate::output::Output;
 use std::io::{self, Write};
 use std::path::PathBuf;
@@ -24,7 +25,7 @@ struct Opt {
     input: Option<PathBuf>,
     header: bool,
     cxx_impl_annotations: Option<String>,
-    include: Vec<String>,
+    include: Vec<Include>,
     outputs: Vec<Output>,
 }
 
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index ecfa436..963e870 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -20,8 +20,9 @@ mod gen;
 mod syntax;
 
 pub use crate::error::Error;
-pub use crate::gen::include::HEADER;
+pub use crate::gen::include::{Include, HEADER};
 pub use crate::gen::{GeneratedCode, Opt};
+pub use crate::syntax::IncludeKind;
 use proc_macro2::TokenStream;
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 959b029..705ca24 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -49,9 +49,16 @@ fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     }
 }
 
-#[derive(PartialEq)]
+/// A header to #include.
+///
+/// The cxxbridge tool does not parse or even require the given paths to exist;
+/// they simply go into the generated C++ code as #include lines.
+#[derive(Clone, PartialEq, Debug)]
 pub struct Include {
+    /// The header's path, not including the enclosing quotation marks or angle
+    /// brackets.
     pub path: String,
+    /// Whether to emit `#include "path"` or `#include <path>`.
     pub kind: IncludeKind,
 }
 
@@ -82,12 +89,9 @@ impl Includes {
     }
 }
 
-impl<'a> Extend<&'a String> for Includes {
-    fn extend<I: IntoIterator<Item = &'a String>>(&mut self, iter: I) {
-        self.custom.extend(iter.into_iter().map(|path| Include {
-            path: path.clone(),
-            kind: IncludeKind::Quoted,
-        }));
+impl<'a> Extend<&'a Include> for Includes {
+    fn extend<I: IntoIterator<Item = &'a Include>>(&mut self, iter: I) {
+        self.custom.extend(iter.into_iter().cloned());
     }
 }
 
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 2fee0e9..1a3febd 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -11,6 +11,7 @@ mod write;
 pub(super) use self::error::Error;
 use self::error::{format_err, Result};
 use self::file::File;
+use self::include::Include;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use std::path::Path;
@@ -34,7 +35,7 @@ pub struct Opt {
     /// Any additional headers to #include. The cxxbridge tool does not parse or
     /// even require the given paths to exist; they simply go into the generated
     /// C++ code as #include lines.
-    pub include: Vec<String>,
+    pub include: Vec<Include>,
     /// Optional annotation for implementations of C++ function wrappers that
     /// may be exposed to Rust. You may for example need to provide
     /// `__declspec(dllexport)` or `__attribute__((visibility("default")))` if
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2eccdb6..180c40a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -52,10 +52,13 @@ pub struct Include {
     pub end_span: Span,
 }
 
-#[derive(Copy, Clone, PartialEq)]
+/// Whether to emit `#include "path"` or `#include <path>`.
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum IncludeKind {
-    Quoted,    // #include "quoted/path/to"
-    Bracketed, // #include <bracketed/path/to>
+    /// `#include "quoted/path/to"`
+    Quoted,
+    /// `#include <bracketed/path/to>`
+    Bracketed,
 }
 
 pub struct ExternType {

From d5107638a1a4ae0c84d5b9ca5a5e5101c65ff686 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:41:36 +0000
Subject: [PATCH 1071/2232] Merge pull request #374 from dtolnay/include


Expose IncludeKind to cxx_gen library
---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index bd3bcfd..e2945a1 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -3,6 +3,8 @@
 mod test;
 
 use super::{Opt, Output};
+use crate::gen::include::Include;
+use crate::syntax::IncludeKind;
 use clap::AppSettings;
 use std::ffi::{OsStr, OsString};
 use std::path::PathBuf;
@@ -63,7 +65,19 @@ pub(super) fn from_args() -> Opt {
     let include = matches
         .values_of(INCLUDE)
         .unwrap_or_default()
-        .map(str::to_owned)
+        .map(|include| {
+            if include.starts_with('<') && include.ends_with('>') {
+                Include {
+                    path: include[1..include.len() - 1].to_owned(),
+                    kind: IncludeKind::Bracketed,
+                }
+            } else {
+                Include {
+                    path: include.to_owned(),
+                    kind: IncludeKind::Quoted,
+                }
+            }
+        })
         .collect();
 
     let mut outputs = Vec::new();
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index f0fd9b4..cd58307 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -13,7 +13,8 @@ mod output;
 mod syntax;
 
 use crate::gen::error::{report, Result};
-use crate::gen::{fs, include};
+use crate::gen::fs;
+use crate::gen::include::{self, Include};
 use crate::output::Output;
 use std::io::{self, Write};
 use std::path::PathBuf;
@@ -24,7 +25,7 @@ struct Opt {
     input: Option<PathBuf>,
     header: bool,
     cxx_impl_annotations: Option<String>,
-    include: Vec<String>,
+    include: Vec<Include>,
     outputs: Vec<Output>,
 }
 
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index ecfa436..963e870 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -20,8 +20,9 @@ mod gen;
 mod syntax;
 
 pub use crate::error::Error;
-pub use crate::gen::include::HEADER;
+pub use crate::gen::include::{Include, HEADER};
 pub use crate::gen::{GeneratedCode, Opt};
+pub use crate::syntax::IncludeKind;
 use proc_macro2::TokenStream;
 
 /// Generate C++ bindings code from a Rust token stream. This should be a Rust
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 959b029..705ca24 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -49,9 +49,16 @@ fn find_line(mut offset: usize, line: &str) -> Option<usize> {
     }
 }
 
-#[derive(PartialEq)]
+/// A header to #include.
+///
+/// The cxxbridge tool does not parse or even require the given paths to exist;
+/// they simply go into the generated C++ code as #include lines.
+#[derive(Clone, PartialEq, Debug)]
 pub struct Include {
+    /// The header's path, not including the enclosing quotation marks or angle
+    /// brackets.
     pub path: String,
+    /// Whether to emit `#include "path"` or `#include <path>`.
     pub kind: IncludeKind,
 }
 
@@ -82,12 +89,9 @@ impl Includes {
     }
 }
 
-impl<'a> Extend<&'a String> for Includes {
-    fn extend<I: IntoIterator<Item = &'a String>>(&mut self, iter: I) {
-        self.custom.extend(iter.into_iter().map(|path| Include {
-            path: path.clone(),
-            kind: IncludeKind::Quoted,
-        }));
+impl<'a> Extend<&'a Include> for Includes {
+    fn extend<I: IntoIterator<Item = &'a Include>>(&mut self, iter: I) {
+        self.custom.extend(iter.into_iter().cloned());
     }
 }
 
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 2fee0e9..1a3febd 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -11,6 +11,7 @@ mod write;
 pub(super) use self::error::Error;
 use self::error::{format_err, Result};
 use self::file::File;
+use self::include::Include;
 use crate::syntax::report::Errors;
 use crate::syntax::{self, check, Types};
 use std::path::Path;
@@ -34,7 +35,7 @@ pub struct Opt {
     /// Any additional headers to #include. The cxxbridge tool does not parse or
     /// even require the given paths to exist; they simply go into the generated
     /// C++ code as #include lines.
-    pub include: Vec<String>,
+    pub include: Vec<Include>,
     /// Optional annotation for implementations of C++ function wrappers that
     /// may be exposed to Rust. You may for example need to provide
     /// `__declspec(dllexport)` or `__attribute__((visibility("default")))` if
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2eccdb6..180c40a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -52,10 +52,13 @@ pub struct Include {
     pub end_span: Span,
 }
 
-#[derive(Copy, Clone, PartialEq)]
+/// Whether to emit `#include "path"` or `#include <path>`.
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum IncludeKind {
-    Quoted,    // #include "quoted/path/to"
-    Bracketed, // #include <bracketed/path/to>
+    /// `#include "quoted/path/to"`
+    Quoted,
+    /// `#include <bracketed/path/to>`
+    Bracketed,
 }
 
 pub struct ExternType {

From 75c2385e3023e4cf4b0f18b09797be7304f0e4be Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:41:45 +0000
Subject: [PATCH 1072/2232] Check for disallowed include strings


    error[cxxbridge]: #include relative to `.` or `..` is not supported in Cargo builds
       ┌─ src/main.rs:10:18
       │
    10 │         include!("../header.h");
       │                  ^^^^^^^^^^^^^ #include relative to `.` or `..` is not supported in Cargo builds
       │
       = note: use a path starting with the crate name

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index e6de985..3e37143 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -271,7 +271,10 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
 }
 
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
-    let opt = Opt::default();
+    let opt = Opt {
+        allow_dot_includes: false,
+        ..Opt::default()
+    };
     let generated = gen::generate_from_path(rust_source_file, &opt);
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index cd58307..c723039 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -66,6 +66,7 @@ fn try_main() -> Result<()> {
         cxx_impl_annotations: opt.cxx_impl_annotations,
         gen_header,
         gen_implementation,
+        ..Default::default()
     };
 
     let generated_code = if let Some(input) = opt.input {
diff --git a/gen/src/check.rs b/gen/src/check.rs
new file mode 100644
index 0000000..35929ad
--- /dev/null
+++ b/gen/src/check.rs
@@ -0,0 +1,27 @@
+use crate::gen::Opt;
+use crate::syntax::report::Errors;
+use crate::syntax::{error, Api};
+use quote::{quote, quote_spanned};
+use std::path::{Component, Path};
+
+pub(super) use crate::syntax::check::typecheck;
+
+pub(super) fn precheck(cx: &mut Errors, apis: &[Api], opt: &Opt) {
+    if !opt.allow_dot_includes {
+        check_dot_includes(cx, apis);
+    }
+}
+
+fn check_dot_includes(cx: &mut Errors, apis: &[Api]) {
+    for api in apis {
+        if let Api::Include(include) = api {
+            let first_component = Path::new(&include.path).components().next();
+            if let Some(Component::CurDir) | Some(Component::ParentDir) = first_component {
+                let begin = quote_spanned!(include.begin_span=> .);
+                let end = quote_spanned!(include.end_span=> .);
+                let span = quote!(#begin #end);
+                cx.error(span, error::DOT_INCLUDE.msg);
+            }
+        }
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 1a3febd..236fece 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
+mod check;
 pub(super) mod error;
 mod file;
 pub(super) mod fs;
@@ -13,7 +14,7 @@ use self::error::{format_err, Result};
 use self::file::File;
 use self::include::Include;
 use crate::syntax::report::Errors;
-use crate::syntax::{self, check, Types};
+use crate::syntax::{self, Types};
 use std::path::Path;
 
 /// Options for C++ code generation.
@@ -45,6 +46,7 @@ pub struct Opt {
 
     pub(super) gen_header: bool,
     pub(super) gen_implementation: bool,
+    pub(super) allow_dot_includes: bool,
 }
 
 /// Results of code generation.
@@ -63,6 +65,7 @@ impl Default for Opt {
             cxx_impl_annotations: None,
             gen_header: true,
             gen_implementation: true,
+            allow_dot_includes: true,
         }
     }
 }
@@ -112,6 +115,7 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     let trusted = bridge.unsafety.is_some();
     let ref apis = syntax::parse_items(errors, bridge.content, trusted);
     let ref types = Types::collect(errors, apis);
+    check::precheck(errors, apis, opt);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
diff --git a/syntax/error.rs b/syntax/error.rs
index a60b7da..9597089 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -19,6 +19,7 @@ pub static ERRORS: &[Error] = &[
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
     DISCRIMINANT_OVERFLOW,
+    DOT_INCLUDE,
     DOUBLE_UNDERSCORE,
     RUST_TYPE_BY_VALUE,
     USE_NOT_ALLOWED,
@@ -54,6 +55,12 @@ pub static DISCRIMINANT_OVERFLOW: Error = Error {
     note: Some("note: explicitly set `= 0` if that is desired outcome"),
 };
 
+pub static DOT_INCLUDE: Error = Error {
+    msg: "#include relative to `.` or `..` is not supported in Cargo builds",
+    label: Some("#include relative to `.` or `..` is not supported in Cargo builds"),
+    note: Some("note: use a path starting with the crate name"),
+};
+
 pub static DOUBLE_UNDERSCORE: Error = Error {
     msg: "identifiers containing double underscore are reserved in C++",
     label: Some("reserved identifier"),

From faa1a7c448916d9f52dbc75fdadd56bd151ed13a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:48:22 +0000
Subject: [PATCH 1073/2232] Merge pull request #375 from dtolnay/include


Check for disallowed include strings in Cargo-based workflow
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index e6de985..3e37143 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -271,7 +271,10 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
 }
 
 fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
-    let opt = Opt::default();
+    let opt = Opt {
+        allow_dot_includes: false,
+        ..Opt::default()
+    };
     let generated = gen::generate_from_path(rust_source_file, &opt);
     let ref rel_path = paths::local_relative_path(rust_source_file);
 
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index cd58307..c723039 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -66,6 +66,7 @@ fn try_main() -> Result<()> {
         cxx_impl_annotations: opt.cxx_impl_annotations,
         gen_header,
         gen_implementation,
+        ..Default::default()
     };
 
     let generated_code = if let Some(input) = opt.input {
diff --git a/gen/src/check.rs b/gen/src/check.rs
new file mode 100644
index 0000000..35929ad
--- /dev/null
+++ b/gen/src/check.rs
@@ -0,0 +1,27 @@
+use crate::gen::Opt;
+use crate::syntax::report::Errors;
+use crate::syntax::{error, Api};
+use quote::{quote, quote_spanned};
+use std::path::{Component, Path};
+
+pub(super) use crate::syntax::check::typecheck;
+
+pub(super) fn precheck(cx: &mut Errors, apis: &[Api], opt: &Opt) {
+    if !opt.allow_dot_includes {
+        check_dot_includes(cx, apis);
+    }
+}
+
+fn check_dot_includes(cx: &mut Errors, apis: &[Api]) {
+    for api in apis {
+        if let Api::Include(include) = api {
+            let first_component = Path::new(&include.path).components().next();
+            if let Some(Component::CurDir) | Some(Component::ParentDir) = first_component {
+                let begin = quote_spanned!(include.begin_span=> .);
+                let end = quote_spanned!(include.end_span=> .);
+                let span = quote!(#begin #end);
+                cx.error(span, error::DOT_INCLUDE.msg);
+            }
+        }
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 1a3febd..236fece 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
+mod check;
 pub(super) mod error;
 mod file;
 pub(super) mod fs;
@@ -13,7 +14,7 @@ use self::error::{format_err, Result};
 use self::file::File;
 use self::include::Include;
 use crate::syntax::report::Errors;
-use crate::syntax::{self, check, Types};
+use crate::syntax::{self, Types};
 use std::path::Path;
 
 /// Options for C++ code generation.
@@ -45,6 +46,7 @@ pub struct Opt {
 
     pub(super) gen_header: bool,
     pub(super) gen_implementation: bool,
+    pub(super) allow_dot_includes: bool,
 }
 
 /// Results of code generation.
@@ -63,6 +65,7 @@ impl Default for Opt {
             cxx_impl_annotations: None,
             gen_header: true,
             gen_implementation: true,
+            allow_dot_includes: true,
         }
     }
 }
@@ -112,6 +115,7 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     let trusted = bridge.unsafety.is_some();
     let ref apis = syntax::parse_items(errors, bridge.content, trusted);
     let ref types = Types::collect(errors, apis);
+    check::precheck(errors, apis, opt);
     errors.propagate()?;
     check::typecheck(errors, namespace, apis, types);
     errors.propagate()?;
diff --git a/syntax/error.rs b/syntax/error.rs
index a60b7da..9597089 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -19,6 +19,7 @@ pub static ERRORS: &[Error] = &[
     CXX_STRING_BY_VALUE,
     CXX_TYPE_BY_VALUE,
     DISCRIMINANT_OVERFLOW,
+    DOT_INCLUDE,
     DOUBLE_UNDERSCORE,
     RUST_TYPE_BY_VALUE,
     USE_NOT_ALLOWED,
@@ -54,6 +55,12 @@ pub static DISCRIMINANT_OVERFLOW: Error = Error {
     note: Some("note: explicitly set `= 0` if that is desired outcome"),
 };
 
+pub static DOT_INCLUDE: Error = Error {
+    msg: "#include relative to `.` or `..` is not supported in Cargo builds",
+    label: Some("#include relative to `.` or `..` is not supported in Cargo builds"),
+    note: Some("note: use a path starting with the crate name"),
+};
+
 pub static DOUBLE_UNDERSCORE: Error = Error {
     msg: "identifiers containing double underscore are reserved in C++",
     label: Some("reserved identifier"),

From 2cc2e3a4d13011e338b1624a6ced35f39f25894d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 20:48:34 +0000
Subject: [PATCH 1074/2232] Include angle brackets in include-related errors


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 5b6abbb..3f579a1 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -6,7 +6,7 @@ use crate::syntax::{
     attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang, Pair,
     Receiver, Ref, Signature, Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
-use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
@@ -485,14 +485,10 @@ fn parse_include(input: ParseStream) -> Result<Include> {
 
     if input.peek(Token![<]) {
         let mut path = String::new();
-        let mut begin_span = None;
-        let mut end_span = Span::call_site();
 
-        input.parse::<Token![<]>()?;
+        let langle: Token![<] = input.parse()?;
         while !input.is_empty() && !input.peek(Token![>]) {
             let token: TokenTree = input.parse()?;
-            end_span = token.span();
-            begin_span = Some(begin_span.unwrap_or(end_span));
             match token {
                 TokenTree::Ident(token) => path += &token.to_string(),
                 TokenTree::Literal(token)
@@ -507,14 +503,12 @@ fn parse_include(input: ParseStream) -> Result<Include> {
             }
         }
         let rangle: Token![>] = input.parse()?;
-        let begin_span =
-            begin_span.ok_or_else(|| Error::new(rangle.span, "empty filename in #include"))?;
 
         return Ok(Include {
             path,
             kind: IncludeKind::Bracketed,
-            begin_span,
-            end_span,
+            begin_span: langle.span,
+            end_span: rangle.span,
         });
     }
 

From 353d98cdd93772f2a23e2179386ce3091af85f7f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 28 2020 22:43:35 +0000
Subject: [PATCH 1075/2232] Move syntax Include to gen Include conversion to From impl


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 705ca24..309d8c3 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,5 +1,5 @@
 use crate::gen::out::OutFile;
-use crate::syntax::IncludeKind;
+use crate::syntax::{self, IncludeKind};
 use std::fmt::{self, Display};
 
 /// The complete contents of the "rust/cxx.h" header.
@@ -84,8 +84,8 @@ impl Includes {
         Includes::default()
     }
 
-    pub fn insert(&mut self, include: Include) {
-        self.custom.push(include);
+    pub fn insert(&mut self, include: impl Into<Include>) {
+        self.custom.push(include.into());
     }
 }
 
@@ -95,6 +95,15 @@ impl<'a> Extend<&'a Include> for Includes {
     }
 }
 
+impl<'a> From<&'a syntax::Include> for Include {
+    fn from(include: &syntax::Include) -> Self {
+        Include {
+            path: include.path.clone(),
+            kind: include.kind,
+        }
+    }
+}
+
 impl Display for Includes {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         for include in &self.custom {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f1c7a11..01617ca 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,3 @@
-use crate::gen::include::Include;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -25,9 +24,7 @@ pub(super) fn gen(
     out.include.extend(&opt.include);
     for api in apis {
         if let Api::Include(include) = api {
-            let path = include.path.clone();
-            let kind = include.kind;
-            out.include.insert(Include { path, kind });
+            out.include.insert(include);
         }
     }
 

From dbc5377e9f3c6d29cf82fcf4732005ce17872475 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 29 2020 00:28:51 +0000
Subject: [PATCH 1076/2232] Avoid repeating the underlined type in the label


---

diff --git a/syntax/check.rs b/syntax/check.rs
index ced1570..25183c9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -67,7 +67,8 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
-        cx.error(ident, &format!("unsupported type: {}", ident));
+        let msg = format!("unsupported type: {}", ident);
+        cx.error(ident, &msg);
     }
 }
 
diff --git a/syntax/error.rs b/syntax/error.rs
index a60b7da..2749277 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -21,6 +21,7 @@ pub static ERRORS: &[Error] = &[
     DISCRIMINANT_OVERFLOW,
     DOUBLE_UNDERSCORE,
     RUST_TYPE_BY_VALUE,
+    UNSUPPORTED_TYPE,
     USE_NOT_ALLOWED,
 ];
 
@@ -66,6 +67,12 @@ pub static RUST_TYPE_BY_VALUE: Error = Error {
     note: Some("hint: wrap it in a Box<>"),
 };
 
+pub static UNSUPPORTED_TYPE: Error = Error {
+    msg: "unsupported type: ",
+    label: Some("unsupported type"),
+    note: None,
+};
+
 pub static USE_NOT_ALLOWED: Error = Error {
     msg: "`use` items are not allowed within cxx bridge",
     label: Some("not allowed"),

From 7b14585af9856a7e7bbc042d0292335933c35300 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 29 2020 01:27:36 +0000
Subject: [PATCH 1077/2232] Merge pull request #377 from dtolnay/unsupported-type


Include typename in diagnostic on unsupported type
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2f3c334..25183c9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -67,7 +67,8 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
         && !cx.types.cxx.contains(ident)
         && !cx.types.rust.contains(ident)
     {
-        cx.error(ident, "unsupported type");
+        let msg = format!("unsupported type: {}", ident);
+        cx.error(ident, &msg);
     }
 }
 
diff --git a/syntax/error.rs b/syntax/error.rs
index 9597089..d0ae021 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -22,6 +22,7 @@ pub static ERRORS: &[Error] = &[
     DOT_INCLUDE,
     DOUBLE_UNDERSCORE,
     RUST_TYPE_BY_VALUE,
+    UNSUPPORTED_TYPE,
     USE_NOT_ALLOWED,
 ];
 
@@ -73,6 +74,12 @@ pub static RUST_TYPE_BY_VALUE: Error = Error {
     note: Some("hint: wrap it in a Box<>"),
 };
 
+pub static UNSUPPORTED_TYPE: Error = Error {
+    msg: "unsupported type: ",
+    label: Some("unsupported type"),
+    note: None,
+};
+
 pub static USE_NOT_ALLOWED: Error = Error {
     msg: "`use` items are not allowed within cxx bridge",
     label: Some("not allowed"),

From d60c07b7629a373396c4cb15c57c4903402cee27 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 29 2020 23:46:40 +0000
Subject: [PATCH 1078/2232] Merge pull request 370 from adetaylor/allow-namespace-override


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 236fece..e6e2c7c 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -6,6 +6,7 @@ pub(super) mod error;
 mod file;
 pub(super) mod fs;
 pub(super) mod include;
+mod namespace_organizer;
 pub(super) mod out;
 mod write;
 
@@ -113,23 +114,23 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
         .ok_or(Error::NoBridgeMod)?;
     let ref namespace = bridge.namespace;
     let trusted = bridge.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, bridge.content, trusted);
+    let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
     let ref types = Types::collect(errors, apis);
     check::precheck(errors, apis, opt);
     errors.propagate()?;
-    check::typecheck(errors, namespace, apis, types);
+    check::typecheck(errors, apis, types);
     errors.propagate()?;
     // Some callers may wish to generate both header and C++
     // from the same token stream to avoid parsing twice. But others
     // only need to generate one or the other.
     Ok(GeneratedCode {
         header: if opt.gen_header {
-            write::gen(namespace, apis, types, opt, true).content()
+            write::gen(apis, types, opt, true).content()
         } else {
             Vec::new()
         },
         implementation: if opt.gen_implementation {
-            write::gen(namespace, apis, types, opt, false).content()
+            write::gen(apis, types, opt, false).content()
         } else {
             Vec::new()
         },
diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
new file mode 100644
index 0000000..c54e784
--- /dev/null
+++ b/gen/src/namespace_organizer.rs
@@ -0,0 +1,40 @@
+use crate::syntax::Api;
+use proc_macro2::Ident;
+use std::collections::BTreeMap;
+
+pub(crate) struct NamespaceEntries<'a> {
+    pub(crate) entries: Vec<&'a Api>,
+    pub(crate) children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+}
+
+pub(crate) fn sort_by_namespace(apis: &[Api]) -> NamespaceEntries {
+    let api_refs = apis.iter().collect::<Vec<_>>();
+    sort_by_inner_namespace(api_refs, 0)
+}
+
+fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
+    let mut root = NamespaceEntries {
+        entries: Vec::new(),
+        children: BTreeMap::new(),
+    };
+
+    let mut kids_by_child_ns = BTreeMap::new();
+    for api in apis {
+        if let Some(ns) = api.get_namespace() {
+            let first_ns_elem = ns.iter().nth(depth);
+            if let Some(first_ns_elem) = first_ns_elem {
+                let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
+                list.push(api);
+                continue;
+            }
+        }
+        root.entries.push(api);
+    }
+
+    for (k, v) in kids_by_child_ns.into_iter() {
+        root.children
+            .insert(k, sort_by_inner_namespace(v, depth + 1));
+    }
+
+    root
+}
diff --git a/gen/src/out.rs b/gen/src/out.rs
index d42ea74..8a6bd86 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,10 +1,8 @@
 use crate::gen::include::Includes;
-use crate::syntax::namespace::Namespace;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile {
-    pub namespace: Namespace,
     pub header: bool,
     pub include: Includes,
     pub front: Content,
@@ -18,9 +16,8 @@ pub struct Content {
 }
 
 impl OutFile {
-    pub fn new(namespace: Namespace, header: bool) -> Self {
+    pub fn new(header: bool) -> Self {
         OutFile {
-            namespace,
             header,
             include: Includes::new(),
             front: Content::new(),
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 01617ca..967d4ff 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,20 +1,17 @@
+use crate::gen::namespace_organizer::{sort_by_namespace, NamespaceEntries};
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::Symbol;
-use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
+use crate::syntax::{
+    mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
+    Types, Var,
+};
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
-pub(super) fn gen(
-    namespace: &Namespace,
-    apis: &[Api],
-    types: &Types,
-    opt: &Opt,
-    header: bool,
-) -> OutFile {
-    let mut out_file = OutFile::new(namespace.clone(), header);
+pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> OutFile {
+    let mut out_file = OutFile::new(header);
     let out = &mut out_file;
 
     if header {
@@ -32,16 +29,36 @@ pub(super) fn gen(
     write_include_cxxbridge(out, apis, types);
 
     out.next_section();
-    for name in namespace {
-        writeln!(out, "namespace {} {{", name);
+
+    let apis_by_namespace = sort_by_namespace(apis);
+
+    gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
+
+    if !header {
+        out.next_section();
+        write_generic_instantiations(out, types);
     }
 
+    write!(out.front, "{}", out.include);
+
+    out_file
+}
+
+fn gen_namespace_contents(
+    ns_entries: &NamespaceEntries,
+    types: &Types,
+    opt: &Opt,
+    header: bool,
+    out: &mut OutFile,
+) {
+    let apis = &ns_entries.entries;
+
     out.next_section();
     for api in apis {
         match api {
-            Api::Struct(strct) => write_struct_decl(out, &strct.ident),
-            Api::CxxType(ety) => write_struct_using(out, &ety.ident),
-            Api::RustType(ety) => write_struct_decl(out, &ety.ident),
+            Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
+            Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
+            Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
             _ => {}
         }
     }
@@ -51,7 +68,7 @@ pub(super) fn gen(
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
-                    .entry(&receiver.ty)
+                    .entry(&receiver.ty.rust)
                     .or_insert_with(Vec::new)
                     .push(efn);
             }
@@ -62,22 +79,22 @@ pub(super) fn gen(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                if !types.cxx.contains(&strct.ident) {
-                    write_struct(out, strct);
+                if !types.cxx.contains(&strct.ident.rust) {
+                    write_struct(out, strct, types);
                 }
             }
             Api::Enum(enm) => {
                 out.next_section();
-                if types.cxx.contains(&enm.ident) {
+                if types.cxx.contains(&enm.ident.rust) {
                     check_enum(out, enm);
                 } else {
                     write_enum(out, enm);
                 }
             }
             Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.ident) {
+                if let Some(methods) = methods_for_type.get(&ety.ident.rust) {
                     out.next_section();
-                    write_struct_with_methods(out, ety, methods);
+                    write_struct_with_methods(out, ety, methods, types);
                 }
             }
             _ => {}
@@ -87,8 +104,8 @@ pub(super) fn gen(
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if types.required_trivial.contains_key(&ety.ident) {
-                check_trivial_extern_type(out, &ety.ident)
+            if types.required_trivial.contains_key(&ety.ident.rust) {
+                check_trivial_extern_type(out, &ety.ident.cxx)
             }
         }
     }
@@ -116,24 +133,18 @@ pub(super) fn gen(
     }
 
     out.next_section();
-    for name in namespace.iter().rev() {
-        writeln!(out, "}} // namespace {}", name);
-    }
 
-    if !header {
-        out.next_section();
-        write_generic_instantiations(out, types);
+    for (child_ns, child_ns_entries) in &ns_entries.children {
+        writeln!(out, "namespace {} {{", child_ns);
+        gen_namespace_contents(&child_ns_entries, types, opt, header, out);
+        writeln!(out, "}} // namespace {}", child_ns);
     }
-
-    write!(out.front, "{}", out.include);
-
-    out_file
 }
 
 fn write_includes(out: &mut OutFile, types: &Types) {
     for ty in types {
         match ty {
-            Type::Ident(ident) => match Atom::from(ident) {
+            Type::Ident(ident) => match Atom::from(&ident.rust) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
                 | Some(I64) => out.include.cstdint = true,
                 Some(Usize) => out.include.cstddef = true,
@@ -332,17 +343,17 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct) {
-    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, strct.ident);
+fn write_struct(out: &mut OutFile, strct: &Struct, types: &Types) {
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.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);
+    writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
     for field in &strct.fields {
         write!(out, "  ");
-        write_type_space(out, &field.ty);
+        write_type_space(out, &field.ty, types);
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
@@ -353,25 +364,39 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "struct {};", ident);
 }
 
-fn write_struct_using(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "using {} = {};", ident, ident);
+fn write_struct_using(out: &mut OutFile, ident: &CppName) {
+    writeln!(
+        out,
+        "using {} = {};",
+        ident.ident,
+        ident.to_fully_qualified()
+    );
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
-    let guard = format!("CXXBRIDGE05_STRUCT_{}{}", out.namespace, ety.ident);
+fn write_struct_with_methods(
+    out: &mut OutFile,
+    ety: &ExternType,
+    methods: &[&ExternFn],
+    types: &Types,
+) {
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.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);
-    writeln!(out, "  {}() = delete;", ety.ident);
-    writeln!(out, "  {}(const {} &) = delete;", ety.ident, ety.ident);
+    writeln!(out, "struct {} final {{", ety.ident.cxx.ident);
+    writeln!(out, "  {}() = delete;", ety.ident.cxx.ident);
+    writeln!(
+        out,
+        "  {}(const {} &) = delete;",
+        ety.ident.cxx.ident, ety.ident.cxx.ident
+    );
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.cxx.to_string();
-        write_rust_function_shim_decl(out, &local_name, sig, false);
+        let local_name = method.ident.cxx.ident.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false, types);
         writeln!(out, ";");
     }
     writeln!(out, "}};");
@@ -379,13 +404,13 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
 }
 
 fn write_enum(out: &mut OutFile, enm: &Enum) {
-    let guard = format!("CXXBRIDGE05_ENUM_{}{}", out.namespace, enm.ident);
+    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.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);
+    write!(out, "enum class {} : ", enm.ident.cxx.ident);
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
@@ -396,7 +421,11 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
 }
 
 fn check_enum(out: &mut OutFile, enm: &Enum) {
-    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident);
+    write!(
+        out,
+        "static_assert(sizeof({}) == sizeof(",
+        enm.ident.cxx.ident
+    );
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
@@ -405,12 +434,12 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident, variant.ident, variant.discriminant,
+            enm.ident.cxx.ident, variant.ident, variant.discriminant,
         );
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
     // 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:
@@ -429,6 +458,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     // not being recognized as such by the C++ type system due to a move
     // constructor or destructor.
 
+    let id = &id.to_fully_qualified();
     out.include.type_traits = true;
     writeln!(out, "static_assert(");
     writeln!(
@@ -450,7 +480,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
     );
 }
 
-fn write_exception_glue(out: &mut OutFile, apis: &[Api]) {
+fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
     let mut has_cxx_throws = false;
     for api in apis {
         if let Api::CxxFunction(efn) = api {
@@ -486,13 +516,17 @@ fn write_cxx_function_shim(
     } else {
         write_extern_return_type_space(out, &efn.ret, types);
     }
-    let mangled = mangle::extern_fn(&out.namespace, efn);
+    let mangled = mangle::extern_fn(efn, types);
     write!(out, "{}(", mangled);
     if let Some(receiver) = &efn.receiver {
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ty);
+        write!(
+            out,
+            "{} &self",
+            types.resolve(&receiver.ty).to_fully_qualified()
+        );
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 || efn.receiver.is_some() {
@@ -510,21 +544,26 @@ fn write_cxx_function_shim(
         if !efn.args.is_empty() || efn.receiver.is_some() {
             write!(out, ", ");
         }
-        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap(), types);
         write!(out, "*return$");
     }
     writeln!(out, ") noexcept {{");
     write!(out, "  ");
-    write_return_type(out, &efn.ret);
+    write_return_type(out, &efn.ret, types);
     match &efn.receiver {
         None => write!(out, "(*{}$)(", efn.ident.rust),
-        Some(receiver) => write!(out, "({}::*{}$)(", receiver.ty, efn.ident.rust),
+        Some(receiver) => write!(
+            out,
+            "({}::*{}$)(",
+            types.resolve(&receiver.ty).to_fully_qualified(),
+            efn.ident.rust
+        ),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
-        write_type(out, &arg.ty);
+        write_type(out, &arg.ty, types);
     }
     write!(out, ")");
     if let Some(receiver) = &efn.receiver {
@@ -534,8 +573,13 @@ fn write_cxx_function_shim(
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident.cxx),
-        Some(receiver) => write!(out, "&{}::{}", receiver.ty, efn.ident.cxx),
+        None => write!(out, "{}", efn.ident.cxx.to_fully_qualified()),
+        Some(receiver) => write!(
+            out,
+            "&{}::{}",
+            types.resolve(&receiver.ty).to_fully_qualified(),
+            efn.ident.cxx.ident
+        ),
     }
     writeln!(out, ";");
     write!(out, "  ");
@@ -548,7 +592,7 @@ fn write_cxx_function_shim(
     if indirect_return {
         out.include.new = true;
         write!(out, "new (return$) ");
-        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap(), types);
         write!(out, "(");
     } else if efn.ret.is_some() {
         write!(out, "return ");
@@ -570,10 +614,10 @@ fn write_cxx_function_shim(
             write!(out, ", ");
         }
         if let Type::RustBox(_) = &arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "::from_raw({})", arg.ident);
         } else if let Type::UniquePtr(_) = &arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "({})", arg.ident);
         } else if arg.ty == RustString {
             write!(
@@ -582,7 +626,7 @@ fn write_cxx_function_shim(
                 arg.ident,
             );
         } else if let Type::RustVec(_) = arg.ty {
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
@@ -632,17 +676,17 @@ fn write_function_pointer_trampoline(
     types: &Types,
 ) {
     out.next_section();
-    let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
+    let r_trampoline = mangle::r_trampoline(efn, var, types);
     let indirect_call = true;
     write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
 
     out.next_section();
-    let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
+    let c_trampoline = mangle::c_trampoline(efn, var, types).to_string();
     write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
-    let link_name = mangle::extern_fn(&out.namespace, efn);
+    let link_name = mangle::extern_fn(efn, types);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
 }
@@ -665,7 +709,11 @@ fn write_rust_function_decl_impl(
         if receiver.mutability.is_none() {
             write!(out, "const ");
         }
-        write!(out, "{} &self", receiver.ty);
+        write!(
+            out,
+            "{} &self",
+            types.resolve(&receiver.ty).to_fully_qualified()
+        );
         needs_comma = true;
     }
     for arg in &sig.args {
@@ -679,7 +727,7 @@ fn write_rust_function_decl_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &sig.ret);
+        write_return_type(out, &sig.ret, types);
         write!(out, "*return$");
         needs_comma = true;
     }
@@ -697,10 +745,14 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.cxx.to_string(),
-        Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
+        None => efn.ident.cxx.ident.to_string(),
+        Some(receiver) => format!(
+            "{}::{}",
+            types.resolve(&receiver.ty).ident,
+            efn.ident.cxx.ident
+        ),
     };
-    let invoke = mangle::extern_fn(&out.namespace, efn);
+    let invoke = mangle::extern_fn(efn, types);
     let indirect_call = false;
     write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
 }
@@ -710,14 +762,15 @@ fn write_rust_function_shim_decl(
     local_name: &str,
     sig: &Signature,
     indirect_call: bool,
+    types: &Types,
 ) {
-    write_return_type(out, &sig.ret);
+    write_return_type(out, &sig.ret, types);
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
-        write_type_space(out, &arg.ty);
+        write_type_space(out, &arg.ty, types);
         write!(out, "{}", arg.ident);
     }
     if indirect_call {
@@ -749,7 +802,7 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call, types);
     if out.header {
         writeln!(out, ";");
         return;
@@ -759,7 +812,7 @@ fn write_rust_function_shim_impl(
         if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "  ::rust::ManuallyDrop<");
-            write_type(out, &arg.ty);
+            write_type(out, &arg.ty, types);
             writeln!(out, "> {}$(::std::move({0}));", arg.ident);
         }
     }
@@ -767,18 +820,18 @@ fn write_rust_function_shim_impl(
     let indirect_return = indirect_return(sig, types);
     if indirect_return {
         write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
+        write_type(out, sig.ret.as_ref().unwrap(), types);
         writeln!(out, "> return$;");
         write!(out, "  ");
     } else if let Some(ret) = &sig.ret {
         write!(out, "return ");
         match ret {
             Type::RustBox(_) => {
-                write_type(out, ret);
+                write_type(out, ret, types);
                 write!(out, "::from_raw(");
             }
             Type::UniquePtr(_) => {
-                write_type(out, ret);
+                write_type(out, ret, types);
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
@@ -844,10 +897,10 @@ fn write_rust_function_shim_impl(
     writeln!(out, "}}");
 }
 
-fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
+fn write_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         None => write!(out, "void "),
-        Some(ty) => write_type_space(out, ty),
+        Some(ty) => write_type_space(out, ty, types),
     }
 }
 
@@ -857,27 +910,27 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type, types: &Types) {
     match ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Type::Ref(ty) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, " *");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr"),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
-        _ => write_type(out, ty),
+        _ => write_type(out, ty, types),
     }
 }
 
-fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
-    write_indirect_return_type(out, ty);
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
+    write_indirect_return_type(out, ty, types);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
         Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
@@ -888,32 +941,32 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
 fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
     match ty {
         Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Some(Type::Ref(ty)) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, " *");
         }
         Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
-        _ => write_return_type(out, ty),
+        _ => write_return_type(out, ty, types),
     }
 }
 
 fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     match &arg.ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
-            write_type_space(out, &ty.inner);
+            write_type_space(out, &ty.inner, types);
             write!(out, "*");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        _ => write_type_space(out, &arg.ty),
+        _ => write_type_space(out, &arg.ty, types),
     }
     if types.needs_indirect_abi(&arg.ty) {
         write!(out, "*");
@@ -921,37 +974,37 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
     write!(out, "{}", arg.ident);
 }
 
-fn write_type(out: &mut OutFile, ty: &Type) {
+fn write_type(out: &mut OutFile, ty: &Type, types: &Types) {
     match ty {
-        Type::Ident(ident) => match Atom::from(ident) {
+        Type::Ident(ident) => match Atom::from(&ident.rust) {
             Some(atom) => write_atom(out, atom),
-            None => write!(out, "{}", ident),
+            None => write!(out, "{}", types.resolve(ident).to_fully_qualified()),
         },
         Type::RustBox(ty) => {
             write!(out, "::rust::Box<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::RustVec(ty) => {
             write!(out, "::rust::Vec<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::UniquePtr(ptr) => {
             write!(out, "::std::unique_ptr<");
-            write_type(out, &ptr.inner);
+            write_type(out, &ptr.inner, types);
             write!(out, ">");
         }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
-            write_type(out, &ty.inner);
+            write_type(out, &ty.inner, types);
             write!(out, ">");
         }
         Type::Ref(r) => {
             if r.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &r.inner);
+            write_type(out, &r.inner, types);
             write!(out, " &");
         }
         Type::Slice(_) => {
@@ -967,7 +1020,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
             match &f.ret {
-                Some(ret) => write_type(out, ret),
+                Some(ret) => write_type(out, ret, types),
                 None => write!(out, "void"),
             }
             write!(out, "(");
@@ -975,7 +1028,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
                 if i > 0 {
                     write!(out, ", ");
                 }
-                write_type(out, &arg.ty);
+                write_type(out, &arg.ty, types);
             }
             write!(out, ")>");
         }
@@ -1003,8 +1056,8 @@ fn write_atom(out: &mut OutFile, atom: Atom) {
     }
 }
 
-fn write_type_space(out: &mut OutFile, ty: &Type) {
-    write_type(out, ty);
+fn write_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
+    write_type(out, ty, types);
     write_space_after_type(out, ty);
 }
 
@@ -1025,28 +1078,20 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 // Only called for legal referent types of unique_ptr and element types of
 // std::vector and Vec.
-fn to_typename(namespace: &Namespace, ty: &Type) -> String {
+fn to_typename(ty: &Type, types: &Types) -> String {
     match ty {
-        Type::Ident(ident) => {
-            let mut path = String::new();
-            for name in namespace {
-                path += &name.to_string();
-                path += "::";
-            }
-            path += &ident.to_string();
-            path
-        }
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(namespace, &ptr.inner)),
+        Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
+        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
         _ => unreachable!(),
     }
 }
 
 // Only called for legal referent types of unique_ptr and element types of
 // std::vector and Vec.
-fn to_mangled(namespace: &Namespace, ty: &Type) -> String {
+fn to_mangled(ty: &Type, types: &Types) -> Symbol {
     match ty {
-        Type::Ident(_) => to_typename(namespace, ty).replace("::", "$"),
-        Type::CxxVector(ptr) => format!("std$vector${}", to_mangled(namespace, &ptr.inner)),
+        Type::Ident(ident) => ident.to_symbol(types),
+        Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
         _ => unreachable!(),
     }
 }
@@ -1057,19 +1102,20 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
                 out.next_section();
-                write_rust_box_extern(out, inner);
+                write_rust_box_extern(out, &types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
+                if Atom::from(&inner.rust).is_none() {
                     out.next_section();
-                    write_rust_vec_extern(out, inner);
+                    write_rust_vec_extern(out, inner, types);
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none()
-                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                if Atom::from(&inner.rust).is_none()
+                    && (!types.aliases.contains_key(&inner.rust)
+                        || types.explicit_impls.contains(ty))
                 {
                     out.next_section();
                     write_unique_ptr(out, inner, types);
@@ -1077,8 +1123,9 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(inner).is_none()
-                    && (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
+                if Atom::from(&inner.rust).is_none()
+                    && (!types.aliases.contains_key(&inner.rust)
+                        || types.explicit_impls.contains(ty))
                 {
                     out.next_section();
                     write_cxx_vector(out, ty, inner, types);
@@ -1093,12 +1140,12 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     for ty in types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, inner);
+                write_rust_box_impl(out, &types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(inner).is_none() {
-                    write_rust_vec_impl(out, inner);
+                if Atom::from(&inner.rust).is_none() {
+                    write_rust_vec_impl(out, inner, types);
                 }
             }
         }
@@ -1107,14 +1154,9 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += &name.to_string();
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
+    let inner = ident.to_fully_qualified();
+    let instance = ident.to_symbol();
 
     writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
@@ -1131,10 +1173,10 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
@@ -1166,14 +1208,9 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
-    let mut inner = String::new();
-    for name in &out.namespace {
-        inner += &name.to_string();
-        inner += "::";
-    }
-    inner += &ident.to_string();
-    let instance = inner.replace("::", "$");
+fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
+    let inner = ident.to_fully_qualified();
+    let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
@@ -1186,10 +1223,10 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
@@ -1225,9 +1262,9 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
+fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName, types: &Types) {
     let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&out.namespace, &ty);
+    let instance = to_mangled(&ty, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
@@ -1241,8 +1278,8 @@ fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
 fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     out.include.new = true;
     out.include.utility = true;
-    let inner = to_typename(&out.namespace, ty);
-    let instance = to_mangled(&out.namespace, ty);
+    let inner = to_typename(ty, types);
+    let instance = to_mangled(ty, types);
 
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types. We can't
@@ -1250,7 +1287,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         Type::Ident(ident) => {
-            types.structs.contains_key(ident) || types.aliases.contains_key(ident)
+            types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust)
         }
         _ => false,
     };
@@ -1315,10 +1352,10 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName, types: &Types) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&out.namespace, &element);
-    let instance = to_mangled(&out.namespace, &element);
+    let inner = to_typename(&element, types);
+    let instance = to_mangled(&element, types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4a4ec64..1bcaa1e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,11 @@
 use crate::derive::DeriveAttribute;
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::file::Module;
-use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Signature, Struct, Type, TypeAlias,
-    Types,
+    self, check, mangle, Api, CppName, Enum, ExternFn, ExternType, Impl, ResolvableName, Signature,
+    Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -17,11 +16,11 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
     let content = mem::take(&mut ffi.content);
     let trusted = ffi.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, content, trusted);
+    let namespace = &ffi.namespace;
+    let ref apis = syntax::parse_items(errors, content, trusted, namespace);
     let ref types = Types::collect(errors, apis);
     errors.propagate()?;
-    let namespace = &ffi.namespace;
-    check::typecheck(errors, namespace, apis, types);
+    check::typecheck(errors, apis, types);
     errors.propagate()?;
 
     Ok(expand(ffi, apis, types))
@@ -30,7 +29,6 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
 fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
-    let namespace = &ffi.namespace;
 
     for api in apis {
         if let Api::RustType(ety) = api {
@@ -42,23 +40,23 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(namespace, strct)),
-            Api::Enum(enm) => expanded.extend(expand_enum(namespace, enm)),
+            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.ident;
-                if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
-                    expanded.extend(expand_cxx_type(namespace, ety));
+                if !types.structs.contains_key(&ident.rust)
+                    && !types.enums.contains_key(&ident.rust)
+                {
+                    expanded.extend(expand_cxx_type(ety));
                 }
             }
             Api::CxxFunction(efn) => {
-                expanded.extend(expand_cxx_function_shim(namespace, efn, types));
-            }
-            Api::RustFunction(efn) => {
-                hidden.extend(expand_rust_function_shim(namespace, efn, types))
+                expanded.extend(expand_cxx_function_shim(efn, types));
             }
+            Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
-                hidden.extend(expand_type_alias_verify(namespace, alias, types));
+                hidden.extend(expand_type_alias_verify(alias, types));
             }
         }
     }
@@ -67,33 +65,33 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(ident).is_none() {
-                    hidden.extend(expand_rust_box(namespace, ident));
+                if Atom::from(&ident.rust).is_none() {
+                    hidden.extend(expand_rust_box(ident, types));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(ident).is_none() {
-                    hidden.extend(expand_rust_vec(namespace, ident));
+                if Atom::from(&ident.rust).is_none() {
+                    hidden.extend(expand_rust_vec(ident, types));
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
-                    expanded.extend(expand_unique_ptr(namespace, ident, types, explicit_impl));
+                    expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(ident).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(ident))
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
                     // Generate impl for CxxVector<T> if T is a struct or opaque
                     // C++ type. Impl for primitives is already provided by cxx
                     // crate.
-                    expanded.extend(expand_cxx_vector(namespace, ident, explicit_impl));
+                    expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
                 }
             }
         }
@@ -126,11 +124,12 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     }
 }
 
-fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
-    let ident = &strct.ident;
+fn expand_struct(strct: &Struct) -> TokenStream {
+    let ident = &strct.ident.rust;
+    let cxx_ident = &strct.ident.cxx;
     let doc = &strct.doc;
     let derives = DeriveAttribute(&strct.derives);
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(cxx_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,12 @@ fn expand_struct(namespace: &Namespace, strct: &Struct) -> TokenStream {
     }
 }
 
-fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
-    let ident = &enm.ident;
+fn expand_enum(enm: &Enum) -> TokenStream {
+    let ident = &enm.ident.rust;
+    let cxx_ident = &enm.ident.cxx;
     let doc = &enm.doc;
     let repr = enm.repr;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(cxx_ident);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -186,10 +186,11 @@ fn expand_enum(namespace: &Namespace, enm: &Enum) -> TokenStream {
     }
 }
 
-fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
-    let ident = &ety.ident;
+fn expand_cxx_type(ety: &ExternType) -> TokenStream {
+    let ident = &ety.ident.rust;
+    let cxx_ident = &ety.ident.cxx;
     let doc = &ety.doc;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(&cxx_ident);
 
     quote! {
         #doc
@@ -205,7 +206,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
     }
 }
 
-fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
+fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
         quote!(_: #receiver_type)
@@ -236,7 +237,7 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         outparam = Some(quote!(__return: *mut #ret));
     }
-    let link_name = mangle::extern_fn(namespace, efn);
+    let link_name = mangle::extern_fn(efn, types);
     let local_name = format_ident!("__{}", efn.ident.rust);
     quote! {
         #[link_name = #link_name]
@@ -244,9 +245,9 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
     }
 }
 
-fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
+fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
-    let decl = expand_cxx_function_decl(namespace, efn, types);
+    let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
         let ampersand = receiver.ampersand;
         let mutability = receiver.mutability;
@@ -272,14 +273,14 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     let arg_vars = efn.args.iter().map(|arg| {
         let var = &arg.ident;
         match &arg.ty {
-            Type::Ident(ident) if ident == RustString => {
+            Type::Ident(ident) if ident.rust == RustString => {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => quote!(::cxx::private::RustString::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
                 },
@@ -306,9 +307,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         .filter_map(|arg| {
             if let Type::Fn(f) = &arg.ty {
                 let var = &arg.ident;
-                Some(expand_function_pointer_trampoline(
-                    namespace, efn, var, f, types,
-                ))
+                Some(expand_function_pointer_trampoline(efn, var, f, types))
             } else {
                 None
             }
@@ -355,7 +354,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
     };
     let expr = if efn.throws {
         efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => {
+            Type::Ident(ident) if ident.rust == RustString => {
                 Some(quote!(#call.map(|r| r.into_string())))
             }
             Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
@@ -368,7 +367,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => Some(quote!(#call.map(|r| r.as_string()))),
                     Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
                 },
@@ -388,7 +387,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
         })
     } else {
         efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident == RustString => Some(quote!(#call.into_string())),
+            Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
             Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
             Type::RustVec(vec) => {
                 if vec.inner == RustString {
@@ -399,7 +398,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
             }
             Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident == RustString => match ty.mutability {
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                     None => Some(quote!(#call.as_string())),
                     Some(_) => Some(quote!(#call.as_mut_string())),
                 },
@@ -445,14 +444,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
 }
 
 fn expand_function_pointer_trampoline(
-    namespace: &Namespace,
     efn: &ExternFn,
     var: &Ident,
     sig: &Signature,
     types: &Types,
 ) -> TokenStream {
-    let c_trampoline = mangle::c_trampoline(namespace, efn, var);
-    let r_trampoline = mangle::r_trampoline(namespace, efn, var);
+    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.ident.rust, var);
     let shim = expand_rust_function_shim_impl(
@@ -500,7 +498,7 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     let sized = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Sized
     };
-    quote_spanned! {ident.span()=>
+    quote_spanned! {ident.rust.span()=>
         let _ = {
             fn __AssertSized<T: ?#sized + #sized>() {}
             __AssertSized::<#ident>
@@ -508,8 +506,8 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     }
 }
 
-fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
-    let link_name = mangle::extern_fn(namespace, efn);
+fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
+    let link_name = mangle::extern_fn(efn, types);
     let local_name = format_ident!("__{}", efn.ident.rust);
     let catch_unwind_label = format!("::{}", efn.ident.rust);
     let invoke = Some(&efn.ident.rust);
@@ -553,7 +551,7 @@ fn expand_rust_function_shim_impl(
     let arg_vars = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
         match &arg.ty {
-            Type::Ident(i) if i == RustString => {
+            Type::Ident(i) if i.rust == RustString => {
                 quote!(::std::mem::take((*#ident).as_mut_string()))
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#ident)),
@@ -566,7 +564,7 @@ fn expand_rust_function_shim_impl(
             }
             Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i == RustString => match ty.mutability {
+                Type::Ident(i) if i.rust == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
                     Some(_) => quote!(#ident.as_mut_string()),
                 },
@@ -601,7 +599,9 @@ fn expand_rust_function_shim_impl(
     call.extend(quote! { (#(#vars),*) });
 
     let conversion = sig.ret.as_ref().and_then(|ret| match ret {
-        Type::Ident(ident) if ident == RustString => Some(quote!(::cxx::private::RustString::from)),
+        Type::Ident(ident) if ident.rust == RustString => {
+            Some(quote!(::cxx::private::RustString::from))
+        }
         Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw)),
         Type::RustVec(vec) => {
             if vec.inner == RustString {
@@ -612,7 +612,7 @@ fn expand_rust_function_shim_impl(
         }
         Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
         Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident == RustString => match ty.mutability {
+            Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                 None => Some(quote!(::cxx::private::RustString::from_ref)),
                 Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
             },
@@ -686,13 +686,9 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     }
 }
 
-fn expand_type_alias_verify(
-    namespace: &Namespace,
-    alias: &TypeAlias,
-    types: &Types,
-) -> TokenStream {
+fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
     let ident = &alias.ident;
-    let type_id = type_id(namespace, ident);
+    let type_id = type_id(&ident.cxx);
     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::<);
@@ -702,7 +698,7 @@ fn expand_type_alias_verify(
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial.contains_key(&alias.ident) {
+    if types.required_trivial.contains_key(&alias.ident.rust) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
@@ -712,25 +708,19 @@ fn expand_type_alias_verify(
     verify
 }
 
-fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let mut path = String::new();
-    for name in namespace {
-        path += &name.to_string();
-        path += "::";
-    }
-    path += &ident.to_string();
-
+fn type_id(ident: &CppName) -> TokenStream {
+    let path = ident.to_fully_qualified();
     quote! {
         ::cxx::type_id!(#path)
     }
 }
 
-fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$box${}{}$", namespace, ident);
+fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
+    let link_prefix = format!("cxxbridge05$box${}$", types.resolve(ident).to_symbol());
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
-    let local_prefix = format_ident!("{}__box_", ident);
+    let local_prefix = format_ident!("{}__box_", &ident.rust);
     let local_uninit = format_ident!("{}uninit", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
@@ -754,15 +744,15 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$rust_vec${}{}$", namespace, elem);
+fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
+    let link_prefix = format!("cxxbridge05$rust_vec${}$", elem.to_symbol(types));
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", elem);
+    let local_prefix = format_ident!("{}__vec_", elem.rust);
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
@@ -800,13 +790,12 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
 }
 
 fn expand_unique_ptr(
-    namespace: &Namespace,
-    ident: &Ident,
+    ident: &ResolvableName,
     types: &Types,
     explicit_impl: Option<&Impl>,
 ) -> TokenStream {
-    let name = ident.to_string();
-    let prefix = format!("cxxbridge05$unique_ptr${}{}$", namespace, ident);
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge05$unique_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -814,21 +803,22 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
-        Some(quote! {
-            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
-                extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+    let new_method =
+        if types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust) {
+            Some(quote! {
+                fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+                    extern "C" {
+                        #[link_name = #link_new]
+                        fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+                    }
+                    let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                    unsafe { __new(&mut repr, &mut value) }
+                    repr
                 }
-                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __new(&mut repr, &mut value) }
-                repr
-            }
-        })
-    } else {
-        None
-    };
+            })
+        } else {
+            None
+        };
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -883,16 +873,19 @@ fn expand_unique_ptr(
 }
 
 fn expand_cxx_vector(
-    namespace: &Namespace,
-    elem: &Ident,
+    elem: &ResolvableName,
     explicit_impl: Option<&Impl>,
+    types: &Types,
 ) -> TokenStream {
     let _ = explicit_impl;
-    let name = elem.to_string();
-    let prefix = format!("cxxbridge05$std$vector${}{}$", namespace, elem);
+    let name = elem.rust.to_string();
+    let prefix = format!("cxxbridge05$std$vector${}$", elem.to_symbol(types));
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
-    let unique_ptr_prefix = format!("cxxbridge05$unique_ptr$std$vector${}{}$", namespace, elem);
+    let unique_ptr_prefix = format!(
+        "cxxbridge05$unique_ptr$std$vector${}$",
+        elem.to_symbol(types)
+    );
     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);
@@ -979,7 +972,7 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
 
 fn expand_extern_type(ty: &Type) -> TokenStream {
     match ty {
-        Type::Ident(ident) if ident == RustString => quote!(::cxx::private::RustString),
+        Type::Ident(ident) if ident.rust == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
             let inner = expand_extern_type(&ty.inner);
             quote!(*mut #inner)
@@ -991,7 +984,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
         Type::Ref(ty) => {
             let mutability = ty.mutability;
             match &ty.inner {
-                Type::Ident(ident) if ident == RustString => {
+                Type::Ident(ident) if ident.rust == RustString => {
                     quote!(&#mutability ::cxx::private::RustString)
                 }
                 Type::RustVec(ty) => {
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 6e5fa88..7d0ef6b 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -81,7 +81,7 @@ impl AsRef<str> for Atom {
 impl PartialEq<Atom> for Type {
     fn eq(&self, atom: &Atom) -> bool {
         match self {
-            Type::Ident(ident) => ident == atom,
+            Type::Ident(ident) => ident.rust == atom,
             _ => false,
         }
     }
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 4c8a3e5..25af229 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,3 +1,4 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
@@ -12,19 +13,7 @@ pub struct Parser<'a> {
     pub repr: Option<&'a mut Option<Atom>>,
     pub cxx_name: Option<&'a mut Option<Ident>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
-}
-
-pub(super) fn parse_doc(cx: &mut Errors, attrs: &[Attribute]) -> Doc {
-    let mut doc = Doc::new();
-    parse(
-        cx,
-        attrs,
-        Parser {
-            doc: Some(&mut doc),
-            ..Parser::default()
-        },
-    );
-    doc
+    pub namespace: Option<&'a mut Namespace>,
 }
 
 pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
@@ -79,6 +68,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("namespace") {
+            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(namespace) = &mut parser.namespace {
+                        **namespace = attr;
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -131,3 +130,10 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
         input.parse()
     }
 }
+
+fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
+    let content;
+    syn::parenthesized!(content in input);
+    let namespace = content.parse::<Namespace>()?;
+    Ok(namespace)
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index 25183c9..08e0dfa 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,4 @@
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
@@ -11,15 +10,13 @@ use quote::{quote, ToTokens};
 use std::fmt::Display;
 
 pub(crate) struct Check<'a> {
-    namespace: &'a Namespace,
     apis: &'a [Api],
     types: &'a Types<'a>,
     errors: &'a mut Errors,
 }
 
-pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], types: &Types) {
+pub(crate) fn typecheck(cx: &mut Errors, apis: &[Api], types: &Types) {
     do_typecheck(&mut Check {
-        namespace,
         apis,
         types,
         errors: cx,
@@ -27,11 +24,11 @@ pub(crate) fn typecheck(cx: &mut Errors, namespace: &Namespace, apis: &[Api], ty
 }
 
 fn do_typecheck(cx: &mut Check) {
-    ident::check_all(cx, cx.namespace, cx.apis);
+    ident::check_all(cx, cx.apis);
 
     for ty in cx.types {
         match ty {
-            Type::Ident(ident) => check_type_ident(cx, ident),
+            Type::Ident(ident) => check_type_ident(cx, &ident.rust),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
@@ -74,14 +71,14 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
 
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
+        if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.structs.contains_key(&ident.rust)
+            && !cx.types.enums.contains_key(&ident.rust)
         {
             cx.error(ptr, error::BOX_CXX_TYPE.msg);
         }
 
-        if Atom::from(ident).is_none() {
+        if Atom::from(&ident.rust).is_none() {
             return;
         }
     }
@@ -91,15 +88,15 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
+        if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.structs.contains_key(&ident.rust)
+            && !cx.types.enums.contains_key(&ident.rust)
         {
             cx.error(ty, "Rust Vec containing C++ type is not supported yet");
             return;
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(RustString) => return,
@@ -113,11 +110,11 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
 
 fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.rust.contains(ident) {
+        if cx.types.rust.contains(&ident.rust) {
             cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(CxxString) => return,
             _ => {}
         }
@@ -130,14 +127,14 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
 
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
-        if cx.types.rust.contains(ident) {
+        if cx.types.rust.contains(&ident.rust) {
             cx.error(
                 ptr,
                 "C++ vector containing a Rust type is not supported yet",
             );
         }
 
-        match Atom::from(ident) {
+        match Atom::from(&ident.rust) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(CxxString) => return,
@@ -171,15 +168,15 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
     let ident = &strct.ident;
-    check_reserved_name(cx, ident);
+    check_reserved_name(cx, &ident.rust);
 
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
     }
 
-    if cx.types.cxx.contains(ident) {
-        if let Some(ety) = cx.types.untrusted.get(ident) {
+    if cx.types.cxx.contains(&ident.rust) {
+        if let Some(ety) = cx.types.untrusted.get(&ident.rust) {
             let msg = "extern shared struct must be declared in an `unsafe extern` block";
             cx.error(ety, msg);
         }
@@ -201,7 +198,7 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 }
 
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
-    check_reserved_name(cx, &enm.ident);
+    check_reserved_name(cx, &enm.ident.rust);
 
     if enm.variants.is_empty() {
         let span = span_for_enum_error(enm);
@@ -210,11 +207,13 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 }
 
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
-    check_reserved_name(cx, &ety.ident);
+    check_reserved_name(cx, &ety.ident.rust);
 
-    if let Some(reason) = cx.types.required_trivial.get(&ety.ident) {
+    if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
         let what = match reason {
-            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident),
+            TrivialReason::StructField(strct) => {
+                format!("a field of `{}`", strct.ident.cxx.to_fully_qualified())
+            }
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
@@ -230,7 +229,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
         let ref span = span_for_receiver_error(receiver);
 
-        if receiver.ty == "Self" {
+        if receiver.ty.is_self() {
             let mutability = match receiver.mutability {
                 Some(_) => "mut ",
                 None => "",
@@ -242,9 +241,9 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 mutability = mutability,
             );
             cx.error(span, msg);
-        } else if !cx.types.structs.contains_key(&receiver.ty)
-            && !cx.types.cxx.contains(&receiver.ty)
-            && !cx.types.rust.contains(&receiver.ty)
+        } else if !cx.types.structs.contains_key(&receiver.ty.rust)
+            && !cx.types.cxx.contains(&receiver.ty.rust)
+            && !cx.types.rust.contains(&receiver.ty.rust)
         {
             cx.error(span, "unrecognized receiver type");
         }
@@ -291,7 +290,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
     if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
         if let Type::Ident(inner) = &ty.inner {
-            if Atom::from(inner).is_none() {
+            if Atom::from(&inner.rust).is_none() {
                 return;
             }
         }
@@ -358,7 +357,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
     let ident = match ty {
-        Type::Ident(ident) => ident,
+        Type::Ident(ident) => &ident.rust,
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
@@ -401,20 +400,20 @@ fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
 fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
-            if cx.types.structs.contains_key(ident) {
+            if cx.types.structs.contains_key(&ident.rust) {
                 "struct".to_owned()
-            } else if cx.types.enums.contains_key(ident) {
+            } else if cx.types.enums.contains_key(&ident.rust) {
                 "enum".to_owned()
-            } else if cx.types.aliases.contains_key(ident) {
+            } else if cx.types.aliases.contains_key(&ident.rust) {
                 "C++ type".to_owned()
-            } else if cx.types.cxx.contains(ident) {
+            } else if cx.types.cxx.contains(&ident.rust) {
                 "opaque C++ type".to_owned()
-            } else if cx.types.rust.contains(ident) {
+            } else if cx.types.rust.contains(&ident.rust) {
                 "opaque Rust type".to_owned()
-            } else if Atom::from(ident) == Some(CxxString) {
+            } else if Atom::from(&ident.rust) == Some(CxxString) {
                 "C++ string".to_owned()
             } else {
-                ident.to_string()
+                ident.rust.to_string()
             }
         }
         Type::RustBox(_) => "Box".to_owned(),
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 66f7365..354790a 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,6 +1,5 @@
 use crate::syntax::check::Check;
-use crate::syntax::namespace::Namespace;
-use crate::syntax::{error, Api};
+use crate::syntax::{error, Api, CppName};
 use proc_macro2::Ident;
 
 fn check(cx: &mut Check, ident: &Ident) {
@@ -13,28 +12,31 @@ fn check(cx: &mut Check, ident: &Ident) {
     }
 }
 
-pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
-    for segment in namespace {
+fn check_ident(cx: &mut Check, ident: &CppName) {
+    for segment in &ident.ns {
         check(cx, segment);
     }
+    check(cx, &ident.ident);
+}
 
+pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
     for api in apis {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
-                check(cx, &strct.ident);
+                check_ident(cx, &strct.ident.cxx);
                 for field in &strct.fields {
                     check(cx, &field.ident);
                 }
             }
             Api::Enum(enm) => {
-                check(cx, &enm.ident);
+                check_ident(cx, &enm.ident.cxx);
                 for variant in &enm.variants {
                     check(cx, &variant.ident);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                check(cx, &ety.ident);
+                check_ident(cx, &ety.ident.cxx);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                 check(cx, &efn.ident.rust);
@@ -43,7 +45,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {
                 }
             }
             Api::TypeAlias(alias) => {
-                check(cx, &alias.ident);
+                check_ident(cx, &alias.ident.cxx);
             }
         }
     }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a4b393a..424ad9d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,8 +1,13 @@
-use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{
+    Api, CppName, ExternFn, Impl, Include, Namespace, Pair, Receiver, Ref, ResolvableName,
+    Signature, Slice, Symbol, Ty1, Type, Types,
+};
+use proc_macro2::{Ident, Span};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
+use syn::Token;
 
 impl PartialEq for Include {
     fn eq(&self, other: &Include) -> bool {
@@ -292,3 +297,84 @@ impl Borrow<Type> for &Impl {
         &self.ty
     }
 }
+
+impl Pair {
+    /// Use this constructor when the item can't have a different
+    /// name in Rust and C++. For cases where #[rust_name] and similar
+    /// attributes can be used, construct the object by hand.
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self {
+            rust: ident.clone(),
+            cxx: CppName::new(ns, ident),
+        }
+    }
+}
+
+impl ResolvableName {
+    pub fn new(ident: Ident) -> Self {
+        Self { rust: ident }
+    }
+
+    pub fn from_pair(pair: Pair) -> Self {
+        Self { rust: pair.rust }
+    }
+
+    pub fn make_self(span: Span) -> Self {
+        Self {
+            rust: Token![Self](span).into(),
+        }
+    }
+
+    pub fn is_self(&self) -> bool {
+        self.rust == "Self"
+    }
+
+    pub fn span(&self) -> Span {
+        self.rust.span()
+    }
+
+    pub fn to_symbol(&self, types: &Types) -> Symbol {
+        types.resolve(self).to_symbol()
+    }
+}
+
+impl Api {
+    pub fn get_namespace(&self) -> Option<&Namespace> {
+        match self {
+            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
+            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
+            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
+            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
+            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
+            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
+            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
+        }
+    }
+}
+
+impl CppName {
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self { ns, ident }
+    }
+
+    fn iter_all_segments(
+        &self,
+    ) -> std::iter::Chain<std::slice::Iter<Ident>, std::iter::Once<&Ident>> {
+        self.ns.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/mangle.rs b/syntax/mangle.rs
index e461887..9255feb 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,6 +1,5 @@
-use crate::syntax::namespace::Namespace;
 use crate::syntax::symbol::{self, Symbol};
-use crate::syntax::ExternFn;
+use crate::syntax::{ExternFn, Types};
 use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge05";
@@ -11,19 +10,27 @@ macro_rules! join {
     };
 }
 
-pub fn extern_fn(namespace: &Namespace, efn: &ExternFn) -> Symbol {
+pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
     match &efn.receiver {
-        Some(receiver) => join!(namespace, CXXBRIDGE, receiver.ty, efn.ident.rust),
-        None => join!(namespace, CXXBRIDGE, efn.ident.rust),
+        Some(receiver) => {
+            let receiver_ident = types.resolve(&receiver.ty);
+            join!(
+                efn.ident.cxx.ns,
+                CXXBRIDGE,
+                receiver_ident.ident,
+                efn.ident.rust
+            )
+        }
+        None => join!(efn.ident.cxx.ns, CXXBRIDGE, efn.ident.rust),
     }
 }
 
 // The C half of a function pointer trampoline.
-pub fn c_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
-    join!(extern_fn(namespace, efn), var, 0)
+pub fn c_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var, 0)
 }
 
 // The Rust half of a function pointer trampoline.
-pub fn r_trampoline(namespace: &Namespace, efn: &ExternFn, var: &Ident) -> Symbol {
-    join!(extern_fn(namespace, efn), var, 1)
+pub fn r_trampoline(efn: &ExternFn, var: &Ident, types: &Types) -> Symbol {
+    join!(extern_fn(efn, types), var, 1)
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 180c40a..6498d74 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -21,7 +21,9 @@ mod tokens;
 pub mod types;
 
 use self::discriminant::Discriminant;
+use self::namespace::Namespace;
 use self::parse::kw;
+use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
@@ -33,6 +35,29 @@ pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
+/// A Rust identifier will forver == a proc_macro2::Ident,
+/// but for completeness here's a type alias.
+pub type RsIdent = Ident;
+
+/// At the moment, a Rust name is simply a proc_macro2::Ident.
+/// In the future, it may become namespaced based on a mod path.
+pub type RsName = RsIdent;
+
+/// At the moment, a C++ identifier is also a proc_macro2::Ident.
+/// In the future, we may wish to make a newtype wrapper here
+/// to avoid confusion between C++ and Rust identifiers.
+pub type CppIdent = Ident;
+
+#[derive(Clone)]
+/// 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 unqualfiied name.
+pub struct CppName {
+    pub ns: Namespace,
+    pub ident: CppIdent,
+}
+
 pub enum Api {
     Include(Include),
     Struct(Struct),
@@ -64,7 +89,7 @@ pub enum IncludeKind {
 pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Ident,
+    pub ident: Pair,
     pub semi_token: Token![;],
     pub trusted: bool,
 }
@@ -73,7 +98,7 @@ pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub struct_token: Token![struct],
-    pub ident: Ident,
+    pub ident: Pair,
     pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
@@ -81,15 +106,18 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub enum_token: Token![enum],
-    pub ident: Ident,
+    pub ident: Pair,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
 }
 
+/// A type with a defined Rust name and a fully resolved,
+/// qualified, namespaced, C++ name.
+#[derive(Clone)]
 pub struct Pair {
-    pub cxx: Ident,
-    pub rust: Ident,
+    pub cxx: CppName,
+    pub rust: RsName,
 }
 
 pub struct ExternFn {
@@ -103,7 +131,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Ident,
+    pub ident: Pair,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
@@ -128,7 +156,7 @@ pub struct Signature {
 
 #[derive(Eq, PartialEq, Hash)]
 pub struct Var {
-    pub ident: Ident,
+    pub ident: RsIdent, // fields and variables are not namespaced
     pub ty: Type,
 }
 
@@ -137,18 +165,18 @@ pub struct Receiver {
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
-    pub ty: Ident,
+    pub ty: ResolvableName,
     pub shorthand: bool,
 }
 
 pub struct Variant {
-    pub ident: Ident,
+    pub ident: RsIdent,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
 }
 
 pub enum Type {
-    Ident(Ident),
+    Ident(ResolvableName),
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
@@ -162,7 +190,7 @@ pub enum Type {
 }
 
 pub struct Ty1 {
-    pub name: Ident,
+    pub name: ResolvableName,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
@@ -185,3 +213,10 @@ pub enum Lang {
     Cxx,
     Rust,
 }
+
+/// Wrapper for a type which needs to be resolved
+/// before it can be printed in C++.
+#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
+pub struct ResolvableName {
+    pub rust: RsName,
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3f579a1..7a56ab8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,8 +3,9 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang, Pair,
-    Receiver, Ref, Signature, Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
+    attrs, error, Api, CppName, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
+    Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
+    Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -20,20 +21,22 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api> {
+pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool, ns: &Namespace) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(cx, item) {
+            Item::Struct(item) => match parse_struct(cx, item, ns.clone()) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item) {
+            Item::Enum(item) => match parse_enum(cx, item, ns.clone()) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
-            Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
-            Item::Impl(item) => match parse_impl(item) {
+            Item::ForeignMod(foreign_mod) => {
+                parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, ns)
+            }
+            Item::Impl(item) => match parse_impl(item, ns) {
                 Ok(imp) => apis.push(imp),
                 Err(err) => cx.push(err),
             },
@@ -44,7 +47,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api>
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -65,6 +68,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -81,7 +85,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
         doc,
         derives,
         struct_token: item.struct_token,
-        ident: item.ident,
+        ident: Pair::new(ns.clone(), item.ident),
         brace_token: fields.brace_token,
         fields: fields
             .named
@@ -89,14 +93,14 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct) -> Result<Api> {
             .map(|field| {
                 Ok(Var {
                     ident: field.ident.unwrap(),
-                    ty: parse_type(&field.ty)?,
+                    ty: parse_type(&field.ty, &ns)?,
                 })
             })
             .collect::<Result<_>>()?,
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, mut ns: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -117,6 +121,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
         attrs::Parser {
             doc: Some(&mut doc),
             repr: Some(&mut repr),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -167,7 +172,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum) -> Result<Api> {
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
-        ident: item.ident,
+        ident: Pair::new(ns, item.ident),
         brace_token,
         variants,
         repr,
@@ -179,6 +184,7 @@ fn parse_foreign_mod(
     foreign_mod: ItemForeignMod,
     out: &mut Vec<Api>,
     trusted: bool,
+    ns: &Namespace,
 ) {
     let lang = match parse_lang(&foreign_mod.abi) {
         Ok(lang) => lang,
@@ -202,11 +208,13 @@ fn parse_foreign_mod(
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
-            ForeignItem::Type(foreign) => match parse_extern_type(cx, foreign, lang, trusted) {
-                Ok(ety) => items.push(ety),
-                Err(err) => cx.push(err),
-            },
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang) {
+            ForeignItem::Type(foreign) => {
+                match parse_extern_type(cx, foreign, lang, trusted, ns.clone()) {
+                    Ok(ety) => items.push(ety),
+                    Err(err) => cx.push(err),
+                }
+            }
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, ns.clone()) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -216,10 +224,12 @@ fn parse_foreign_mod(
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Verbatim(tokens) => match parse_extern_verbatim(cx, tokens, lang) {
-                Ok(api) => items.push(api),
-                Err(err) => cx.push(err),
-            },
+            ForeignItem::Verbatim(tokens) => {
+                match parse_extern_verbatim(cx, tokens, lang, ns.clone()) {
+                    Ok(api) => items.push(api),
+                    Err(err) => cx.push(err),
+                }
+            }
             _ => cx.error(foreign, "unsupported foreign item"),
         }
     }
@@ -234,8 +244,8 @@ fn parse_foreign_mod(
         for item in &mut items {
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
-                    if receiver.ty == "Self" {
-                        receiver.ty = single_type.clone();
+                    if receiver.ty.is_self() {
+                        receiver.ty = ResolvableName::from_pair(single_type.clone());
                     }
                 }
             }
@@ -267,8 +277,18 @@ fn parse_extern_type(
     foreign_type: &ForeignItemType,
     lang: Lang,
     trusted: bool,
+    mut ns: Namespace,
 ) -> Result<Api> {
-    let doc = attrs::parse_doc(cx, &foreign_type.attrs);
+    let mut doc = Doc::new();
+    attrs::parse(
+        cx,
+        &foreign_type.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            namespace: Some(&mut ns),
+            ..Default::default()
+        },
+    );
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
     let semi_token = foreign_type.semi_token;
@@ -279,13 +299,18 @@ fn parse_extern_type(
     Ok(api_type(ExternType {
         doc,
         type_token,
-        ident,
+        ident: Pair::new(ns, ident),
         semi_token,
         trusted,
     }))
 }
 
-fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> Result<Api> {
+fn parse_extern_fn(
+    cx: &mut Errors,
+    foreign_fn: &ForeignItemFn,
+    lang: Lang,
+    mut ns: Namespace,
+) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         return Err(Error::new_spanned(
@@ -310,6 +335,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
+            namespace: Some(&mut ns),
             ..Default::default()
         },
     );
@@ -326,7 +352,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                         lifetime: lifetime.clone(),
                         mutability: arg.mutability,
                         var: arg.self_token,
-                        ty: Token![Self](arg.self_token.span).into(),
+                        ty: ResolvableName::make_self(arg.self_token.span),
                         shorthand: true,
                     });
                     continue;
@@ -341,7 +367,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
-                let ty = parse_type(&arg.ty)?;
+                let ty = parse_type(&arg.ty, &ns)?;
                 if ident != "self" {
                     args.push_value(Var { ident, ty });
                     if let Some(comma) = comma {
@@ -355,7 +381,7 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
                             ampersand: reference.ampersand,
                             lifetime: reference.lifetime,
                             mutability: reference.mutability,
-                            var: Token![self](ident.span()),
+                            var: Token![self](ident.rust.span()),
                             ty: ident,
                             shorthand: false,
                         });
@@ -368,12 +394,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     }
 
     let mut throws_tokens = None;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &ns)?;
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = Pair {
-        cxx: cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        cxx: CppName::new(ns, cxx_name.unwrap_or(foreign_fn.sig.ident.clone())),
         rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
     };
     let paren_token = foreign_fn.sig.paren_token;
@@ -401,7 +427,12 @@ fn parse_extern_fn(cx: &mut Errors, foreign_fn: &ForeignItemFn, lang: Lang) -> R
     }))
 }
 
-fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> Result<Api> {
+fn parse_extern_verbatim(
+    cx: &mut Errors,
+    tokens: &TokenStream,
+    lang: Lang,
+    mut ns: Namespace,
+) -> Result<Api> {
     // type Alias = crate::path::to::Type;
     let parse = |input: ParseStream| -> Result<TypeAlias> {
         let attrs = input.call(Attribute::parse_outer)?;
@@ -416,12 +447,21 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
         let eq_token: Token![=] = input.parse()?;
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
-        let doc = attrs::parse_doc(cx, &attrs);
+        let mut doc = Doc::new();
+        attrs::parse(
+            cx,
+            &attrs,
+            attrs::Parser {
+                doc: Some(&mut doc),
+                namespace: Some(&mut ns),
+                ..Default::default()
+            },
+        );
 
         Ok(TypeAlias {
             doc,
             type_token,
-            ident,
+            ident: Pair::new(ns, ident),
             eq_token,
             ty,
             semi_token,
@@ -440,7 +480,7 @@ fn parse_extern_verbatim(cx: &mut Errors, tokens: &TokenStream, lang: Lang) -> R
     }
 }
 
-fn parse_impl(imp: ItemImpl) -> Result<Api> {
+fn parse_impl(imp: ItemImpl, ns: &Namespace) -> Result<Api> {
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -466,7 +506,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
 
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
-        ty: parse_type(&self_ty)?,
+        ty: parse_type(&self_ty, ns)?,
         brace_token: imp.brace_token,
     }))
 }
@@ -515,21 +555,21 @@ fn parse_include(input: ParseStream) -> Result<Include> {
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
 }
 
-fn parse_type(ty: &RustType) -> Result<Type> {
+fn parse_type(ty: &RustType, ns: &Namespace) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => parse_type_reference(ty),
-        RustType::Path(ty) => parse_type_path(ty),
-        RustType::Slice(ty) => parse_type_slice(ty),
-        RustType::BareFn(ty) => parse_type_fn(ty),
+        RustType::Reference(ty) => parse_type_reference(ty, ns),
+        RustType::Path(ty) => parse_type_path(ty, ns),
+        RustType::Slice(ty) => parse_type_slice(ty, ns),
+        RustType::BareFn(ty) => parse_type_fn(ty, ns),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
+fn parse_type_reference(ty: &TypeReference, ns: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, ns)?;
     let which = match &inner {
-        Type::Ident(ident) if ident == "str" => {
+        Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
                 return Err(Error::new_spanned(ty, "unsupported type"));
             } else {
@@ -537,7 +577,7 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
             }
         }
         Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
             _ => Type::Ref,
         },
         _ => Type::Ref,
@@ -550,19 +590,20 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     })))
 }
 
-fn parse_type_path(ty: &TypePath) -> Result<Type> {
+fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
         let ident = segment.ident.clone();
+        let maybe_resolved_ident = ResolvableName::new(ident.clone());
         match &segment.arguments {
-            PathArguments::None => return Ok(Type::Ident(ident)),
+            PathArguments::None => return Ok(Type::Ident(maybe_resolved_ident)),
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -570,9 +611,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -580,9 +621,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -590,9 +631,9 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg)?;
+                        let inner = parse_type(arg, ns)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
-                            name: ident,
+                            name: maybe_resolved_ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -606,15 +647,15 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
+fn parse_type_slice(ty: &TypeSlice, ns: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, ns)?;
     Ok(Type::Slice(Box::new(Slice {
         bracket: ty.bracket_token,
         inner,
     })))
 }
 
-fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
+fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
             ty,
@@ -632,7 +673,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
         .iter()
         .enumerate()
         .map(|(i, arg)| {
-            let ty = parse_type(&arg.ty)?;
+            let ty = parse_type(&arg.ty, ns)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("_{}", i),
@@ -641,7 +682,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
         })
         .collect::<Result<_>>()?;
     let mut throws_tokens = None;
-    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens, ns)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
@@ -658,6 +699,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
 fn parse_return_type(
     ty: &ReturnType,
     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
+    ns: &Namespace,
 ) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
@@ -679,7 +721,7 @@ fn parse_return_type(
             }
         }
     }
-    match parse_type(ret)? {
+    match parse_type(ret, ns)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),
     }
diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index be9bceb..5eefb8d 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -10,6 +10,7 @@ impl QualifiedName {
     pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
         let mut segments = Vec::new();
         let mut trailing_punct = true;
+        input.parse::<Option<Token![::]>>()?;
         while trailing_punct && input.peek(Ident::peek_any) {
             let ident = Ident::parse_any(input)?;
             segments.push(ident);
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 1e5b513..0b79d5f 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -1,4 +1,5 @@
 use crate::syntax::namespace::Namespace;
+use crate::syntax::CppName;
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use std::fmt::{self, Display, Write};
@@ -19,12 +20,6 @@ impl ToTokens for Symbol {
     }
 }
 
-impl From<&Ident> for Symbol {
-    fn from(ident: &Ident) -> Self {
-        Symbol(ident.to_string())
-    }
-}
-
 impl Symbol {
     fn push(&mut self, segment: &dyn Display) {
         let len_before = self.0.len();
@@ -34,18 +29,47 @@ impl Symbol {
         self.0.write_fmt(format_args!("{}", segment)).unwrap();
         assert!(self.0.len() > len_before);
     }
+
+    pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
+        let mut symbol = Symbol(String::new());
+        for segment in it {
+            segment.write(&mut symbol);
+        }
+        assert!(!symbol.0.is_empty());
+        symbol
+    }
+
+    /// For example, for taking a symbol and then making a new symbol
+    /// for a vec of that symbol.
+    pub fn prefix_with(&self, prefix: &str) -> Symbol {
+        Symbol(format!("{}{}", prefix, self.to_string()))
+    }
+}
+
+pub trait Segment {
+    fn write(&self, symbol: &mut Symbol);
 }
 
-pub trait Segment: Display {
+impl Segment for str {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for usize {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for Ident {
+    fn write(&self, symbol: &mut Symbol) {
+        symbol.push(&self);
+    }
+}
+impl Segment for Symbol {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
-
-impl Segment for str {}
-impl Segment for usize {}
-impl Segment for Ident {}
-impl Segment for Symbol {}
 
 impl Segment for Namespace {
     fn write(&self, symbol: &mut Symbol) {
@@ -55,9 +79,16 @@ impl Segment for Namespace {
     }
 }
 
+impl Segment for CppName {
+    fn write(&self, symbol: &mut Symbol) {
+        self.ns.write(symbol);
+        self.ident.write(symbol);
+    }
+}
+
 impl<T> Segment for &'_ T
 where
-    T: ?Sized + Segment,
+    T: ?Sized + Segment + Display,
 {
     fn write(&self, symbol: &mut Symbol) {
         (**self).write(symbol);
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7618e99..57db8eb 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, Signature, Slice, Struct, Ty1,
-    Type, TypeAlias, Var,
+    Atom, Derive, Enum, ExternFn, ExternType, Impl, Pair, Receiver, Ref, ResolvableName, Signature,
+    Slice, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -11,11 +11,11 @@ impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
             Type::Ident(ident) => {
-                if ident == CxxString {
-                    let span = ident.span();
+                if ident.rust == CxxString {
+                    let span = ident.rust.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }
-                ident.to_tokens(tokens);
+                ident.rust.to_tokens(tokens);
             }
             Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                 ty.to_tokens(tokens)
@@ -39,7 +39,7 @@ impl ToTokens for Var {
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
-        let name = self.name.to_string();
+        let name = self.name.rust.to_string();
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
@@ -121,6 +121,12 @@ impl ToTokens for ExternFn {
     }
 }
 
+impl ToTokens for Pair {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.rust.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.impl_token.to_tokens(tokens);
@@ -149,6 +155,12 @@ impl ToTokens for Signature {
     }
 }
 
+impl ToTokens for ResolvableName {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.rust.to_tokens(tokens);
+    }
+}
+
 pub struct ReceiverType<'a>(&'a Receiver);
 
 impl Receiver {
diff --git a/syntax/types.rs b/syntax/types.rs
index 5bac76e..178da3e 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,7 +1,10 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Derive, Enum, ExternFn, ExternType, Impl, Struct, Type, TypeAlias};
+use crate::syntax::{
+    Api, CppName, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    TypeAlias,
+};
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
@@ -16,6 +19,7 @@ pub struct Types<'a> {
     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>,
 }
 
 impl<'a> Types<'a> {
@@ -28,6 +32,7 @@ impl<'a> Types<'a> {
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
         let mut explicit_impls = Set::new();
+        let mut resolutions = Map::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -50,6 +55,10 @@ impl<'a> Types<'a> {
             }
         }
 
+        let mut add_resolution = |pair: &'a Pair| {
+            resolutions.insert(&pair.rust, &pair.cxx);
+        };
+
         let mut type_names = UnorderedSet::new();
         let mut function_names = UnorderedSet::new();
         for api in apis {
@@ -62,7 +71,7 @@ impl<'a> Types<'a> {
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
-                    let ident = &strct.ident;
+                    let ident = &strct.ident.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -73,13 +82,14 @@ impl<'a> Types<'a> {
                         // type, then error.
                         duplicate_name(cx, strct, ident);
                     }
-                    structs.insert(ident, strct);
+                    structs.insert(&strct.ident.rust, strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
+                    add_resolution(&strct.ident);
                 }
                 Api::Enum(enm) => {
-                    let ident = &enm.ident;
+                    let ident = &enm.ident.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -91,9 +101,10 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, enm, ident);
                     }
                     enums.insert(ident, enm);
+                    add_resolution(&enm.ident);
                 }
                 Api::CxxType(ety) => {
-                    let ident = &ety.ident;
+                    let ident = &ety.ident.rust;
                     if !type_names.insert(ident)
                         && (cxx.contains(ident)
                             || !structs.contains_key(ident) && !enums.contains_key(ident))
@@ -107,13 +118,15 @@ impl<'a> Types<'a> {
                     if !ety.trusted {
                         untrusted.insert(ident, ety);
                     }
+                    add_resolution(&ety.ident);
                 }
                 Api::RustType(ety) => {
-                    let ident = &ety.ident;
+                    let ident = &ety.ident.rust;
                     if !type_names.insert(ident) {
                         duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
+                    add_resolution(&ety.ident);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     // Note: duplication of the C++ name is fine because C++ has
@@ -130,11 +143,12 @@ impl<'a> Types<'a> {
                 }
                 Api::TypeAlias(alias) => {
                     let ident = &alias.ident;
-                    if !type_names.insert(ident) {
-                        duplicate_name(cx, alias, ident);
+                    if !type_names.insert(&ident.rust) {
+                        duplicate_name(cx, alias, &ident.rust);
                     }
-                    cxx.insert(ident);
-                    aliases.insert(ident, alias);
+                    cxx.insert(&ident.rust);
+                    aliases.insert(&ident.rust, alias);
+                    add_resolution(&alias.ident);
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
@@ -150,8 +164,8 @@ impl<'a> Types<'a> {
         let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if cxx.contains(ident) {
-                    required_trivial.entry(ident).or_insert(reason);
+                if cxx.contains(&ident.rust) {
+                    required_trivial.entry(&ident.rust).or_insert(reason);
                 }
             }
         };
@@ -187,16 +201,17 @@ impl<'a> Types<'a> {
             untrusted,
             required_trivial,
             explicit_impls,
+            resolutions,
         }
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
         match ty {
             Type::Ident(ident) => {
-                if let Some(strct) = self.structs.get(ident) {
+                if let Some(strct) = self.structs.get(&ident.rust) {
                     !self.is_pod(strct)
                 } else {
-                    Atom::from(ident) == Some(RustString)
+                    Atom::from(&ident.rust) == Some(RustString)
                 }
             }
             Type::RustVec(_) => true,
@@ -212,6 +227,12 @@ impl<'a> Types<'a> {
         }
         false
     }
+
+    pub fn resolve(&self, ident: &ResolvableName) -> &CppName {
+        self.resolutions
+            .get(&ident.rust)
+            .expect("Unable to resolve type")
+    }
 }
 
 impl<'t, 'a> IntoIterator for &'t Types<'a> {
diff --git a/tests/BUCK b/tests/BUCK
index 5bbe500..f51be09 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -15,6 +15,7 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
+        "ffi/class_in_ns.rs",
     ],
     crate = "cxx_test_suite",
     deps = [
@@ -30,6 +31,7 @@ cxx_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
+        ":class_in_ns/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -52,3 +54,8 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
+
+rust_cxx_bridge(
+    name = "class_in_ns",
+    src = "ffi/class_in_ns.rs",
+)
diff --git a/tests/BUILD b/tests/BUILD
index 57ffab9..a400f47 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -18,6 +18,7 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
+        "ffi/class_in_ns.rs",
     ],
     deps = [
         ":impl",
@@ -32,6 +33,7 @@ cc_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
+        ":class_in_ns/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -57,3 +59,9 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
+
+rust_cxx_bridge(
+    name = "class_in_ns",
+    src = "ffi/class_in_ns.rs",
+    deps = [":impl"],
+)
\ No newline at end of file
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 4b2cbdf..9bdb711 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs", "class_in_ns.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
new file mode 100644
index 0000000..8b50561
--- /dev/null
+++ b/tests/ffi/class_in_ns.rs
@@ -0,0 +1,21 @@
+// To test receivers on a type in a namespace outide
+// the default. cxx::bridge blocks can only have a single
+// receiver type, and there can only be one such block per,
+// which is why this is outside.
+
+#[rustfmt::skip]
+#[cxx::bridge(namespace = tests)]
+pub mod ffi3 {
+
+    extern "C" {
+        include!("tests/ffi/tests.h");
+
+        #[namespace (namespace = I)]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace (namespace = I)]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
+    }
+}
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index a809ea4..633cf93 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -12,20 +12,44 @@
 pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
+    impl UniquePtr<F> {}
+    impl UniquePtr<G> {}
 
     extern "C" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
         type E = crate::other::E;
+        #[namespace (namespace = F)]
+        type F = crate::other::f::F;
+        #[namespace (namespace = G)]
+        type G = crate::other::G;
+
+        #[namespace(namespace = H)]
+        type H;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
         fn c_take_trivial(d: D);
+        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
+        fn c_take_trivial_ns_ref(g: &G);
+        fn c_take_trivial_ns(g: G);
         fn c_take_opaque_ptr(e: UniquePtr<E>);
         fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
+        fn c_take_opaque_ns_ref(e: &F);
         fn c_return_trivial_ptr() -> UniquePtr<D>;
         fn c_return_trivial() -> D;
+        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
+        fn c_return_trivial_ns() -> G;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
+        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
+        fn c_take_ref_ns_c(h: &H);
+
+        #[namespace (namespace = other)]
+        fn ns_c_take_trivial(d: D);
+        #[namespace (namespace = other)]
+        fn ns_c_return_trivial() -> D;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4078b37..be145f3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,6 +4,7 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
+pub mod class_in_ns;
 pub mod extra;
 pub mod module;
 
@@ -25,6 +26,32 @@ mod other {
         e_str: CxxString,
     }
 
+    pub mod f {
+        use cxx::kind::Opaque;
+        use cxx::{type_id, CxxString, ExternType};
+
+        #[repr(C)]
+        pub struct F {
+            e: u64,
+            e_str: CxxString,
+        }
+
+        unsafe impl ExternType for F {
+            type Id = type_id!("F::F");
+            type Kind = Opaque;
+        }
+    }
+
+    #[repr(C)]
+    pub struct G {
+        pub g: u64,
+    }
+
+    unsafe impl ExternType for G {
+        type Id = type_id!("G::G");
+        type Kind = Trivial;
+    }
+
     unsafe impl ExternType for D {
         type Id = type_id!("tests::D");
         type Kind = Trivial;
@@ -49,6 +76,32 @@ pub mod ffi {
         CVal,
     }
 
+    #[namespace(namespace = A)]
+    #[derive(Clone)]
+    struct AShared {
+        z: usize,
+    }
+
+    #[namespace(namespace = A)]
+    enum AEnum {
+        AAVal,
+        ABVal = 2020,
+        ACVal,
+    }
+
+    #[namespace(namespace = A::B)]
+    enum ABEnum {
+        ABAVal,
+        ABBVal = 2020,
+        ABCVal,
+    }
+
+    #[namespace(namespace = A::B)]
+    #[derive(Clone)]
+    struct ABShared {
+        z: usize,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 
@@ -78,6 +131,10 @@ pub mod ffi {
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
         fn c_return_enum(n: u16) -> Enum;
+        fn c_return_ns_ref(shared: &AShared) -> &usize;
+        fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
+        fn c_return_ns_enum(n: u16) -> AEnum;
+        fn c_return_nested_ns_enum(n: u16) -> ABEnum;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -108,6 +165,12 @@ pub mod ffi {
         fn c_take_callback(callback: fn(String) -> usize);
         */
         fn c_take_enum(e: Enum);
+        fn c_take_ns_enum(e: AEnum);
+        fn c_take_nested_ns_enum(e: ABEnum);
+        fn c_take_ns_shared(shared: AShared);
+        fn c_take_nested_ns_shared(shared: ABShared);
+        fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
+        fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
@@ -137,6 +200,9 @@ pub mod ffi {
         fn cOverloadedFunction(x: i32) -> String;
         #[rust_name = "str_overloaded_function"]
         fn cOverloadedFunction(x: &str) -> String;
+
+        #[namespace (namespace = other)]
+        fn ns_c_take_ns_shared(shared: AShared);
     }
 
     extern "C" {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 983cf95..05bf5fb 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -43,6 +43,10 @@ size_t c_return_primitive() { return 2020; }
 
 Shared c_return_shared() { return Shared{2020}; }
 
+::A::AShared c_return_ns_shared() { return ::A::AShared{2020}; }
+
+::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; }
+
 rust::Box<R> c_return_box() {
   return rust::Box<R>::from_raw(cxx_test_suite_get_box());
 }
@@ -51,8 +55,16 @@ std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
 
+std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
+  return std::unique_ptr<::H::H>(new ::H::H{"hello"});
+}
+
 const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
+const size_t &c_return_ns_ref(const ::A::AShared &shared) { return shared.z; }
+
+const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { return shared.z; }
+
 size_t &c_return_mut(Shared &shared) { return shared.z; }
 
 rust::Str c_return_str(const Shared &shared) {
@@ -144,6 +156,26 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+::A::AEnum c_return_ns_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(::A::AEnum::AAVal)) {
+    return ::A::AEnum::AAVal;
+  } else if (n <= static_cast<uint16_t>(::A::AEnum::ABVal)) {
+    return ::A::AEnum::ABVal;
+  } else {
+    return ::A::AEnum::ACVal;
+  }
+}
+
+::A::B::ABEnum c_return_nested_ns_enum(uint16_t n) {
+  if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABAVal)) {
+    return ::A::B::ABEnum::ABAVal;
+  } else if (n <= static_cast<uint16_t>(::A::B::ABEnum::ABBVal)) {
+    return ::A::B::ABEnum::ABBVal;
+  } else {
+    return ::A::B::ABEnum::ABCVal;
+  }
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
@@ -156,6 +188,18 @@ void c_take_shared(Shared shared) {
   }
 }
 
+void c_take_ns_shared(::A::AShared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_nested_ns_shared(::A::B::ABShared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_box(rust::Box<R> r) {
   if (cxx_test_suite_r_is_correct(&*r)) {
     cxx_test_suite_set_correct();
@@ -180,6 +224,12 @@ void c_take_ref_c(const C &c) {
   }
 }
 
+void c_take_ref_ns_c(const ::H::H &h) {
+  if (h.h == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_str(rust::Str s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
@@ -258,6 +308,26 @@ void c_take_rust_vec_shared(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v) {
+  uint32_t sum = 0;
+  for (auto i : v) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v) {
+  uint32_t sum = 0;
+  for (auto i : v) {
+    sum += i.z;
+  }
+  if (sum == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_vec_string(rust::Vec<rust::String> v) {
   (void)v;
   cxx_test_suite_set_correct();
@@ -326,6 +396,18 @@ void c_take_enum(Enum e) {
   }
 }
 
+void c_take_ns_enum(::A::AEnum e) {
+  if (e == ::A::AEnum::AAVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_nested_ns_enum(::A::B::ABEnum e) {
+  if (e == ::A::B::ABEnum::ABAVal) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
@@ -394,24 +476,56 @@ void c_take_trivial_ref(const D& d) {
     cxx_test_suite_set_correct();
   }
 }
+
 void c_take_trivial(D d) {
   if (d.d == 30) {
     cxx_test_suite_set_correct();
   }
 }
 
+
+void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g) {
+  if (g->g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ns_ref(const ::G::G& g) {
+  if (g.g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_trivial_ns(::G::G g) {
+  if (g.g == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ptr(std::unique_ptr<E> e) {
   if (e->e == 40) {
     cxx_test_suite_set_correct();
   }
 }
 
+void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f) {
+  if (f->f == 40) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ref(const E& e) {
   if (e.e == 40 && e.e_str == "hello") {
     cxx_test_suite_set_correct();
   }
 }
 
+void c_take_opaque_ns_ref(const ::F::F& f) {
+  if (f.f == 40 && f.f_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 std::unique_ptr<D> c_return_trivial_ptr() {
   auto d = std::unique_ptr<D>(new D());
   d->d = 30;
@@ -424,6 +538,18 @@ D c_return_trivial() {
   return d;
 }
 
+std::unique_ptr<::G::G> c_return_trivial_ns_ptr() {
+  auto g = std::unique_ptr<::G::G>(new ::G::G());
+  g->g = 30;
+  return g;
+}
+
+::G::G c_return_trivial_ns() {
+  ::G::G g;
+  g.g = 30;
+  return g;
+}
+
 std::unique_ptr<E> c_return_opaque_ptr() {
   auto e = std::unique_ptr<E>(new E());
   e->e = 40;
@@ -431,6 +557,13 @@ std::unique_ptr<E> c_return_opaque_ptr() {
   return e;
 }
 
+std::unique_ptr<::F::F> c_return_ns_opaque_ptr() {
+  auto f = std::unique_ptr<::F::F>(new ::F::F());
+  f->f = 40;
+  f->f_str = std::string("hello");
+  return f;
+}
+
 extern "C" const char *cxx_run_test() noexcept {
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
@@ -494,3 +627,34 @@ extern "C" const char *cxx_run_test() noexcept {
 }
 
 } // namespace tests
+
+namespace other {
+
+  void ns_c_take_trivial(::tests::D d) {
+    if (d.d == 30) {
+      cxx_test_suite_set_correct();
+    }
+  }
+
+  ::tests::D ns_c_return_trivial() {
+    ::tests::D d;
+    d.d = 30;
+    return d;
+  }
+
+  void ns_c_take_ns_shared(::A::AShared shared) {
+    if (shared.z == 2020) {
+      cxx_test_suite_set_correct();
+    }
+  }
+} // namespace other
+
+namespace I {
+  uint32_t I::get() const {
+    return a;
+  }
+
+  std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
+    return std::unique_ptr<I>(new I());
+  }
+} // namespace I
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index b3f547e..3835660 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -3,6 +3,35 @@
 #include <memory>
 #include <string>
 
+namespace A {
+  struct AShared;
+  enum class AEnum : uint16_t;
+  namespace B {
+    struct ABShared;
+    enum class ABEnum : uint16_t;
+  } // namespace B
+} // namespace A
+
+namespace F {
+  struct F {
+    uint64_t f;
+    std::string f_str;
+  };
+}
+
+namespace G {
+  struct G {
+    uint64_t g;
+  };
+}
+
+namespace H {
+  class H {
+  public:
+    std::string h;
+  };
+}
+
 namespace tests {
 
 struct R;
@@ -44,9 +73,14 @@ enum COwnedEnum {
 
 size_t c_return_primitive();
 Shared c_return_shared();
+::A::AShared c_return_ns_shared();
+::A::B::ABShared c_return_nested_ns_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
+std::unique_ptr<::H::H> c_return_ns_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
+const size_t &c_return_ns_ref(const ::A::AShared &shared);
+const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
@@ -66,13 +100,18 @@ rust::Vec<rust::String> c_return_rust_vec_string();
 size_t c_return_identity(size_t n);
 size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
+::A::AEnum c_return_ns_enum(uint16_t n);
+::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
+void c_take_ns_shared(::A::AShared shared);
+void c_take_nested_ns_shared(::A::B::ABShared shared);
 void c_take_box(rust::Box<R> r);
 void c_take_unique_ptr(std::unique_ptr<C> c);
 void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
+void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<uint8_t> s);
 void c_take_rust_string(rust::String s);
@@ -86,6 +125,8 @@ void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);
 void c_take_rust_vec_index(rust::Vec<uint8_t> v);
 void c_take_rust_vec_shared(rust::Vec<Shared> v);
+void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v);
+void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v);
 void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
@@ -98,6 +139,8 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 */
 void c_take_enum(Enum e);
+void c_take_ns_enum(::A::AEnum e);
+void c_take_nested_ns_enum(::A::B::ABEnum e);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
@@ -115,13 +158,40 @@ const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D& d);
 void c_take_trivial(D d);
+
+void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g);
+void c_take_trivial_ns_ref(const ::G::G& g);
+void c_take_trivial_ns(::G::G g);
 void c_take_opaque_ptr(std::unique_ptr<E> e);
+void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f);
 void c_take_opaque_ref(const E& e);
+void c_take_opaque_ns_ref(const ::F::F& f);
 std::unique_ptr<D> c_return_trivial_ptr();
 D c_return_trivial();
+std::unique_ptr<::G::G> c_return_trivial_ns_ptr();
+::G::G c_return_trivial_ns();
 std::unique_ptr<E> c_return_opaque_ptr();
+std::unique_ptr<::F::F> c_return_ns_opaque_ptr();
 
 rust::String cOverloadedFunction(int32_t x);
 rust::String cOverloadedFunction(rust::Str x);
 
 } // namespace tests
+
+namespace other {
+  void ns_c_take_trivial(::tests::D d);
+  ::tests::D ns_c_return_trivial();
+  void ns_c_take_ns_shared(::A::AShared shared);
+} // namespace other
+
+namespace I {
+  class I {
+  private:
+    uint32_t a;
+  public:
+    I() : a(1000) {}
+    uint32_t get() const;
+  };
+
+  std::unique_ptr<I> ns_c_return_unique_ptr_ns();
+} // namespace I
diff --git a/tests/test.rs b/tests/test.rs
index b92eebf..20b23ac 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,3 +1,4 @@
+use cxx_test_suite::class_in_ns::ffi3;
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;
@@ -23,12 +24,17 @@ macro_rules! check {
 #[test]
 fn test_c_return() {
     let shared = ffi::Shared { z: 2020 };
+    let ns_shared = ffi::AShared { z: 2020 };
+    let nested_ns_shared = ffi::ABShared { z: 2020 };
 
     assert_eq!(2020, ffi::c_return_primitive());
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, *ffi::c_return_box());
     ffi::c_return_unique_ptr();
+    ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
+    assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
+    assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
     assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
     assert_eq!("2020", ffi::c_return_rust_string());
@@ -64,6 +70,14 @@ fn test_c_return() {
         enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
+    match ffi::c_return_ns_enum(0) {
+        enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr),
+        _ => assert!(false),
+    }
+    match ffi::c_return_nested_ns_enum(0) {
+        enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr),
+        _ => assert!(false),
+    }
 }
 
 #[test]
@@ -85,11 +99,16 @@ fn test_c_try_return() {
 #[test]
 fn test_c_take() {
     let unique_ptr = ffi::c_return_unique_ptr();
+    let unique_ptr_ns = ffi2::c_return_ns_unique_ptr();
 
     check!(ffi::c_take_primitive(2020));
     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
+    check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 }));
+    check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 }));
+    check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
     check!(ffi::c_take_box(Box::new(2020)));
     check!(ffi::c_take_ref_c(&unique_ptr));
+    check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
@@ -119,7 +138,16 @@ fn test_c_take() {
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }];
+    check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec));
+    let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }];
+    check!(ffi::c_take_rust_vec_nested_ns_shared(
+        nested_ns_shared_test_vec
+    ));
+
     check!(ffi::c_take_enum(ffi::Enum::AVal));
+    check!(ffi::c_take_ns_enum(ffi::AEnum::AAVal));
+    check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
 }
 
 /*
@@ -167,6 +195,14 @@ fn test_c_method_calls() {
 }
 
 #[test]
+fn test_c_ns_method_calls() {
+    let unique_ptr = ffi3::ns_c_return_unique_ptr_ns();
+
+    let old_value = unique_ptr.get();
+    assert_eq!(1000, old_value);
+}
+
+#[test]
 fn test_enum_representations() {
     assert_eq!(0, ffi::Enum::AVal.repr);
     assert_eq!(2020, ffi::Enum::BVal.repr);
@@ -200,6 +236,15 @@ fn test_extern_trivial() {
     let d = ffi2::c_return_trivial_ptr();
     check!(ffi2::c_take_trivial_ptr(d));
     cxx::UniquePtr::new(ffi2::D { d: 42 });
+    let d = ffi2::ns_c_return_trivial();
+    check!(ffi2::ns_c_take_trivial(d));
+
+    let g = ffi2::c_return_trivial_ns();
+    check!(ffi2::c_take_trivial_ns_ref(&g));
+    check!(ffi2::c_take_trivial_ns(g));
+    let g = ffi2::c_return_trivial_ns_ptr();
+    check!(ffi2::c_take_trivial_ns_ptr(g));
+    cxx::UniquePtr::new(ffi2::G { g: 42 });
 }
 
 #[test]
@@ -207,4 +252,8 @@ fn test_extern_opaque() {
     let e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ptr(e));
+
+    let f = ffi2::c_return_ns_opaque_ptr();
+    check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap()));
+    check!(ffi2::c_take_opaque_ns_ptr(f));
 }
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 0a56dd4..a860f3d 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,7 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `S`
+error: needs a cxx::ExternType impl in order to be used as a field of `::S`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;

From 3e5cff4a3d29873e0cadb33f2990e63988e5c045 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 02:48:45 +0000
Subject: [PATCH 1079/2232] Switch to #[namespace = A::B] syntax.


Thanks to sbrocket for this parsing code.

---

diff --git a/gen/src/file.rs b/gen/src/file.rs
index c696407..1b324cb 100644
--- a/gen/src/file.rs
+++ b/gen/src/file.rs
@@ -67,6 +67,6 @@ fn parse_args(attr: &Attribute) -> Result<Namespace> {
     if attr.tokens.is_empty() {
         Ok(Namespace::none())
     } else {
-        attr.parse_args()
+        attr.parse_args_with(Namespace::parse_bridge_attr_namespace)
     }
 }
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 291b03c..4d9b986 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -18,7 +18,7 @@ use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
 use proc_macro::TokenStream;
-use syn::parse::{Parse, ParseStream, Result};
+use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
 
 /// `#[cxx::bridge] mod ffi { ... }`
@@ -42,7 +42,10 @@ use syn::parse_macro_input;
 pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
-    let namespace = parse_macro_input!(args as Namespace);
+    let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) {
+        Ok(ns) => ns,
+        Err(err) => return err.to_compile_error().into(),
+    };
     let mut ffi = parse_macro_input!(input as Module);
     ffi.namespace = namespace;
 
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 25af229..af73b7a 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -132,8 +132,7 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
 }
 
 fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
-    let content;
-    syn::parenthesized!(content in input);
-    let namespace = content.parse::<Namespace>()?;
+    input.parse::<Token![=]>()?;
+    let namespace = input.parse::<Namespace>()?;
     Ok(namespace)
 }
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 49b31d1..b4c6716 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -24,19 +24,23 @@ impl Namespace {
     pub fn iter(&self) -> Iter<Ident> {
         self.segments.iter()
     }
+
+    pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
+        if input.is_empty() {
+            return Ok(Namespace::none());
+        }
+
+        input.parse::<kw::namespace>()?;
+        input.parse::<Token![=]>()?;
+        let ns = input.parse::<Namespace>()?;
+        input.parse::<Option<Token![,]>>()?;
+        Ok(ns)
+    }
 }
 
 impl Parse for Namespace {
     fn parse(input: ParseStream) -> Result<Self> {
-        let mut segments = Vec::new();
-        if !input.is_empty() {
-            input.parse::<kw::namespace>()?;
-            input.parse::<Token![=]>()?;
-            segments = input
-                .call(QualifiedName::parse_quoted_or_unquoted)?
-                .segments;
-            input.parse::<Option<Token![,]>>()?;
-        }
+        let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
         Ok(Namespace { segments })
     }
 }
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
index 8b50561..a03da78 100644
--- a/tests/ffi/class_in_ns.rs
+++ b/tests/ffi/class_in_ns.rs
@@ -10,12 +10,12 @@ pub mod ffi3 {
     extern "C" {
         include!("tests/ffi/tests.h");
 
-        #[namespace (namespace = I)]
+        #[namespace = "I"]
         type I;
 
         fn get(self: &I) -> u32;
 
-        #[namespace (namespace = I)]
+        #[namespace = "I"]
         fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
     }
 }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 633cf93..58700a2 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -20,12 +20,12 @@ pub mod ffi2 {
 
         type D = crate::other::D;
         type E = crate::other::E;
-        #[namespace (namespace = F)]
+        #[namespace = "F"]
         type F = crate::other::f::F;
-        #[namespace (namespace = G)]
+        #[namespace = "G"]
         type G = crate::other::G;
 
-        #[namespace(namespace = H)]
+        #[namespace = "H"]
         type H;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
@@ -47,9 +47,9 @@ pub mod ffi2 {
         fn c_return_ns_unique_ptr() -> UniquePtr<H>;
         fn c_take_ref_ns_c(h: &H);
 
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_take_trivial(d: D);
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_return_trivial() -> D;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index be145f3..17146ce 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -76,27 +76,27 @@ pub mod ffi {
         CVal,
     }
 
-    #[namespace(namespace = A)]
+    #[namespace = "A"]
     #[derive(Clone)]
     struct AShared {
         z: usize,
     }
 
-    #[namespace(namespace = A)]
+    #[namespace = "A"]
     enum AEnum {
         AAVal,
         ABVal = 2020,
         ACVal,
     }
 
-    #[namespace(namespace = A::B)]
+    #[namespace = "A::B"]
     enum ABEnum {
         ABAVal,
         ABBVal = 2020,
         ABCVal,
     }
 
-    #[namespace(namespace = A::B)]
+    #[namespace = "A::B"]
     #[derive(Clone)]
     struct ABShared {
         z: usize,
@@ -201,7 +201,7 @@ pub mod ffi {
         #[rust_name = "str_overloaded_function"]
         fn cOverloadedFunction(x: &str) -> String;
 
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_take_ns_shared(shared: AShared);
     }
 

From 71b34be0be6457e9d939a9005f0f246dc7f98218 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 30 2020 03:05:09 +0000
Subject: [PATCH 1080/2232] Merge pull request #380 from adetaylor/namespaces-syntax-update


Switch to #[namespace = A::B] syntax.
---

diff --git a/gen/src/file.rs b/gen/src/file.rs
index c696407..1b324cb 100644
--- a/gen/src/file.rs
+++ b/gen/src/file.rs
@@ -67,6 +67,6 @@ fn parse_args(attr: &Attribute) -> Result<Namespace> {
     if attr.tokens.is_empty() {
         Ok(Namespace::none())
     } else {
-        attr.parse_args()
+        attr.parse_args_with(Namespace::parse_bridge_attr_namespace)
     }
 }
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 291b03c..4d9b986 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -18,7 +18,7 @@ use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
 use proc_macro::TokenStream;
-use syn::parse::{Parse, ParseStream, Result};
+use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
 
 /// `#[cxx::bridge] mod ffi { ... }`
@@ -42,7 +42,10 @@ use syn::parse_macro_input;
 pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
-    let namespace = parse_macro_input!(args as Namespace);
+    let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) {
+        Ok(ns) => ns,
+        Err(err) => return err.to_compile_error().into(),
+    };
     let mut ffi = parse_macro_input!(input as Module);
     ffi.namespace = namespace;
 
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 25af229..af73b7a 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -132,8 +132,7 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
 }
 
 fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
-    let content;
-    syn::parenthesized!(content in input);
-    let namespace = content.parse::<Namespace>()?;
+    input.parse::<Token![=]>()?;
+    let namespace = input.parse::<Namespace>()?;
     Ok(namespace)
 }
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 49b31d1..b4c6716 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -24,19 +24,23 @@ impl Namespace {
     pub fn iter(&self) -> Iter<Ident> {
         self.segments.iter()
     }
+
+    pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
+        if input.is_empty() {
+            return Ok(Namespace::none());
+        }
+
+        input.parse::<kw::namespace>()?;
+        input.parse::<Token![=]>()?;
+        let ns = input.parse::<Namespace>()?;
+        input.parse::<Option<Token![,]>>()?;
+        Ok(ns)
+    }
 }
 
 impl Parse for Namespace {
     fn parse(input: ParseStream) -> Result<Self> {
-        let mut segments = Vec::new();
-        if !input.is_empty() {
-            input.parse::<kw::namespace>()?;
-            input.parse::<Token![=]>()?;
-            segments = input
-                .call(QualifiedName::parse_quoted_or_unquoted)?
-                .segments;
-            input.parse::<Option<Token![,]>>()?;
-        }
+        let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
         Ok(Namespace { segments })
     }
 }
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
index 8b50561..a03da78 100644
--- a/tests/ffi/class_in_ns.rs
+++ b/tests/ffi/class_in_ns.rs
@@ -10,12 +10,12 @@ pub mod ffi3 {
     extern "C" {
         include!("tests/ffi/tests.h");
 
-        #[namespace (namespace = I)]
+        #[namespace = "I"]
         type I;
 
         fn get(self: &I) -> u32;
 
-        #[namespace (namespace = I)]
+        #[namespace = "I"]
         fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
     }
 }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 633cf93..58700a2 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -20,12 +20,12 @@ pub mod ffi2 {
 
         type D = crate::other::D;
         type E = crate::other::E;
-        #[namespace (namespace = F)]
+        #[namespace = "F"]
         type F = crate::other::f::F;
-        #[namespace (namespace = G)]
+        #[namespace = "G"]
         type G = crate::other::G;
 
-        #[namespace(namespace = H)]
+        #[namespace = "H"]
         type H;
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
@@ -47,9 +47,9 @@ pub mod ffi2 {
         fn c_return_ns_unique_ptr() -> UniquePtr<H>;
         fn c_take_ref_ns_c(h: &H);
 
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_take_trivial(d: D);
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_return_trivial() -> D;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index be145f3..17146ce 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -76,27 +76,27 @@ pub mod ffi {
         CVal,
     }
 
-    #[namespace(namespace = A)]
+    #[namespace = "A"]
     #[derive(Clone)]
     struct AShared {
         z: usize,
     }
 
-    #[namespace(namespace = A)]
+    #[namespace = "A"]
     enum AEnum {
         AAVal,
         ABVal = 2020,
         ACVal,
     }
 
-    #[namespace(namespace = A::B)]
+    #[namespace = "A::B"]
     enum ABEnum {
         ABAVal,
         ABBVal = 2020,
         ABCVal,
     }
 
-    #[namespace(namespace = A::B)]
+    #[namespace = "A::B"]
     #[derive(Clone)]
     struct ABShared {
         z: usize,
@@ -201,7 +201,7 @@ pub mod ffi {
         #[rust_name = "str_overloaded_function"]
         fn cOverloadedFunction(x: &str) -> String;
 
-        #[namespace (namespace = other)]
+        #[namespace = "other"]
         fn ns_c_take_ns_shared(shared: AShared);
     }
 

From 565ddf035eb945b14cc0b3e6dc00fefac6643db9 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 04:12:36 +0000
Subject: [PATCH 1081/2232] Code review comments on namespace work.


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index c54e784..ee7408e 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -2,39 +2,49 @@ use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 
-pub(crate) struct NamespaceEntries<'a> {
-    pub(crate) entries: Vec<&'a Api>,
-    pub(crate) children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+pub struct NamespaceEntries<'a> {
+    entries: Vec<&'a Api>,
+    children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
 
-pub(crate) fn sort_by_namespace(apis: &[Api]) -> NamespaceEntries {
-    let api_refs = apis.iter().collect::<Vec<_>>();
-    sort_by_inner_namespace(api_refs, 0)
-}
+impl<'a> NamespaceEntries<'a> {
+    pub fn new(apis: &'a [Api]) -> Self {
+        let api_refs = apis.iter().collect::<Vec<_>>();
+        Self::sort_by_inner_namespace(api_refs, 0)
+    }
 
-fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
-    let mut root = NamespaceEntries {
-        entries: Vec::new(),
-        children: BTreeMap::new(),
-    };
-
-    let mut kids_by_child_ns = BTreeMap::new();
-    for api in apis {
-        if let Some(ns) = api.get_namespace() {
-            let first_ns_elem = ns.iter().nth(depth);
-            if let Some(first_ns_elem) = first_ns_elem {
-                let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
-                list.push(api);
-                continue;
-            }
-        }
-        root.entries.push(api);
+    pub fn entries(&self) -> &[&'a Api] {
+        &self.entries
     }
 
-    for (k, v) in kids_by_child_ns.into_iter() {
-        root.children
-            .insert(k, sort_by_inner_namespace(v, depth + 1));
+    pub fn children(&self) -> impl Iterator<Item = (&&Ident, &NamespaceEntries)> {
+        self.children.iter()
     }
 
-    root
+    fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
+        let mut root = NamespaceEntries {
+            entries: Vec::new(),
+            children: BTreeMap::new(),
+        };
+
+        let mut kids_by_child_ns = BTreeMap::new();
+        for api in apis {
+            if let Some(ns) = api.get_namespace() {
+                let first_ns_elem = ns.iter().nth(depth);
+                if let Some(first_ns_elem) = first_ns_elem {
+                    let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
+                    list.push(api);
+                    continue;
+                }
+            }
+            root.entries.push(api);
+        }
+
+        for (k, v) in kids_by_child_ns.into_iter() {
+            root.children
+                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
+        }
+
+        root
+    }
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 967d4ff..7e7a9ea 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,4 @@
-use crate::gen::namespace_organizer::{sort_by_namespace, NamespaceEntries};
+use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -30,7 +30,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> OutFi
 
     out.next_section();
 
-    let apis_by_namespace = sort_by_namespace(apis);
+    let apis_by_namespace = NamespaceEntries::new(apis);
 
     gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
 
@@ -51,10 +51,10 @@ fn gen_namespace_contents(
     header: bool,
     out: &mut OutFile,
 ) {
-    let apis = &ns_entries.entries;
+    let apis = ns_entries.entries();
 
     out.next_section();
-    for api in apis {
+    for api in apis.into_iter() {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
@@ -64,7 +64,7 @@ fn gen_namespace_contents(
     }
 
     let mut methods_for_type = HashMap::new();
-    for api in apis {
+    for api in apis.into_iter() {
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
@@ -134,7 +134,7 @@ fn gen_namespace_contents(
 
     out.next_section();
 
-    for (child_ns, child_ns_entries) in &ns_entries.children {
+    for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
         gen_namespace_contents(&child_ns_entries, types, opt, header, out);
         writeln!(out, "}} // namespace {}", child_ns);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 424ad9d..92c804a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -315,10 +315,6 @@ impl ResolvableName {
         Self { rust: ident }
     }
 
-    pub fn from_pair(pair: Pair) -> Self {
-        Self { rust: pair.rust }
-    }
-
     pub fn make_self(span: Span) -> Self {
         Self {
             rust: Token![Self](span).into(),
@@ -357,9 +353,7 @@ impl CppName {
         Self { ns, ident }
     }
 
-    fn iter_all_segments(
-        &self,
-    ) -> std::iter::Chain<std::slice::Iter<Ident>, std::iter::Once<&Ident>> {
+    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
         self.ns.iter().chain(std::iter::once(&self.ident))
     }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7a56ab8..484b101 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -245,7 +245,7 @@ fn parse_foreign_mod(
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
                     if receiver.ty.is_self() {
-                        receiver.ty = ResolvableName::from_pair(single_type.clone());
+                        receiver.ty = ResolvableName::new(single_type.rust.clone());
                     }
                 }
             }

From f2d9d86c3dd9185d7ffb94749a779ec5f33bac6d Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 04:21:30 +0000
Subject: [PATCH 1082/2232] Simplify test suite.


---

diff --git a/tests/BUCK b/tests/BUCK
index f51be09..5bbe500 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -15,7 +15,6 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
-        "ffi/class_in_ns.rs",
     ],
     crate = "cxx_test_suite",
     deps = [
@@ -31,7 +30,6 @@ cxx_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
-        ":class_in_ns/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -54,8 +52,3 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
-
-rust_cxx_bridge(
-    name = "class_in_ns",
-    src = "ffi/class_in_ns.rs",
-)
diff --git a/tests/BUILD b/tests/BUILD
index a400f47..57ffab9 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -18,7 +18,6 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
-        "ffi/class_in_ns.rs",
     ],
     deps = [
         ":impl",
@@ -33,7 +32,6 @@ cc_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
-        ":class_in_ns/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -59,9 +57,3 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
-
-rust_cxx_bridge(
-    name = "class_in_ns",
-    src = "ffi/class_in_ns.rs",
-    deps = [":impl"],
-)
\ No newline at end of file
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 9bdb711..4b2cbdf 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs", "class_in_ns.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
deleted file mode 100644
index a03da78..0000000
--- a/tests/ffi/class_in_ns.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// To test receivers on a type in a namespace outide
-// the default. cxx::bridge blocks can only have a single
-// receiver type, and there can only be one such block per,
-// which is why this is outside.
-
-#[rustfmt::skip]
-#[cxx::bridge(namespace = tests)]
-pub mod ffi3 {
-
-    extern "C" {
-        include!("tests/ffi/tests.h");
-
-        #[namespace = "I"]
-        type I;
-
-        fn get(self: &I) -> u32;
-
-        #[namespace = "I"]
-        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
-    }
-}
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 58700a2..a11970d 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -51,5 +51,13 @@ pub mod ffi2 {
         fn ns_c_take_trivial(d: D);
         #[namespace = "other"]
         fn ns_c_return_trivial() -> D;
+
+        #[namespace = "I"]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace = "I"]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 17146ce..fee5bcb 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,7 +4,6 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
-pub mod class_in_ns;
 pub mod extra;
 pub mod module;
 
diff --git a/tests/test.rs b/tests/test.rs
index 20b23ac..b651feb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,4 +1,3 @@
-use cxx_test_suite::class_in_ns::ffi3;
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;
@@ -196,7 +195,7 @@ fn test_c_method_calls() {
 
 #[test]
 fn test_c_ns_method_calls() {
-    let unique_ptr = ffi3::ns_c_return_unique_ptr_ns();
+    let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
 
     let old_value = unique_ptr.get();
     assert_eq!(1000, old_value);

From 0447e96b840fa1a6fd7bc271cdceda64b45bea59 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 04:22:24 +0000
Subject: [PATCH 1083/2232] Revert to older error string.


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 08e0dfa..ba488e1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -211,9 +211,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
 
     if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
         let what = match reason {
-            TrivialReason::StructField(strct) => {
-                format!("a field of `{}`", strct.ident.cxx.to_fully_qualified())
-            }
+            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident.rust),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index a860f3d..0a56dd4 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,7 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `::S`
+error: needs a cxx::ExternType impl in order to be used as a field of `S`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;

From 0f8ab22aee30f30a86073fee792f831de955aff7 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 04:33:49 +0000
Subject: [PATCH 1084/2232] Improving Pair construction.


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 92c804a..f4c5b05 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -300,14 +300,22 @@ impl Borrow<Type> for &Impl {
 
 impl Pair {
     /// Use this constructor when the item can't have a different
-    /// name in Rust and C++. For cases where #[rust_name] and similar
-    /// attributes can be used, construct the object by hand.
+    /// name in Rust and C++.
     pub fn new(ns: Namespace, ident: Ident) -> Self {
         Self {
             rust: ident.clone(),
             cxx: CppName::new(ns, ident),
         }
     }
+
+    /// 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(ns: Namespace, cxx_ident: Ident, rust_ident: Ident) -> Self {
+        Self {
+            rust: rust_ident,
+            cxx: CppName::new(ns, cxx_ident),
+        }
+    }
 }
 
 impl ResolvableName {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 484b101..1927554 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, CppName, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
@@ -398,10 +398,11 @@ fn parse_extern_fn(
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let ident = Pair {
-        cxx: CppName::new(ns, cxx_name.unwrap_or(foreign_fn.sig.ident.clone())),
-        rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
-    };
+    let ident = Pair::new_from_differing_names(
+        ns,
+        cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
+    );
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
     let api_function = match lang {

From 7827d78f293d7c11222d0de7280066901578ec68 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 05:14:34 +0000
Subject: [PATCH 1085/2232] Add tests for namespace sorter.


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index ee7408e..4aacc8f 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -48,3 +48,81 @@ impl<'a> NamespaceEntries<'a> {
         root
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::NamespaceEntries;
+    use crate::syntax::namespace::Namespace;
+    use crate::syntax::{Api, Doc, ExternType, Pair};
+    use proc_macro2::{Ident, Span};
+    use syn::Token;
+
+    #[test]
+    fn test_ns_entries_sort() {
+        let entries = vec![
+            make_api(None, "C"),
+            make_api(None, "A"),
+            make_api(Some("G"), "E"),
+            make_api(Some("D"), "F"),
+            make_api(Some("G"), "H"),
+            make_api(Some("D::K"), "L"),
+            make_api(Some("D::K"), "M"),
+            make_api(None, "B"),
+            make_api(Some("D"), "I"),
+            make_api(Some("D"), "J"),
+        ];
+        let ns = NamespaceEntries::new(&entries);
+        let root_entries = ns.entries();
+        assert_eq!(root_entries.len(), 3);
+        assert_ident(root_entries[0], "C");
+        assert_ident(root_entries[1], "A");
+        assert_ident(root_entries[2], "B");
+        let mut kids = ns.children();
+        let (d_id, d_nse) = kids.next().unwrap();
+        assert_eq!(d_id.to_string(), "D");
+        let (g_id, g_nse) = kids.next().unwrap();
+        assert_eq!(g_id.to_string(), "G");
+        assert!(kids.next().is_none());
+        let d_nse_entries = d_nse.entries();
+        assert_eq!(d_nse_entries.len(), 3);
+        assert_ident(d_nse_entries[0], "F");
+        assert_ident(d_nse_entries[1], "I");
+        assert_ident(d_nse_entries[2], "J");
+        let g_nse_entries = g_nse.entries();
+        assert_eq!(g_nse_entries.len(), 2);
+        assert_ident(g_nse_entries[0], "E");
+        assert_ident(g_nse_entries[1], "H");
+        let mut g_kids = g_nse.children();
+        assert!(g_kids.next().is_none());
+        let mut d_kids = d_nse.children();
+        let (k_id, k_nse) = d_kids.next().unwrap();
+        assert_eq!(k_id.to_string(), "K");
+        let k_nse_entries = k_nse.entries();
+        assert_eq!(k_nse_entries.len(), 2);
+        assert_ident(k_nse_entries[0], "L");
+        assert_ident(k_nse_entries[1], "M");
+    }
+
+    fn assert_ident(api: &Api, expected: &str) {
+        if let Api::CxxType(cxx_type) = api {
+            assert_eq!(cxx_type.ident.cxx.ident.to_string(), expected);
+        } else {
+            unreachable!()
+        }
+    }
+
+    fn make_api(ns: Option<&str>, ident: &str) -> Api {
+        let ns = match ns {
+            Some(st) => Namespace::from_str(st),
+            None => Namespace::none(),
+        };
+        let ident = Pair::new(ns, Ident::new(ident, Span::call_site()));
+        Api::CxxType(ExternType {
+            doc: Doc::new(),
+            type_token: Token![type](Span::call_site()),
+            ident,
+            semi_token: Token![;](Span::call_site()),
+            trusted: true,
+        })
+    }
+}
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index b4c6716..5eb203a 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,4 +1,6 @@
 use crate::syntax::qualified::QualifiedName;
+#[cfg(test)]
+use proc_macro2::Span;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
@@ -36,6 +38,16 @@ impl Namespace {
         input.parse::<Option<Token![,]>>()?;
         Ok(ns)
     }
+
+    #[cfg(test)]
+    pub fn from_str(ns: &str) -> Self {
+        Namespace {
+            segments: ns
+                .split("::")
+                .map(|x| Ident::new(x, Span::call_site()))
+                .collect(),
+        }
+    }
 }
 
 impl Parse for Namespace {

From 451ec9f44b96e59606b55fe99a277f373cb7c429 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Oct 30 2020 05:51:30 +0000
Subject: [PATCH 1086/2232] Clippy fixes.


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7e7a9ea..b2d52bb 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -54,7 +54,7 @@ fn gen_namespace_contents(
     let apis = ns_entries.entries();
 
     out.next_section();
-    for api in apis.into_iter() {
+    for api in apis.iter() {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
@@ -64,7 +64,7 @@ fn gen_namespace_contents(
     }
 
     let mut methods_for_type = HashMap::new();
-    for api in apis.into_iter() {
+    for api in apis.iter() {
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type

From 6791c39ec61cfdc02df52139879f34e2dca36dd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 30 2020 21:07:14 +0000
Subject: [PATCH 1087/2232] Merge pull request #382 from adetaylor/namespace-code-review


Namespace code review
---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index c54e784..4aacc8f 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -2,39 +2,127 @@ use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 
-pub(crate) struct NamespaceEntries<'a> {
-    pub(crate) entries: Vec<&'a Api>,
-    pub(crate) children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+pub struct NamespaceEntries<'a> {
+    entries: Vec<&'a Api>,
+    children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
 
-pub(crate) fn sort_by_namespace(apis: &[Api]) -> NamespaceEntries {
-    let api_refs = apis.iter().collect::<Vec<_>>();
-    sort_by_inner_namespace(api_refs, 0)
-}
+impl<'a> NamespaceEntries<'a> {
+    pub fn new(apis: &'a [Api]) -> Self {
+        let api_refs = apis.iter().collect::<Vec<_>>();
+        Self::sort_by_inner_namespace(api_refs, 0)
+    }
+
+    pub fn entries(&self) -> &[&'a Api] {
+        &self.entries
+    }
 
-fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
-    let mut root = NamespaceEntries {
-        entries: Vec::new(),
-        children: BTreeMap::new(),
-    };
-
-    let mut kids_by_child_ns = BTreeMap::new();
-    for api in apis {
-        if let Some(ns) = api.get_namespace() {
-            let first_ns_elem = ns.iter().nth(depth);
-            if let Some(first_ns_elem) = first_ns_elem {
-                let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
-                list.push(api);
-                continue;
+    pub fn children(&self) -> impl Iterator<Item = (&&Ident, &NamespaceEntries)> {
+        self.children.iter()
+    }
+
+    fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
+        let mut root = NamespaceEntries {
+            entries: Vec::new(),
+            children: BTreeMap::new(),
+        };
+
+        let mut kids_by_child_ns = BTreeMap::new();
+        for api in apis {
+            if let Some(ns) = api.get_namespace() {
+                let first_ns_elem = ns.iter().nth(depth);
+                if let Some(first_ns_elem) = first_ns_elem {
+                    let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
+                    list.push(api);
+                    continue;
+                }
             }
+            root.entries.push(api);
+        }
+
+        for (k, v) in kids_by_child_ns.into_iter() {
+            root.children
+                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
         }
-        root.entries.push(api);
+
+        root
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::NamespaceEntries;
+    use crate::syntax::namespace::Namespace;
+    use crate::syntax::{Api, Doc, ExternType, Pair};
+    use proc_macro2::{Ident, Span};
+    use syn::Token;
+
+    #[test]
+    fn test_ns_entries_sort() {
+        let entries = vec![
+            make_api(None, "C"),
+            make_api(None, "A"),
+            make_api(Some("G"), "E"),
+            make_api(Some("D"), "F"),
+            make_api(Some("G"), "H"),
+            make_api(Some("D::K"), "L"),
+            make_api(Some("D::K"), "M"),
+            make_api(None, "B"),
+            make_api(Some("D"), "I"),
+            make_api(Some("D"), "J"),
+        ];
+        let ns = NamespaceEntries::new(&entries);
+        let root_entries = ns.entries();
+        assert_eq!(root_entries.len(), 3);
+        assert_ident(root_entries[0], "C");
+        assert_ident(root_entries[1], "A");
+        assert_ident(root_entries[2], "B");
+        let mut kids = ns.children();
+        let (d_id, d_nse) = kids.next().unwrap();
+        assert_eq!(d_id.to_string(), "D");
+        let (g_id, g_nse) = kids.next().unwrap();
+        assert_eq!(g_id.to_string(), "G");
+        assert!(kids.next().is_none());
+        let d_nse_entries = d_nse.entries();
+        assert_eq!(d_nse_entries.len(), 3);
+        assert_ident(d_nse_entries[0], "F");
+        assert_ident(d_nse_entries[1], "I");
+        assert_ident(d_nse_entries[2], "J");
+        let g_nse_entries = g_nse.entries();
+        assert_eq!(g_nse_entries.len(), 2);
+        assert_ident(g_nse_entries[0], "E");
+        assert_ident(g_nse_entries[1], "H");
+        let mut g_kids = g_nse.children();
+        assert!(g_kids.next().is_none());
+        let mut d_kids = d_nse.children();
+        let (k_id, k_nse) = d_kids.next().unwrap();
+        assert_eq!(k_id.to_string(), "K");
+        let k_nse_entries = k_nse.entries();
+        assert_eq!(k_nse_entries.len(), 2);
+        assert_ident(k_nse_entries[0], "L");
+        assert_ident(k_nse_entries[1], "M");
     }
 
-    for (k, v) in kids_by_child_ns.into_iter() {
-        root.children
-            .insert(k, sort_by_inner_namespace(v, depth + 1));
+    fn assert_ident(api: &Api, expected: &str) {
+        if let Api::CxxType(cxx_type) = api {
+            assert_eq!(cxx_type.ident.cxx.ident.to_string(), expected);
+        } else {
+            unreachable!()
+        }
     }
 
-    root
+    fn make_api(ns: Option<&str>, ident: &str) -> Api {
+        let ns = match ns {
+            Some(st) => Namespace::from_str(st),
+            None => Namespace::none(),
+        };
+        let ident = Pair::new(ns, Ident::new(ident, Span::call_site()));
+        Api::CxxType(ExternType {
+            doc: Doc::new(),
+            type_token: Token![type](Span::call_site()),
+            ident,
+            semi_token: Token![;](Span::call_site()),
+            trusted: true,
+        })
+    }
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 967d4ff..b2d52bb 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,4 @@
-use crate::gen::namespace_organizer::{sort_by_namespace, NamespaceEntries};
+use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -30,7 +30,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> OutFi
 
     out.next_section();
 
-    let apis_by_namespace = sort_by_namespace(apis);
+    let apis_by_namespace = NamespaceEntries::new(apis);
 
     gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
 
@@ -51,10 +51,10 @@ fn gen_namespace_contents(
     header: bool,
     out: &mut OutFile,
 ) {
-    let apis = &ns_entries.entries;
+    let apis = ns_entries.entries();
 
     out.next_section();
-    for api in apis {
+    for api in apis.iter() {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
@@ -64,7 +64,7 @@ fn gen_namespace_contents(
     }
 
     let mut methods_for_type = HashMap::new();
-    for api in apis {
+    for api in apis.iter() {
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
@@ -134,7 +134,7 @@ fn gen_namespace_contents(
 
     out.next_section();
 
-    for (child_ns, child_ns_entries) in &ns_entries.children {
+    for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
         gen_namespace_contents(&child_ns_entries, types, opt, header, out);
         writeln!(out, "}} // namespace {}", child_ns);
diff --git a/syntax/check.rs b/syntax/check.rs
index 08e0dfa..ba488e1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -211,9 +211,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
 
     if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
         let what = match reason {
-            TrivialReason::StructField(strct) => {
-                format!("a field of `{}`", strct.ident.cxx.to_fully_qualified())
-            }
+            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident.rust),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
         };
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 424ad9d..f4c5b05 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -300,14 +300,22 @@ impl Borrow<Type> for &Impl {
 
 impl Pair {
     /// Use this constructor when the item can't have a different
-    /// name in Rust and C++. For cases where #[rust_name] and similar
-    /// attributes can be used, construct the object by hand.
+    /// name in Rust and C++.
     pub fn new(ns: Namespace, ident: Ident) -> Self {
         Self {
             rust: ident.clone(),
             cxx: CppName::new(ns, ident),
         }
     }
+
+    /// 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(ns: Namespace, cxx_ident: Ident, rust_ident: Ident) -> Self {
+        Self {
+            rust: rust_ident,
+            cxx: CppName::new(ns, cxx_ident),
+        }
+    }
 }
 
 impl ResolvableName {
@@ -315,10 +323,6 @@ impl ResolvableName {
         Self { rust: ident }
     }
 
-    pub fn from_pair(pair: Pair) -> Self {
-        Self { rust: pair.rust }
-    }
-
     pub fn make_self(span: Span) -> Self {
         Self {
             rust: Token![Self](span).into(),
@@ -357,9 +361,7 @@ impl CppName {
         Self { ns, ident }
     }
 
-    fn iter_all_segments(
-        &self,
-    ) -> std::iter::Chain<std::slice::Iter<Ident>, std::iter::Once<&Ident>> {
+    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
         self.ns.iter().chain(std::iter::once(&self.ident))
     }
 
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index b4c6716..5eb203a 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,4 +1,6 @@
 use crate::syntax::qualified::QualifiedName;
+#[cfg(test)]
+use proc_macro2::Span;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
@@ -36,6 +38,16 @@ impl Namespace {
         input.parse::<Option<Token![,]>>()?;
         Ok(ns)
     }
+
+    #[cfg(test)]
+    pub fn from_str(ns: &str) -> Self {
+        Namespace {
+            segments: ns
+                .split("::")
+                .map(|x| Ident::new(x, Span::call_site()))
+                .collect(),
+        }
+    }
 }
 
 impl Parse for Namespace {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 7a56ab8..1927554 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, CppName, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
+    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
@@ -245,7 +245,7 @@ fn parse_foreign_mod(
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
                     if receiver.ty.is_self() {
-                        receiver.ty = ResolvableName::from_pair(single_type.clone());
+                        receiver.ty = ResolvableName::new(single_type.rust.clone());
                     }
                 }
             }
@@ -398,10 +398,11 @@ fn parse_extern_fn(
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let ident = Pair {
-        cxx: CppName::new(ns, cxx_name.unwrap_or(foreign_fn.sig.ident.clone())),
-        rust: rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
-    };
+    let ident = Pair::new_from_differing_names(
+        ns,
+        cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
+        rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
+    );
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
     let api_function = match lang {
diff --git a/tests/BUCK b/tests/BUCK
index f51be09..5bbe500 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -15,7 +15,6 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
-        "ffi/class_in_ns.rs",
     ],
     crate = "cxx_test_suite",
     deps = [
@@ -31,7 +30,6 @@ cxx_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
-        ":class_in_ns/source",
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
@@ -54,8 +52,3 @@ rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
-
-rust_cxx_bridge(
-    name = "class_in_ns",
-    src = "ffi/class_in_ns.rs",
-)
diff --git a/tests/BUILD b/tests/BUILD
index a400f47..57ffab9 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -18,7 +18,6 @@ rust_library(
         "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
-        "ffi/class_in_ns.rs",
     ],
     deps = [
         ":impl",
@@ -33,7 +32,6 @@ cc_library(
         ":bridge/source",
         ":extra/source",
         ":module/source",
-        ":class_in_ns/source",
     ],
     hdrs = ["ffi/tests.h"],
     deps = [
@@ -59,9 +57,3 @@ rust_cxx_bridge(
     src = "ffi/module.rs",
     deps = [":impl"],
 )
-
-rust_cxx_bridge(
-    name = "class_in_ns",
-    src = "ffi/class_in_ns.rs",
-    deps = [":impl"],
-)
\ No newline at end of file
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 9bdb711..4b2cbdf 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs", "class_in_ns.rs"];
+    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/class_in_ns.rs b/tests/ffi/class_in_ns.rs
deleted file mode 100644
index a03da78..0000000
--- a/tests/ffi/class_in_ns.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// To test receivers on a type in a namespace outide
-// the default. cxx::bridge blocks can only have a single
-// receiver type, and there can only be one such block per,
-// which is why this is outside.
-
-#[rustfmt::skip]
-#[cxx::bridge(namespace = tests)]
-pub mod ffi3 {
-
-    extern "C" {
-        include!("tests/ffi/tests.h");
-
-        #[namespace = "I"]
-        type I;
-
-        fn get(self: &I) -> u32;
-
-        #[namespace = "I"]
-        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
-    }
-}
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 58700a2..a11970d 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -51,5 +51,13 @@ pub mod ffi2 {
         fn ns_c_take_trivial(d: D);
         #[namespace = "other"]
         fn ns_c_return_trivial() -> D;
+
+        #[namespace = "I"]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace = "I"]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 17146ce..fee5bcb 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -4,7 +4,6 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
-pub mod class_in_ns;
 pub mod extra;
 pub mod module;
 
diff --git a/tests/test.rs b/tests/test.rs
index 20b23ac..b651feb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,4 +1,3 @@
-use cxx_test_suite::class_in_ns::ffi3;
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;
@@ -196,7 +195,7 @@ fn test_c_method_calls() {
 
 #[test]
 fn test_c_ns_method_calls() {
-    let unique_ptr = ffi3::ns_c_return_unique_ptr_ns();
+    let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
 
     let old_value = unique_ptr.get();
     assert_eq!(1000, old_value);
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index a860f3d..0a56dd4 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,7 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `::S`
+error: needs a cxx::ExternType impl in order to be used as a field of `S`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;

From 8d32366682c189344565f90f9e8742e167f4b4f9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 03:29:49 +0000
Subject: [PATCH 1088/2232] Match std::string's behavior on (nullptr, 0) construction


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 715e0ce..cbda8b9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -57,12 +57,23 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge05$string$drop(this); }
 
-String::String(const std::string &s) : String(s.data(), s.length()) {}
+String::String(const std::string &s) {
+  if (!cxxbridge05$string$from(this, s.data(), s.length())) {
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
+  }
+}
 
-String::String(const char *s) : String(s, std::strlen(s)) {}
+String::String(const char *s) {
+  if (!cxxbridge05$string$from(this, s, std::strlen(s))) {
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
+  }
+}
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge05$string$from(this, s, len)) {
+  if (!cxxbridge05$string$from(
+          this,
+          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+          len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
@@ -104,15 +115,26 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
+Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
+  }
+}
 
-Str::Str(const char *s) : Str(s, std::strlen(s)) {}
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
+  }
+}
 
-Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
+Str::Str(const char *s, size_t len)
+    : repr(
+          Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+               len}) {
   if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }

From 9167590318a1c02c58b8cde13e92f02a6f02d971 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 03:51:26 +0000
Subject: [PATCH 1089/2232] Merge pull request #383 from dtolnay/nullempty


Match std::string's behavior on (nullptr, 0) construction
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 715e0ce..cbda8b9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -57,12 +57,23 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge05$string$drop(this); }
 
-String::String(const std::string &s) : String(s.data(), s.length()) {}
+String::String(const std::string &s) {
+  if (!cxxbridge05$string$from(this, s.data(), s.length())) {
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
+  }
+}
 
-String::String(const char *s) : String(s, std::strlen(s)) {}
+String::String(const char *s) {
+  if (!cxxbridge05$string$from(this, s, std::strlen(s))) {
+    panic<std::invalid_argument>("data for rust::String is not utf-8");
+  }
+}
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge05$string$from(this, s, len)) {
+  if (!cxxbridge05$string$from(
+          this,
+          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+          len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
@@ -104,15 +115,26 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}
+Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : Str(s.data(), s.length()) {}
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
+  }
+}
 
-Str::Str(const char *s) : Str(s, std::strlen(s)) {}
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+    panic<std::invalid_argument>("data for rust::Str is not utf-8");
+  }
+}
 
-Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
+Str::Str(const char *s, size_t len)
+    : repr(
+          Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+               len}) {
   if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }

From 032d8531611604af1fa246c2e327aff1ac2cc870 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 03:51:51 +0000
Subject: [PATCH 1090/2232] Reduce duplicated checks in string construction


---

diff --git a/src/cxx.cc b/src/cxx.cc
index cbda8b9..05dc15a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -57,25 +57,20 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge05$string$drop(this); }
 
-String::String(const std::string &s) {
-  if (!cxxbridge05$string$from(this, s.data(), s.length())) {
+static void initString(String *self, const char *s, size_t len) {
+  if (!cxxbridge05$string$from(self, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
-String::String(const char *s) {
-  if (!cxxbridge05$string$from(this, s, std::strlen(s))) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
-}
+String::String(const std::string &s) { initString(this, s.data(), s.length()); }
+
+String::String(const char *s) { initString(this, s, std::strlen(s)); }
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge05$string$from(
-          this,
-          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
-          len)) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
+  initString(this,
+             s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+             len);
 }
 
 String &String::operator=(const String &other) noexcept {
@@ -119,25 +114,23 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+static void initStr(Str::Repr repr) {
+  if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  initStr(this->repr);
 }
 
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) { initStr(this->repr); }
+
 Str::Str(const char *s, size_t len)
     : repr(
           Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
                len}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
+  initStr(this->repr);
 }
 
 Str &Str::operator=(Str other) noexcept {

From 6d431e8e24c75cd2a688f959f153ed782b4f85f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 03:58:36 +0000
Subject: [PATCH 1091/2232] Merge pull request #384 from dtolnay/string


Reduce duplicated checks in string construction
---

diff --git a/src/cxx.cc b/src/cxx.cc
index cbda8b9..05dc15a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -57,25 +57,20 @@ String::String(String &&other) noexcept {
 
 String::~String() noexcept { cxxbridge05$string$drop(this); }
 
-String::String(const std::string &s) {
-  if (!cxxbridge05$string$from(this, s.data(), s.length())) {
+static void initString(String *self, const char *s, size_t len) {
+  if (!cxxbridge05$string$from(self, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
 
-String::String(const char *s) {
-  if (!cxxbridge05$string$from(this, s, std::strlen(s))) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
-}
+String::String(const std::string &s) { initString(this, s.data(), s.length()); }
+
+String::String(const char *s) { initString(this, s, std::strlen(s)); }
 
 String::String(const char *s, size_t len) {
-  if (!cxxbridge05$string$from(
-          this,
-          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
-          len)) {
-    panic<std::invalid_argument>("data for rust::String is not utf-8");
-  }
+  initString(this,
+             s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+             len);
 }
 
 String &String::operator=(const String &other) noexcept {
@@ -119,25 +114,23 @@ Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
 Str::Str(const Str &) noexcept = default;
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
+static void initStr(Str::Repr repr) {
+  if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
+Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
+  initStr(this->repr);
 }
 
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) { initStr(this->repr); }
+
 Str::Str(const char *s, size_t len)
     : repr(
           Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
                len}) {
-  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
-    panic<std::invalid_argument>("data for rust::Str is not utf-8");
-  }
+  initStr(this->repr);
 }
 
 Str &Str::operator=(Str other) noexcept {

From 54b13222e20edfe1977864b9deb947c68a9fc9f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 03:58:44 +0000
Subject: [PATCH 1092/2232] Add asserts to protect string construction from nullptr when building with assertions


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 05dc15a..a423df6 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,4 +1,5 @@
 #include "../include/cxx.h"
+#include <cassert>
 #include <cstring>
 #include <exception>
 #include <iostream>
@@ -65,9 +66,13 @@ static void initString(String *self, const char *s, size_t len) {
 
 String::String(const std::string &s) { initString(this, s.data(), s.length()); }
 
-String::String(const char *s) { initString(this, s, std::strlen(s)); }
+String::String(const char *s) {
+  assert(s != nullptr);
+  initString(this, s, std::strlen(s));
+}
 
 String::String(const char *s, size_t len) {
+  assert(s != nullptr || len == 0);
   initString(this,
              s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
              len);
@@ -124,12 +129,16 @@ Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   initStr(this->repr);
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) { initStr(this->repr); }
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+  assert(s != nullptr);
+  initStr(this->repr);
+}
 
 Str::Str(const char *s, size_t len)
     : repr(
           Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
                len}) {
+  assert(s != nullptr || len == 0);
   initStr(this->repr);
 }
 

From 2e5c529055a16cc5a34189d90c8b2ddc95a83cfc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:08:17 +0000
Subject: [PATCH 1093/2232] Merge pull request #385 from dtolnay/string


Add asserts to protect string construction from nullptr when building with assertions
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 05dc15a..a423df6 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,4 +1,5 @@
 #include "../include/cxx.h"
+#include <cassert>
 #include <cstring>
 #include <exception>
 #include <iostream>
@@ -65,9 +66,13 @@ static void initString(String *self, const char *s, size_t len) {
 
 String::String(const std::string &s) { initString(this, s.data(), s.length()); }
 
-String::String(const char *s) { initString(this, s, std::strlen(s)); }
+String::String(const char *s) {
+  assert(s != nullptr);
+  initString(this, s, std::strlen(s));
+}
 
 String::String(const char *s, size_t len) {
+  assert(s != nullptr || len == 0);
   initString(this,
              s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
              len);
@@ -124,12 +129,16 @@ Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
   initStr(this->repr);
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) { initStr(this->repr); }
+Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+  assert(s != nullptr);
+  initStr(this->repr);
+}
 
 Str::Str(const char *s, size_t len)
     : repr(
           Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
                len}) {
+  assert(s != nullptr || len == 0);
   initStr(this->repr);
 }
 

From bf23e3e185f1ea93991bd6f366e60e9f389b2f74 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:12:50 +0000
Subject: [PATCH 1094/2232] Format PR 370 with clang-format


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 05bf5fb..4abc456 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -2,9 +2,9 @@
 #include "tests/ffi/lib.rs.h"
 #include <cstring>
 #include <iterator>
+#include <memory>
 #include <numeric>
 #include <stdexcept>
-#include <memory>
 #include <string>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
@@ -63,7 +63,9 @@ const size_t &c_return_ref(const Shared &shared) { return shared.z; }
 
 const size_t &c_return_ns_ref(const ::A::AShared &shared) { return shared.z; }
 
-const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { return shared.z; }
+const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) {
+  return shared.z;
+}
 
 size_t &c_return_mut(Shared &shared) { return shared.z; }
 
@@ -471,7 +473,7 @@ void c_take_trivial_ptr(std::unique_ptr<D> d) {
   }
 }
 
-void c_take_trivial_ref(const D& d) {
+void c_take_trivial_ref(const D &d) {
   if (d.d == 30) {
     cxx_test_suite_set_correct();
   }
@@ -483,14 +485,13 @@ void c_take_trivial(D d) {
   }
 }
 
-
 void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g) {
   if (g->g == 30) {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_trivial_ns_ref(const ::G::G& g) {
+void c_take_trivial_ns_ref(const ::G::G &g) {
   if (g.g == 30) {
     cxx_test_suite_set_correct();
   }
@@ -514,13 +515,13 @@ void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f) {
   }
 }
 
-void c_take_opaque_ref(const E& e) {
+void c_take_opaque_ref(const E &e) {
   if (e.e == 40 && e.e_str == "hello") {
     cxx_test_suite_set_correct();
   }
 }
 
-void c_take_opaque_ns_ref(const ::F::F& f) {
+void c_take_opaque_ns_ref(const ::F::F &f) {
   if (f.f == 40 && f.f_str == "hello") {
     cxx_test_suite_set_correct();
   }
@@ -629,32 +630,29 @@ extern "C" const char *cxx_run_test() noexcept {
 } // namespace tests
 
 namespace other {
-
-  void ns_c_take_trivial(::tests::D d) {
-    if (d.d == 30) {
-      cxx_test_suite_set_correct();
-    }
+void ns_c_take_trivial(::tests::D d) {
+  if (d.d == 30) {
+    cxx_test_suite_set_correct();
   }
+}
 
-  ::tests::D ns_c_return_trivial() {
-    ::tests::D d;
-    d.d = 30;
-    return d;
-  }
+::tests::D ns_c_return_trivial() {
+  ::tests::D d;
+  d.d = 30;
+  return d;
+}
 
-  void ns_c_take_ns_shared(::A::AShared shared) {
-    if (shared.z == 2020) {
-      cxx_test_suite_set_correct();
-    }
+void ns_c_take_ns_shared(::A::AShared shared) {
+  if (shared.z == 2020) {
+    cxx_test_suite_set_correct();
   }
+}
 } // namespace other
 
 namespace I {
-  uint32_t I::get() const {
-    return a;
-  }
+uint32_t I::get() const { return a; }
 
-  std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
-    return std::unique_ptr<I>(new I());
-  }
+std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
+  return std::unique_ptr<I>(new I());
+}
 } // namespace I
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3835660..6b1ec1e 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -4,33 +4,33 @@
 #include <string>
 
 namespace A {
-  struct AShared;
-  enum class AEnum : uint16_t;
-  namespace B {
-    struct ABShared;
-    enum class ABEnum : uint16_t;
-  } // namespace B
+struct AShared;
+enum class AEnum : uint16_t;
+namespace B {
+struct ABShared;
+enum class ABEnum : uint16_t;
+} // namespace B
 } // namespace A
 
 namespace F {
-  struct F {
-    uint64_t f;
-    std::string f_str;
-  };
-}
+struct F {
+  uint64_t f;
+  std::string f_str;
+};
+} // namespace F
 
 namespace G {
-  struct G {
-    uint64_t g;
-  };
-}
+struct G {
+  uint64_t g;
+};
+} // namespace G
 
 namespace H {
-  class H {
-  public:
-    std::string h;
-  };
-}
+class H {
+public:
+  std::string h;
+};
+} // namespace H
 
 namespace tests {
 
@@ -156,16 +156,16 @@ rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
 void c_take_trivial_ptr(std::unique_ptr<D> d);
-void c_take_trivial_ref(const D& d);
+void c_take_trivial_ref(const D &d);
 void c_take_trivial(D d);
 
 void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g);
-void c_take_trivial_ns_ref(const ::G::G& g);
+void c_take_trivial_ns_ref(const ::G::G &g);
 void c_take_trivial_ns(::G::G g);
 void c_take_opaque_ptr(std::unique_ptr<E> e);
 void c_take_opaque_ns_ptr(std::unique_ptr<::F::F> f);
-void c_take_opaque_ref(const E& e);
-void c_take_opaque_ns_ref(const ::F::F& f);
+void c_take_opaque_ref(const E &e);
+void c_take_opaque_ns_ref(const ::F::F &f);
 std::unique_ptr<D> c_return_trivial_ptr();
 D c_return_trivial();
 std::unique_ptr<::G::G> c_return_trivial_ns_ptr();
@@ -179,19 +179,20 @@ rust::String cOverloadedFunction(rust::Str x);
 } // namespace tests
 
 namespace other {
-  void ns_c_take_trivial(::tests::D d);
-  ::tests::D ns_c_return_trivial();
-  void ns_c_take_ns_shared(::A::AShared shared);
+void ns_c_take_trivial(::tests::D d);
+::tests::D ns_c_return_trivial();
+void ns_c_take_ns_shared(::A::AShared shared);
 } // namespace other
 
 namespace I {
-  class I {
-  private:
-    uint32_t a;
-  public:
-    I() : a(1000) {}
-    uint32_t get() const;
-  };
-
-  std::unique_ptr<I> ns_c_return_unique_ptr_ns();
+class I {
+private:
+  uint32_t a;
+
+public:
+  I() : a(1000) {}
+  uint32_t get() const;
+};
+
+std::unique_ptr<I> ns_c_return_unique_ptr_ns();
 } // namespace I

From 50de2c4813985d3498a6af72046ac3f74fd773d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:16:05 +0000
Subject: [PATCH 1095/2232] Remove various Ident type aliases


I don't see these being particularly helpful to maintaining correctness.
Where needed, we should clarify the meaning of a field with a comment
rather than writing its type as an alias.

---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 6498d74..d770d49 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -35,19 +35,6 @@ pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
-/// A Rust identifier will forver == a proc_macro2::Ident,
-/// but for completeness here's a type alias.
-pub type RsIdent = Ident;
-
-/// At the moment, a Rust name is simply a proc_macro2::Ident.
-/// In the future, it may become namespaced based on a mod path.
-pub type RsName = RsIdent;
-
-/// At the moment, a C++ identifier is also a proc_macro2::Ident.
-/// In the future, we may wish to make a newtype wrapper here
-/// to avoid confusion between C++ and Rust identifiers.
-pub type CppIdent = Ident;
-
 #[derive(Clone)]
 /// A C++ identifier in a particular namespace.
 /// It is intentional that this does not impl Display,
@@ -55,7 +42,7 @@ pub type CppIdent = Ident;
 /// it as a qualified name or as an unqualfiied name.
 pub struct CppName {
     pub ns: Namespace,
-    pub ident: CppIdent,
+    pub ident: Ident,
 }
 
 pub enum Api {
@@ -117,7 +104,7 @@ pub struct Enum {
 #[derive(Clone)]
 pub struct Pair {
     pub cxx: CppName,
-    pub rust: RsName,
+    pub rust: Ident,
 }
 
 pub struct ExternFn {
@@ -156,7 +143,7 @@ pub struct Signature {
 
 #[derive(Eq, PartialEq, Hash)]
 pub struct Var {
-    pub ident: RsIdent, // fields and variables are not namespaced
+    pub ident: Ident,
     pub ty: Type,
 }
 
@@ -170,7 +157,7 @@ pub struct Receiver {
 }
 
 pub struct Variant {
-    pub ident: RsIdent,
+    pub ident: Ident,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
 }
@@ -218,5 +205,5 @@ pub enum Lang {
 /// before it can be printed in C++.
 #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
 pub struct ResolvableName {
-    pub rust: RsName,
+    pub rust: Ident,
 }

From 9071c264e2d7864afbb5ac7498bd6d6502c7dfd4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:18:54 +0000
Subject: [PATCH 1096/2232] Collect name-related structs to the bottom of syntax tree definition


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index d770d49..12d8178 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -35,16 +35,6 @@ pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
-#[derive(Clone)]
-/// 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 unqualfiied name.
-pub struct CppName {
-    pub ns: Namespace,
-    pub ident: Ident,
-}
-
 pub enum Api {
     Include(Include),
     Struct(Struct),
@@ -99,14 +89,6 @@ pub struct Enum {
     pub repr: Atom,
 }
 
-/// A type with a defined Rust name and a fully resolved,
-/// qualified, namespaced, C++ name.
-#[derive(Clone)]
-pub struct Pair {
-    pub cxx: CppName,
-    pub rust: Ident,
-}
-
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
@@ -201,6 +183,24 @@ pub enum Lang {
     Rust,
 }
 
+/// A type with a defined Rust name and a fully resolved,
+/// qualified, namespaced, C++ name.
+#[derive(Clone)]
+pub struct Pair {
+    pub cxx: CppName,
+    pub rust: Ident,
+}
+
+#[derive(Clone)]
+/// 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 unqualfiied name.
+pub struct CppName {
+    pub ns: Namespace,
+    pub ident: Ident,
+}
+
 /// Wrapper for a type which needs to be resolved
 /// before it can be printed in C++.
 #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]

From abff2d5ed04414d733c2ba4dfcd67b0c022dba5c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:20:07 +0000
Subject: [PATCH 1097/2232] Rewrap name struct comments to 80 columns


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 12d8178..4f9815d 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -183,26 +183,25 @@ pub enum Lang {
     Rust,
 }
 
-/// A type with a defined Rust name and a fully resolved,
-/// qualified, namespaced, C++ name.
+// A type with a defined Rust name and a fully resolved, qualified, namespaced,
+// 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 unqualfiied name.
 #[derive(Clone)]
-/// 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 unqualfiied name.
 pub struct CppName {
     pub ns: Namespace,
     pub ident: Ident,
 }
 
-/// Wrapper for a type which needs to be resolved
-/// before it can be printed in C++.
+// Wrapper for a type which needs to be resolved before it can be printed in
+// C++.
 #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
 pub struct ResolvableName {
     pub rust: Ident,

From be7e30e0c9ed719c379952753b98c009412ee39f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:21:23 +0000
Subject: [PATCH 1098/2232] Clarify name struct comments


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4f9815d..b1aaa13 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -183,8 +183,8 @@ pub enum Lang {
     Rust,
 }
 
-// A type with a defined Rust name and a fully resolved, qualified, namespaced,
-// C++ name.
+// An association of a defined Rust name with a fully resolved, namespace
+// qualified C++ name.
 #[derive(Clone)]
 pub struct Pair {
     pub cxx: CppName,
@@ -193,7 +193,7 @@ pub struct Pair {
 
 // 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 unqualfiied name.
+// to output it as a qualified name or as an unqualfied name.
 #[derive(Clone)]
 pub struct CppName {
     pub ns: Namespace,

From 598154250c402828d9ec26bf388fefcc34884954 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:24:05 +0000
Subject: [PATCH 1099/2232] Remove unneeded derives on ResolvableName


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index b1aaa13..8d3b8a2 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -202,7 +202,7 @@ pub struct CppName {
 
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
-#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
+#[derive(Clone, PartialEq, Hash)]
 pub struct ResolvableName {
     pub rust: Ident,
 }

From b560a0fabfbafd3a222a140bd76df13b1daf270c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:40:03 +0000
Subject: [PATCH 1100/2232] Make type information accessible through OutFile


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 8a6bd86..94a54e4 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,9 +1,11 @@
 use crate::gen::include::Includes;
+use crate::syntax::Types;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
-pub(crate) struct OutFile {
+pub(crate) struct OutFile<'a> {
     pub header: bool,
+    pub types: &'a Types<'a>,
     pub include: Includes,
     pub front: Content,
     content: RefCell<Content>,
@@ -15,10 +17,11 @@ pub struct Content {
     blocks_pending: Vec<&'static str>,
 }
 
-impl OutFile {
-    pub fn new(header: bool) -> Self {
+impl<'a> OutFile<'a> {
+    pub fn new(header: bool, types: &'a Types) -> Self {
         OutFile {
             header,
+            types,
             include: Includes::new(),
             front: Content::new(),
             content: RefCell::new(Content::new()),
diff --git a/gen/src/write.rs b/gen/src/write.rs
index b2d52bb..3be5e35 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -10,8 +10,8 @@ use crate::syntax::{
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
-pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> OutFile {
-    let mut out_file = OutFile::new(header);
+pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -> OutFile<'a> {
+    let mut out_file = OutFile::new(header, types);
     let out = &mut out_file;
 
     if header {

From a7c2ea10f160bde07159d2c6b6b98cec968baf13 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:40:14 +0000
Subject: [PATCH 1101/2232] Avoid passing Types around everywhere


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3be5e35..f259222 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -25,8 +25,8 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         }
     }
 
-    write_includes(out, types);
-    write_include_cxxbridge(out, apis, types);
+    write_includes(out);
+    write_include_cxxbridge(out, apis);
 
     out.next_section();
 
@@ -36,7 +36,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     if !header {
         out.next_section();
-        write_generic_instantiations(out, types);
+        write_generic_instantiations(out);
     }
 
     write!(out.front, "{}", out.include);
@@ -80,7 +80,7 @@ fn gen_namespace_contents(
             Api::Struct(strct) => {
                 out.next_section();
                 if !types.cxx.contains(&strct.ident.rust) {
-                    write_struct(out, strct, types);
+                    write_struct(out, strct);
                 }
             }
             Api::Enum(enm) => {
@@ -94,7 +94,7 @@ fn gen_namespace_contents(
             Api::RustType(ety) => {
                 if let Some(methods) = methods_for_type.get(&ety.ident.rust) {
                     out.next_section();
-                    write_struct_with_methods(out, ety, methods, types);
+                    write_struct_with_methods(out, ety, methods);
                 }
             }
             _ => {}
@@ -114,13 +114,13 @@ fn gen_namespace_contents(
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
-            let (efn, write): (_, fn(_, _, _, _)) = match api {
+            let (efn, write): (_, fn(_, _, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
                 Api::RustFunction(efn) => (efn, write_rust_function_decl),
                 _ => continue,
             };
             out.next_section();
-            write(out, efn, types, &opt.cxx_impl_annotations);
+            write(out, efn, &opt.cxx_impl_annotations);
         }
         out.end_block("extern \"C\"");
     }
@@ -128,7 +128,7 @@ fn gen_namespace_contents(
     for api in apis {
         if let Api::RustFunction(efn) = api {
             out.next_section();
-            write_rust_function_shim(out, efn, types);
+            write_rust_function_shim(out, efn);
         }
     }
 
@@ -141,8 +141,8 @@ fn gen_namespace_contents(
     }
 }
 
-fn write_includes(out: &mut OutFile, types: &Types) {
-    for ty in types {
+fn write_includes(out: &mut OutFile) {
+    for ty in out.types {
         match ty {
             Type::Ident(ident) => match Atom::from(&ident.rust) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
@@ -160,7 +160,7 @@ fn write_includes(out: &mut OutFile, types: &Types) {
     }
 }
 
-fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
+fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     let mut needs_panic = false;
     let mut needs_rust_string = false;
     let mut needs_rust_str = false;
@@ -170,7 +170,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     let mut needs_rust_fn = false;
     let mut needs_rust_isize = false;
     let mut needs_unsafe_bitcopy = false;
-    for ty in types {
+    for ty in out.types {
         match ty {
             Type::RustBox(_) => {
                 out.include.new = true;
@@ -240,13 +240,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
                     needs_maybe_uninit = true;
                 }
                 for arg in &efn.args {
-                    if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+                    if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
                         needs_manually_drop = true;
                         break;
                     }
                 }
                 if let Some(ret) = &efn.ret {
-                    if types.needs_indirect_abi(ret) {
+                    if out.types.needs_indirect_abi(ret) {
                         needs_maybe_uninit = true;
                     }
                 }
@@ -343,7 +343,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
     out.end_block("namespace rust");
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct, types: &Types) {
+fn write_struct(out: &mut OutFile, strct: &Struct) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -353,7 +353,7 @@ fn write_struct(out: &mut OutFile, strct: &Struct, types: &Types) {
     writeln!(out, "struct {} final {{", strct.ident.cxx.ident);
     for field in &strct.fields {
         write!(out, "  ");
-        write_type_space(out, &field.ty, types);
+        write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
     writeln!(out, "}};");
@@ -373,12 +373,7 @@ fn write_struct_using(out: &mut OutFile, ident: &CppName) {
     );
 }
 
-fn write_struct_with_methods(
-    out: &mut OutFile,
-    ety: &ExternType,
-    methods: &[&ExternFn],
-    types: &Types,
-) {
+fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -396,7 +391,7 @@ fn write_struct_with_methods(
         write!(out, "  ");
         let sig = &method.sig;
         let local_name = method.ident.cxx.ident.to_string();
-        write_rust_function_shim_decl(out, &local_name, sig, false, types);
+        write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
     writeln!(out, "}};");
@@ -500,12 +495,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
     }
 }
 
-fn write_cxx_function_shim(
-    out: &mut OutFile,
-    efn: &ExternFn,
-    types: &Types,
-    impl_annotations: &Option<String>,
-) {
+fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: &Option<String>) {
     if !out.header {
         if let Some(annotation) = impl_annotations {
             write!(out, "{} ", annotation);
@@ -514,9 +504,9 @@ fn write_cxx_function_shim(
     if efn.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type_space(out, &efn.ret, types);
+        write_extern_return_type_space(out, &efn.ret);
     }
-    let mangled = mangle::extern_fn(efn, types);
+    let mangled = mangle::extern_fn(efn, out.types);
     write!(out, "{}(", mangled);
     if let Some(receiver) = &efn.receiver {
         if receiver.mutability.is_none() {
@@ -525,7 +515,7 @@ fn write_cxx_function_shim(
         write!(
             out,
             "{} &self",
-            types.resolve(&receiver.ty).to_fully_qualified()
+            out.types.resolve(&receiver.ty).to_fully_qualified()
         );
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -537,25 +527,25 @@ fn write_cxx_function_shim(
         } else if let Type::RustVec(_) = arg.ty {
             write!(out, "const ");
         }
-        write_extern_arg(out, arg, types);
+        write_extern_arg(out, arg);
     }
-    let indirect_return = indirect_return(efn, types);
+    let indirect_return = indirect_return(efn, out.types);
     if indirect_return {
         if !efn.args.is_empty() || efn.receiver.is_some() {
             write!(out, ", ");
         }
-        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap(), types);
+        write_indirect_return_type_space(out, efn.ret.as_ref().unwrap());
         write!(out, "*return$");
     }
     writeln!(out, ") noexcept {{");
     write!(out, "  ");
-    write_return_type(out, &efn.ret, types);
+    write_return_type(out, &efn.ret);
     match &efn.receiver {
         None => write!(out, "(*{}$)(", efn.ident.rust),
         Some(receiver) => write!(
             out,
             "({}::*{}$)(",
-            types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).to_fully_qualified(),
             efn.ident.rust
         ),
     }
@@ -563,7 +553,7 @@ fn write_cxx_function_shim(
         if i > 0 {
             write!(out, ", ");
         }
-        write_type(out, &arg.ty, types);
+        write_type(out, &arg.ty);
     }
     write!(out, ")");
     if let Some(receiver) = &efn.receiver {
@@ -577,7 +567,7 @@ fn write_cxx_function_shim(
         Some(receiver) => write!(
             out,
             "&{}::{}",
-            types.resolve(&receiver.ty).to_fully_qualified(),
+            out.types.resolve(&receiver.ty).to_fully_qualified(),
             efn.ident.cxx.ident
         ),
     }
@@ -592,7 +582,7 @@ fn write_cxx_function_shim(
     if indirect_return {
         out.include.new = true;
         write!(out, "new (return$) ");
-        write_indirect_return_type(out, efn.ret.as_ref().unwrap(), types);
+        write_indirect_return_type(out, efn.ret.as_ref().unwrap());
         write!(out, "(");
     } else if efn.ret.is_some() {
         write!(out, "return ");
@@ -614,10 +604,10 @@ fn write_cxx_function_shim(
             write!(out, ", ");
         }
         if let Type::RustBox(_) = &arg.ty {
-            write_type(out, &arg.ty, types);
+            write_type(out, &arg.ty);
             write!(out, "::from_raw({})", arg.ident);
         } else if let Type::UniquePtr(_) = &arg.ty {
-            write_type(out, &arg.ty, types);
+            write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
         } else if arg.ty == RustString {
             write!(
@@ -626,9 +616,9 @@ fn write_cxx_function_shim(
                 arg.ident,
             );
         } else if let Type::RustVec(_) = arg.ty {
-            write_type(out, &arg.ty, types);
+            write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if types.needs_indirect_abi(&arg.ty) {
+        } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
         } else {
@@ -663,7 +653,7 @@ fn write_cxx_function_shim(
     for arg in &efn.args {
         if let Type::Fn(f) = &arg.ty {
             let var = &arg.ident;
-            write_function_pointer_trampoline(out, efn, var, f, types);
+            write_function_pointer_trampoline(out, efn, var, f);
         }
     }
 }
@@ -673,35 +663,33 @@ fn write_function_pointer_trampoline(
     efn: &ExternFn,
     var: &Ident,
     f: &Signature,
-    types: &Types,
 ) {
     out.next_section();
-    let r_trampoline = mangle::r_trampoline(efn, var, types);
+    let r_trampoline = mangle::r_trampoline(efn, var, out.types);
     let indirect_call = true;
-    write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
+    write_rust_function_decl_impl(out, &r_trampoline, f, indirect_call);
 
     out.next_section();
-    let c_trampoline = mangle::c_trampoline(efn, var, types).to_string();
-    write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
+    let c_trampoline = mangle::c_trampoline(efn, var, out.types).to_string();
+    write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
 }
 
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
-    let link_name = mangle::extern_fn(efn, types);
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, _: &Option<String>) {
+    let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
-    write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
+    write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
 }
 
 fn write_rust_function_decl_impl(
     out: &mut OutFile,
     link_name: &Symbol,
     sig: &Signature,
-    types: &Types,
     indirect_call: bool,
 ) {
     if sig.throws {
         write!(out, "::rust::Str::Repr ");
     } else {
-        write_extern_return_type_space(out, &sig.ret, types);
+        write_extern_return_type_space(out, &sig.ret);
     }
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
@@ -712,7 +700,7 @@ fn write_rust_function_decl_impl(
         write!(
             out,
             "{} &self",
-            types.resolve(&receiver.ty).to_fully_qualified()
+            out.types.resolve(&receiver.ty).to_fully_qualified()
         );
         needs_comma = true;
     }
@@ -720,14 +708,14 @@ fn write_rust_function_decl_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        write_extern_arg(out, arg, types);
+        write_extern_arg(out, arg);
         needs_comma = true;
     }
-    if indirect_return(sig, types) {
+    if indirect_return(sig, out.types) {
         if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &sig.ret, types);
+        write_return_type(out, &sig.ret);
         write!(out, "*return$");
         needs_comma = true;
     }
@@ -740,7 +728,7 @@ fn write_rust_function_decl_impl(
     writeln!(out, ") noexcept;");
 }
 
-fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
+fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
@@ -748,13 +736,13 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
         None => efn.ident.cxx.ident.to_string(),
         Some(receiver) => format!(
             "{}::{}",
-            types.resolve(&receiver.ty).ident,
+            out.types.resolve(&receiver.ty).ident,
             efn.ident.cxx.ident
         ),
     };
-    let invoke = mangle::extern_fn(efn, types);
+    let invoke = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
-    write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
+    write_rust_function_shim_impl(out, &local_name, efn, &invoke, indirect_call);
 }
 
 fn write_rust_function_shim_decl(
@@ -762,15 +750,14 @@ fn write_rust_function_shim_decl(
     local_name: &str,
     sig: &Signature,
     indirect_call: bool,
-    types: &Types,
 ) {
-    write_return_type(out, &sig.ret, types);
+    write_return_type(out, &sig.ret);
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
         if i > 0 {
             write!(out, ", ");
         }
-        write_type_space(out, &arg.ty, types);
+        write_type_space(out, &arg.ty);
         write!(out, "{}", arg.ident);
     }
     if indirect_call {
@@ -794,7 +781,6 @@ fn write_rust_function_shim_impl(
     out: &mut OutFile,
     local_name: &str,
     sig: &Signature,
-    types: &Types,
     invoke: &Symbol,
     indirect_call: bool,
 ) {
@@ -802,36 +788,36 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    write_rust_function_shim_decl(out, local_name, sig, indirect_call, types);
+    write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");
         return;
     }
     writeln!(out, " {{");
     for arg in &sig.args {
-        if arg.ty != RustString && types.needs_indirect_abi(&arg.ty) {
+        if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "  ::rust::ManuallyDrop<");
-            write_type(out, &arg.ty, types);
+            write_type(out, &arg.ty);
             writeln!(out, "> {}$(::std::move({0}));", arg.ident);
         }
     }
     write!(out, "  ");
-    let indirect_return = indirect_return(sig, types);
+    let indirect_return = indirect_return(sig, out.types);
     if indirect_return {
         write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap(), types);
+        write_type(out, sig.ret.as_ref().unwrap());
         writeln!(out, "> return$;");
         write!(out, "  ");
     } else if let Some(ret) = &sig.ret {
         write!(out, "return ");
         match ret {
             Type::RustBox(_) => {
-                write_type(out, ret, types);
+                write_type(out, ret);
                 write!(out, "::from_raw(");
             }
             Type::UniquePtr(_) => {
-                write_type(out, ret, types);
+                write_type(out, ret);
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
@@ -852,7 +838,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::Str(_) => write!(out, "::rust::Str::Repr("),
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
-            ty if types.needs_indirect_abi(ty) => write!(out, "&"),
+            ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
         }
         write!(out, "{}", arg.ident);
@@ -860,7 +846,7 @@ fn write_rust_function_shim_impl(
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
             Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
-            ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"),
+            ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
     }
@@ -897,10 +883,10 @@ fn write_rust_function_shim_impl(
     writeln!(out, "}}");
 }
 
-fn write_return_type(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
+fn write_return_type(out: &mut OutFile, ty: &Option<Type>) {
     match ty {
         None => write!(out, "void "),
-        Some(ty) => write_type_space(out, ty, types),
+        Some(ty) => write_type_space(out, ty),
     }
 }
 
@@ -910,27 +896,27 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn write_indirect_return_type(out: &mut OutFile, ty: &Type, types: &Types) {
+fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            write_type_space(out, &ty.inner, types);
+            write_type_space(out, &ty.inner);
             write!(out, "*");
         }
         Type::Ref(ty) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner, types);
+            write_type(out, &ty.inner);
             write!(out, " *");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr"),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
-        _ => write_type(out, ty, types),
+        _ => write_type(out, ty),
     }
 }
 
-fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
-    write_indirect_return_type(out, ty, types);
+fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
+    write_indirect_return_type(out, ty);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
         Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
@@ -938,73 +924,73 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type, types: &Types)
     }
 }
 
-fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>, types: &Types) {
+fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
     match ty {
         Some(Type::RustBox(ty)) | Some(Type::UniquePtr(ty)) => {
-            write_type_space(out, &ty.inner, types);
+            write_type_space(out, &ty.inner);
             write!(out, "*");
         }
         Some(Type::Ref(ty)) => {
             if ty.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &ty.inner, types);
+            write_type(out, &ty.inner);
             write!(out, " *");
         }
         Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "),
-        _ => write_return_type(out, ty, types),
+        Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
+        _ => write_return_type(out, ty),
     }
 }
 
-fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
+fn write_extern_arg(out: &mut OutFile, arg: &Var) {
     match &arg.ty {
         Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) => {
-            write_type_space(out, &ty.inner, types);
+            write_type_space(out, &ty.inner);
             write!(out, "*");
         }
         Type::Str(_) => write!(out, "::rust::Str::Repr "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
-        _ => write_type_space(out, &arg.ty, types),
+        _ => write_type_space(out, &arg.ty),
     }
-    if types.needs_indirect_abi(&arg.ty) {
+    if out.types.needs_indirect_abi(&arg.ty) {
         write!(out, "*");
     }
     write!(out, "{}", arg.ident);
 }
 
-fn write_type(out: &mut OutFile, ty: &Type, types: &Types) {
+fn write_type(out: &mut OutFile, ty: &Type) {
     match ty {
         Type::Ident(ident) => match Atom::from(&ident.rust) {
             Some(atom) => write_atom(out, atom),
-            None => write!(out, "{}", types.resolve(ident).to_fully_qualified()),
+            None => write!(out, "{}", out.types.resolve(ident).to_fully_qualified()),
         },
         Type::RustBox(ty) => {
             write!(out, "::rust::Box<");
-            write_type(out, &ty.inner, types);
+            write_type(out, &ty.inner);
             write!(out, ">");
         }
         Type::RustVec(ty) => {
             write!(out, "::rust::Vec<");
-            write_type(out, &ty.inner, types);
+            write_type(out, &ty.inner);
             write!(out, ">");
         }
         Type::UniquePtr(ptr) => {
             write!(out, "::std::unique_ptr<");
-            write_type(out, &ptr.inner, types);
+            write_type(out, &ptr.inner);
             write!(out, ">");
         }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
-            write_type(out, &ty.inner, types);
+            write_type(out, &ty.inner);
             write!(out, ">");
         }
         Type::Ref(r) => {
             if r.mutability.is_none() {
                 write!(out, "const ");
             }
-            write_type(out, &r.inner, types);
+            write_type(out, &r.inner);
             write!(out, " &");
         }
         Type::Slice(_) => {
@@ -1020,7 +1006,7 @@ fn write_type(out: &mut OutFile, ty: &Type, types: &Types) {
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
             match &f.ret {
-                Some(ret) => write_type(out, ret, types),
+                Some(ret) => write_type(out, ret),
                 None => write!(out, "void"),
             }
             write!(out, "(");
@@ -1028,7 +1014,7 @@ fn write_type(out: &mut OutFile, ty: &Type, types: &Types) {
                 if i > 0 {
                     write!(out, ", ");
                 }
-                write_type(out, &arg.ty, types);
+                write_type(out, &arg.ty);
             }
             write!(out, ")>");
         }
@@ -1056,8 +1042,8 @@ fn write_atom(out: &mut OutFile, atom: Atom) {
     }
 }
 
-fn write_type_space(out: &mut OutFile, ty: &Type, types: &Types) {
-    write_type(out, ty, types);
+fn write_type_space(out: &mut OutFile, ty: &Type) {
+    write_type(out, ty);
     write_space_after_type(out, ty);
 }
 
@@ -1096,39 +1082,39 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
     }
 }
 
-fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
+fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block("extern \"C\"");
-    for ty in types {
+    for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
                 out.next_section();
-                write_rust_box_extern(out, &types.resolve(&inner));
+                write_rust_box_extern(out, &out.types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
                 if Atom::from(&inner.rust).is_none() {
                     out.next_section();
-                    write_rust_vec_extern(out, inner, types);
+                    write_rust_vec_extern(out, inner);
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
-                    && (!types.aliases.contains_key(&inner.rust)
-                        || types.explicit_impls.contains(ty))
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
                 {
                     out.next_section();
-                    write_unique_ptr(out, inner, types);
+                    write_unique_ptr(out, inner);
                 }
             }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
-                    && (!types.aliases.contains_key(&inner.rust)
-                        || types.explicit_impls.contains(ty))
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
                 {
                     out.next_section();
-                    write_cxx_vector(out, ty, inner, types);
+                    write_cxx_vector(out, ty, inner);
                 }
             }
         }
@@ -1137,15 +1123,15 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
 
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");
-    for ty in types {
+    for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, &types.resolve(&inner));
+                write_rust_box_impl(out, &out.types.resolve(&inner));
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
                 if Atom::from(&inner.rust).is_none() {
-                    write_rust_vec_impl(out, inner, types);
+                    write_rust_vec_impl(out, inner);
                 }
             }
         }
@@ -1173,10 +1159,10 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {
     writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName, types: &Types) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, types);
-    let instance = to_mangled(&element, types);
+    let inner = to_typename(&element, out.types);
+    let instance = to_mangled(&element, out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
@@ -1223,10 +1209,10 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &CppName) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName, types: &Types) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, types);
-    let instance = to_mangled(&element, types);
+    let inner = to_typename(&element, out.types);
+    let instance = to_mangled(&element, out.types);
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
@@ -1262,24 +1248,24 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName, types: &Type
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName, types: &Types) {
+fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
     let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&ty, types);
+    let instance = to_mangled(&ty, out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
 
-    write_unique_ptr_common(out, &ty, types);
+    write_unique_ptr_common(out, &ty);
 
     writeln!(out, "#endif // CXXBRIDGE05_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
-fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
+fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     out.include.new = true;
     out.include.utility = true;
-    let inner = to_typename(ty, types);
-    let instance = to_mangled(ty, types);
+    let inner = to_typename(ty, out.types);
+    let instance = to_mangled(ty, out.types);
 
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types. We can't
@@ -1287,7 +1273,8 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         Type::Ident(ident) => {
-            types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust)
+            out.types.structs.contains_key(&ident.rust)
+                || out.types.aliases.contains_key(&ident.rust)
         }
         _ => false,
     };
@@ -1352,10 +1339,10 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName, types: &Types) {
+fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName) {
     let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, types);
-    let instance = to_mangled(&element, types);
+    let inner = to_typename(&element, out.types);
+    let instance = to_mangled(&element, out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
@@ -1374,7 +1361,7 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableNam
     writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
-    write_unique_ptr_common(out, vector_ty, types);
+    write_unique_ptr_common(out, vector_ty);
 
     writeln!(out, "#endif // CXXBRIDGE05_VECTOR_{}", instance);
 }

From 5fedc9a359648ee23ad51d298030795267006c16 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 04:46:17 +0000
Subject: [PATCH 1102/2232] Use a less strange return type for NamespaceEntries::children


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index 4aacc8f..525c367 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -17,8 +17,8 @@ impl<'a> NamespaceEntries<'a> {
         &self.entries
     }
 
-    pub fn children(&self) -> impl Iterator<Item = (&&Ident, &NamespaceEntries)> {
-        self.children.iter()
+    pub fn children(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
+        self.children.iter().map(|(k, entries)| (*k, entries))
     }
 
     fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {

From cedcde1ddd45c456f94039445e500e1164ca34f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 18:47:14 +0000
Subject: [PATCH 1103/2232] Fill in missing const on operator Repr


---

diff --git a/include/cxx.h b/include/cxx.h
index 0373a38..7b332b4 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -81,7 +81,7 @@ public:
     size_t len;
   };
   Str(Repr) noexcept;
-  explicit operator Repr() noexcept;
+  explicit operator Repr() const noexcept;
 
 private:
   Repr repr;
@@ -112,7 +112,7 @@ public:
     size_t len;
   };
   Slice(Repr) noexcept;
-  explicit operator Repr() noexcept;
+  explicit operator Repr() const noexcept;
 
 private:
   Repr repr;
@@ -348,7 +348,7 @@ template <typename T>
 Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
 
 template <typename T>
-Slice<T>::operator Repr() noexcept {
+Slice<T>::operator Repr() const noexcept {
   return this->repr;
 }
 #endif // CXXBRIDGE05_RUST_SLICE
diff --git a/src/cxx.cc b/src/cxx.cc
index a423df6..254072e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -159,7 +159,7 @@ size_t Str::length() const noexcept { return this->repr.len; }
 
 Str::Str(Repr repr_) noexcept : repr(repr_) {}
 
-Str::operator Repr() noexcept { return this->repr; }
+Str::operator Repr() const noexcept { return this->repr; }
 
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());

From de9a5b12b30518bc9f66d4d86b8f460b960194c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 19:17:42 +0000
Subject: [PATCH 1104/2232] Guarantee trivial copy constructor and destructor for Str and Slice


Repro:

    const char *ptr(Str str) { return str.repr.ptr; }
    size_t len(Str str) { return str.repr.len; }

Before:

    ptr(Str):
        mov     rax, qword ptr [rdi]
        ret
    len(Str):
        mov     rax, qword ptr [rdi + 8]
        ret

After:

    ptr(Str):
        mov     rax, rdi
        ret
    len(Str):
        mov     rax, rsi
        ret

---

diff --git a/include/cxx.h b/include/cxx.h
index 7b332b4..9f0bf46 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,8 +56,6 @@ private:
 class Str final {
 public:
   Str() noexcept;
-  Str(const Str &) noexcept;
-
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
@@ -72,6 +70,10 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  // Important in order for System V ABI to pass in registers.
+  Str(const Str &) noexcept = default;
+  ~Str() noexcept = default;
+
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
   // Not necessarily ABI compatible with &str. Codegen will translate to
@@ -93,7 +95,6 @@ template <typename T>
 class Slice final {
 public:
   Slice() noexcept;
-  Slice(const Slice<T> &) noexcept;
   Slice(const T *, size_t count) noexcept;
 
   Slice &operator=(Slice<T>) noexcept;
@@ -102,6 +103,10 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  // Important in order for System V ABI to pass in registers.
+  Slice(const Slice<T> &) noexcept = default;
+  ~Slice() noexcept = default;
+
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
   // At present this class is only used for &[u8] slices.
@@ -318,9 +323,6 @@ template <typename T>
 Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
 
 template <typename T>
-Slice<T>::Slice(const Slice<T> &) noexcept = default;
-
-template <typename T>
 Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
 
 template <typename T>
diff --git a/src/cxx.cc b/src/cxx.cc
index 254072e..96a1861 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -117,8 +117,6 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 
 Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
-Str::Str(const Str &) noexcept = default;
-
 static void initStr(Str::Repr repr) {
   if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");

From a53086ba5104a13295a8f0478e0fcc8c5840a18f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 19:31:50 +0000
Subject: [PATCH 1105/2232] Merge pull request #387 from dtolnay/trivial


Guarantee trivial copy constructor and destructor for Str and Slice
---

diff --git a/include/cxx.h b/include/cxx.h
index 7b332b4..9f0bf46 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,8 +56,6 @@ private:
 class Str final {
 public:
   Str() noexcept;
-  Str(const Str &) noexcept;
-
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
@@ -72,6 +70,10 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  // Important in order for System V ABI to pass in registers.
+  Str(const Str &) noexcept = default;
+  ~Str() noexcept = default;
+
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
   // Not necessarily ABI compatible with &str. Codegen will translate to
@@ -93,7 +95,6 @@ template <typename T>
 class Slice final {
 public:
   Slice() noexcept;
-  Slice(const Slice<T> &) noexcept;
   Slice(const T *, size_t count) noexcept;
 
   Slice &operator=(Slice<T>) noexcept;
@@ -102,6 +103,10 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  // Important in order for System V ABI to pass in registers.
+  Slice(const Slice<T> &) noexcept = default;
+  ~Slice() noexcept = default;
+
   // Repr is PRIVATE; must not be used other than by our generated code.
   //
   // At present this class is only used for &[u8] slices.
@@ -318,9 +323,6 @@ template <typename T>
 Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
 
 template <typename T>
-Slice<T>::Slice(const Slice<T> &) noexcept = default;
-
-template <typename T>
 Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
 
 template <typename T>
diff --git a/src/cxx.cc b/src/cxx.cc
index 254072e..96a1861 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -117,8 +117,6 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 
 Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
 
-Str::Str(const Str &) noexcept = default;
-
 static void initStr(Str::Repr repr) {
   if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");

From 4852122f35be1e5872728a3a1641f58437646e2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 21:59:42 +0000
Subject: [PATCH 1106/2232] Fill in some missing final specifiers


---

diff --git a/include/cxx.h b/include/cxx.h
index 9f0bf46..bf16dd0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -78,7 +78,7 @@ public:
   //
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
-  struct Repr {
+  struct Repr final {
     const char *ptr;
     size_t len;
   };
@@ -112,7 +112,7 @@ public:
   // At present this class is only used for &[u8] slices.
   // Not necessarily ABI compatible with &[u8]. Codegen will translate to
   // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
-  struct Repr {
+  struct Repr final {
     const T *ptr;
     size_t len;
   };
@@ -187,7 +187,7 @@ public:
   const T &front() const;
   const T &back() const;
 
-  class const_iterator {
+  class const_iterator final {
   public:
     using difference_type = ptrdiff_t;
     using value_type = typename std::add_const<T>::type;
@@ -231,7 +231,7 @@ template <typename Signature, bool Throws = false>
 class Fn;
 
 template <typename Ret, typename... Args, bool Throws>
-class Fn<Ret(Args...), Throws> {
+class Fn<Ret(Args...), Throws> final {
 public:
   Ret operator()(Args... args) const noexcept(!Throws);
   Fn operator*() const noexcept;
@@ -310,7 +310,7 @@ Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
 
 #ifndef CXXBRIDGE05_RUST_BITCOPY
 #define CXXBRIDGE05_RUST_BITCOPY
-struct unsafe_bitcopy_t {
+struct unsafe_bitcopy_t final {
   explicit unsafe_bitcopy_t() = default;
 };
 

From cc1ae76bd09dc91b7ada120435539c3f60b2b2a4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 22:53:53 +0000
Subject: [PATCH 1107/2232] Remove redundant header branch from write_cxx_function_shim


These shims only get emitted in the non-header case in the first place.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index f259222..25f1b0b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -496,10 +496,8 @@ fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
 }
 
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: &Option<String>) {
-    if !out.header {
-        if let Some(annotation) = impl_annotations {
-            write!(out, "{} ", annotation);
-        }
+    if let Some(annotation) = impl_annotations {
+        write!(out, "{} ", annotation);
     }
     if efn.throws {
         write!(out, "::rust::Str::Repr ");

From 504cf3cfb84c7df1e59544793113288add4ba36a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 23:09:18 +0000
Subject: [PATCH 1108/2232] Fix unqualified strncpy call


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 96a1861..d18bec9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -167,7 +167,7 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
 extern "C" {
 const char *cxxbridge05$error(const char *ptr, size_t len) {
   char *copy = new char[len];
-  strncpy(copy, ptr, len);
+  std::strncpy(copy, ptr, len);
   return copy;
 }
 } // extern "C"

From 5b41479aeb04f41e719c03e60c6d58e30b6ef878 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 23:58:14 +0000
Subject: [PATCH 1109/2232] Fix stray delete in Error move constructor


---

diff --git a/src/cxx.cc b/src/cxx.cc
index d18bec9..43bf245 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -180,7 +180,6 @@ Error::Error(const Error &other) {
 }
 
 Error::Error(Error &&other) noexcept {
-  delete[] this->msg.ptr;
   this->msg = other.msg;
   other.msg.ptr = nullptr;
   other.msg.len = 0;

From a0c9bc7167891d7522270f19b971b3a25d7ed807 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 23:59:29 +0000
Subject: [PATCH 1110/2232] Decouple Error from Str::Repr


It was misleading to use Str (which ordinarily represents borrowed
strings) also for owned error messages.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 25f1b0b..8de422d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -315,6 +315,25 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
+    if needs_rust_error {
+        out.begin_block("namespace repr");
+        writeln!(out, "struct PtrLen final {{");
+        writeln!(out, "  const char *ptr;");
+        writeln!(out, "  size_t len;");
+        writeln!(out, "}};");
+        out.end_block("namespace repr");
+
+        writeln!(out, "class impl final {{");
+        writeln!(out, "public:");
+        writeln!(out, "  static Error error(repr::PtrLen ptrlen) noexcept {{");
+        writeln!(out, "    Error error;");
+        writeln!(out, "    error.msg = ptrlen.ptr;");
+        writeln!(out, "    error.len = ptrlen.len;");
+        writeln!(out, "    return error;");
+        writeln!(out, "  }}");
+        writeln!(out, "}};");
+    }
+
     out.end_block("namespace cxxbridge05");
 
     if needs_trycatch {
@@ -685,7 +704,7 @@ fn write_rust_function_decl_impl(
     indirect_call: bool,
 ) {
     if sig.throws {
-        write!(out, "::rust::Str::Repr ");
+        write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &sig.ret);
     }
@@ -823,7 +842,7 @@ fn write_rust_function_shim_impl(
         }
     }
     if sig.throws {
-        write!(out, "::rust::Str::Repr error$ = ");
+        write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
     if sig.receiver.is_some() {
@@ -871,7 +890,7 @@ fn write_rust_function_shim_impl(
     writeln!(out, ";");
     if sig.throws {
         writeln!(out, "  if (error$.ptr) {{");
-        writeln!(out, "    throw ::rust::Error(error$);");
+        writeln!(out, "    throw ::rust::impl::error(error$);");
         writeln!(out, "  }}");
     }
     if indirect_return {
diff --git a/include/cxx.h b/include/cxx.h
index bf16dd0..d044111 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -251,12 +251,14 @@ class Error final : public std::exception {
 public:
   Error(const Error &);
   Error(Error &&) noexcept;
-  Error(Str::Repr) noexcept;
   ~Error() noexcept;
   const char *what() const noexcept override;
 
 private:
-  Str::Repr msg;
+  Error() noexcept = default;
+  friend class impl;
+  const char *msg;
+  size_t len;
 };
 #endif // CXXBRIDGE05_RUST_ERROR
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 43bf245..077f8ce 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -172,22 +172,21 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 }
 } // extern "C"
 
-Error::Error(Str::Repr msg) noexcept : msg(msg) {}
-
 Error::Error(const Error &other) {
-  this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
-  this->msg.len = other.msg.len;
+  this->msg = cxxbridge05$error(other.msg, other.len);
+  this->len = other.len;
 }
 
 Error::Error(Error &&other) noexcept {
   this->msg = other.msg;
-  other.msg.ptr = nullptr;
-  other.msg.len = 0;
+  this->len = other.len;
+  other.msg = nullptr;
+  other.len = 0;
 }
 
-Error::~Error() noexcept { delete[] this->msg.ptr; }
+Error::~Error() noexcept { delete[] this->msg; }
 
-const char *Error::what() const noexcept { return this->msg.ptr; }
+const char *Error::what() const noexcept { return this->msg; }
 
 } // namespace cxxbridge05
 } // namespace rust

From 84ddf9e27f084d7431eea2c6c33f3a39ce4a7d20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 23:59:29 +0000
Subject: [PATCH 1111/2232] Move "impl" into anonymous namespace


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8de422d..3b404c6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -281,6 +281,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
+    if needs_rust_error {
+        out.begin_block("namespace");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl;");
+        out.end_block("namespace");
+    }
+
     include::write(out, needs_rust_string, "CXXBRIDGE05_RUST_STRING");
     include::write(out, needs_rust_str, "CXXBRIDGE05_RUST_STR");
     include::write(out, needs_rust_slice, "CXXBRIDGE05_RUST_SLICE");
@@ -316,22 +323,22 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     }
 
     if needs_rust_error {
-        out.begin_block("namespace repr");
-        writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const char *ptr;");
-        writeln!(out, "  size_t len;");
-        writeln!(out, "}};");
-        out.end_block("namespace repr");
-
-        writeln!(out, "class impl final {{");
+        out.begin_block("namespace");
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Error> final {{");
         writeln!(out, "public:");
-        writeln!(out, "  static Error error(repr::PtrLen ptrlen) noexcept {{");
+        writeln!(out, "  struct Repr final {{");
+        writeln!(out, "    const char *msg;");
+        writeln!(out, "    size_t len;");
+        writeln!(out, "  }};");
+        writeln!(out, "  static Error error(Repr repr) noexcept {{");
         writeln!(out, "    Error error;");
-        writeln!(out, "    error.msg = ptrlen.ptr;");
-        writeln!(out, "    error.len = ptrlen.len;");
+        writeln!(out, "    error.msg = repr.msg;");
+        writeln!(out, "    error.len = repr.len;");
         writeln!(out, "    return error;");
         writeln!(out, "  }}");
         writeln!(out, "}};");
+        out.end_block("namespace");
     }
 
     out.end_block("namespace cxxbridge05");
@@ -704,7 +711,7 @@ fn write_rust_function_decl_impl(
     indirect_call: bool,
 ) {
     if sig.throws {
-        write!(out, "::rust::repr::PtrLen ");
+        write!(out, "::rust::impl<::rust::Error>::Repr ");
     } else {
         write_extern_return_type_space(out, &sig.ret);
     }
@@ -842,7 +849,7 @@ fn write_rust_function_shim_impl(
         }
     }
     if sig.throws {
-        write!(out, "::rust::repr::PtrLen error$ = ");
+        write!(out, "::rust::impl<::rust::Error>::Repr error$ = ");
     }
     write!(out, "{}(", invoke);
     if sig.receiver.is_some() {
@@ -889,8 +896,8 @@ fn write_rust_function_shim_impl(
     }
     writeln!(out, ";");
     if sig.throws {
-        writeln!(out, "  if (error$.ptr) {{");
-        writeln!(out, "    throw ::rust::impl::error(error$);");
+        writeln!(out, "  if (error$.msg) {{");
+        writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
         writeln!(out, "  }}");
     }
     if indirect_return {
diff --git a/include/cxx.h b/include/cxx.h
index d044111..adbc8e6 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -19,6 +19,11 @@ inline namespace cxxbridge05 {
 
 struct unsafe_bitcopy_t;
 
+namespace {
+template <typename T>
+class impl;
+}
+
 #ifndef CXXBRIDGE05_RUST_STRING
 #define CXXBRIDGE05_RUST_STRING
 class String final {
@@ -256,7 +261,7 @@ public:
 
 private:
   Error() noexcept = default;
-  friend class impl;
+  friend impl<Error>;
   const char *msg;
   size_t len;
 };

From d68dfa8ee7624ec7859167bcc4eadd89caca1dda Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Oct 31 2020 23:59:29 +0000
Subject: [PATCH 1112/2232] Decouple exception catch from Str::Repr


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3b404c6..16bb7cd 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -322,25 +322,31 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
+    out.begin_block("namespace");
+
+    if needs_trycatch || needs_rust_error {
+        out.begin_block("namespace repr");
+        writeln!(out, "struct PtrLen final {{");
+        writeln!(out, "  const char *ptr;");
+        writeln!(out, "  size_t len;");
+        writeln!(out, "}};");
+        out.end_block("namespace repr");
+    }
+
     if needs_rust_error {
-        out.begin_block("namespace");
         writeln!(out, "template <>");
         writeln!(out, "class impl<Error> final {{");
         writeln!(out, "public:");
-        writeln!(out, "  struct Repr final {{");
-        writeln!(out, "    const char *msg;");
-        writeln!(out, "    size_t len;");
-        writeln!(out, "  }};");
-        writeln!(out, "  static Error error(Repr repr) noexcept {{");
+        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
         writeln!(out, "    Error error;");
-        writeln!(out, "    error.msg = repr.msg;");
+        writeln!(out, "    error.msg = repr.ptr;");
         writeln!(out, "    error.len = repr.len;");
         writeln!(out, "    return error;");
         writeln!(out, "  }}");
         writeln!(out, "}};");
-        out.end_block("namespace");
     }
 
+    out.end_block("namespace");
     out.end_block("namespace cxxbridge05");
 
     if needs_trycatch {
@@ -526,7 +532,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
         write!(out, "{} ", annotation);
     }
     if efn.throws {
-        write!(out, "::rust::Str::Repr ");
+        write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &efn.ret);
     }
@@ -598,7 +604,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
-        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "::rust::repr::PtrLen throw$;");
         writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
         write!(out, "        ");
@@ -711,7 +717,7 @@ fn write_rust_function_decl_impl(
     indirect_call: bool,
 ) {
     if sig.throws {
-        write!(out, "::rust::impl<::rust::Error>::Repr ");
+        write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &sig.ret);
     }
@@ -849,7 +855,7 @@ fn write_rust_function_shim_impl(
         }
     }
     if sig.throws {
-        write!(out, "::rust::impl<::rust::Error>::Repr error$ = ");
+        write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
     if sig.receiver.is_some() {
@@ -896,7 +902,7 @@ fn write_rust_function_shim_impl(
     }
     writeln!(out, ";");
     if sig.throws {
-        writeln!(out, "  if (error$.msg) {{");
+        writeln!(out, "  if (error$.ptr) {{");
         writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
         writeln!(out, "  }}");
     }

From 59c5dc28918752409afd1bfdce6dbafeada5880a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:09:02 +0000
Subject: [PATCH 1113/2232] Merge pull request #388 from dtolnay/error


Decouple Error from Str::Repr
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 25f1b0b..16bb7cd 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -281,6 +281,13 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
+    if needs_rust_error {
+        out.begin_block("namespace");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl;");
+        out.end_block("namespace");
+    }
+
     include::write(out, needs_rust_string, "CXXBRIDGE05_RUST_STRING");
     include::write(out, needs_rust_str, "CXXBRIDGE05_RUST_STR");
     include::write(out, needs_rust_slice, "CXXBRIDGE05_RUST_SLICE");
@@ -315,6 +322,31 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
+    out.begin_block("namespace");
+
+    if needs_trycatch || needs_rust_error {
+        out.begin_block("namespace repr");
+        writeln!(out, "struct PtrLen final {{");
+        writeln!(out, "  const char *ptr;");
+        writeln!(out, "  size_t len;");
+        writeln!(out, "}};");
+        out.end_block("namespace repr");
+    }
+
+    if needs_rust_error {
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Error> final {{");
+        writeln!(out, "public:");
+        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
+        writeln!(out, "    Error error;");
+        writeln!(out, "    error.msg = repr.ptr;");
+        writeln!(out, "    error.len = repr.len;");
+        writeln!(out, "    return error;");
+        writeln!(out, "  }}");
+        writeln!(out, "}};");
+    }
+
+    out.end_block("namespace");
     out.end_block("namespace cxxbridge05");
 
     if needs_trycatch {
@@ -500,7 +532,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
         write!(out, "{} ", annotation);
     }
     if efn.throws {
-        write!(out, "::rust::Str::Repr ");
+        write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &efn.ret);
     }
@@ -572,7 +604,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
-        writeln!(out, "::rust::Str::Repr throw$;");
+        writeln!(out, "::rust::repr::PtrLen throw$;");
         writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
         write!(out, "        ");
@@ -685,7 +717,7 @@ fn write_rust_function_decl_impl(
     indirect_call: bool,
 ) {
     if sig.throws {
-        write!(out, "::rust::Str::Repr ");
+        write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &sig.ret);
     }
@@ -823,7 +855,7 @@ fn write_rust_function_shim_impl(
         }
     }
     if sig.throws {
-        write!(out, "::rust::Str::Repr error$ = ");
+        write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
     if sig.receiver.is_some() {
@@ -871,7 +903,7 @@ fn write_rust_function_shim_impl(
     writeln!(out, ";");
     if sig.throws {
         writeln!(out, "  if (error$.ptr) {{");
-        writeln!(out, "    throw ::rust::Error(error$);");
+        writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
         writeln!(out, "  }}");
     }
     if indirect_return {
diff --git a/include/cxx.h b/include/cxx.h
index bf16dd0..adbc8e6 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -19,6 +19,11 @@ inline namespace cxxbridge05 {
 
 struct unsafe_bitcopy_t;
 
+namespace {
+template <typename T>
+class impl;
+}
+
 #ifndef CXXBRIDGE05_RUST_STRING
 #define CXXBRIDGE05_RUST_STRING
 class String final {
@@ -251,12 +256,14 @@ class Error final : public std::exception {
 public:
   Error(const Error &);
   Error(Error &&) noexcept;
-  Error(Str::Repr) noexcept;
   ~Error() noexcept;
   const char *what() const noexcept override;
 
 private:
-  Str::Repr msg;
+  Error() noexcept = default;
+  friend impl<Error>;
+  const char *msg;
+  size_t len;
 };
 #endif // CXXBRIDGE05_RUST_ERROR
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 43bf245..077f8ce 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -172,22 +172,21 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 }
 } // extern "C"
 
-Error::Error(Str::Repr msg) noexcept : msg(msg) {}
-
 Error::Error(const Error &other) {
-  this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
-  this->msg.len = other.msg.len;
+  this->msg = cxxbridge05$error(other.msg, other.len);
+  this->len = other.len;
 }
 
 Error::Error(Error &&other) noexcept {
   this->msg = other.msg;
-  other.msg.ptr = nullptr;
-  other.msg.len = 0;
+  this->len = other.len;
+  other.msg = nullptr;
+  other.len = 0;
 }
 
-Error::~Error() noexcept { delete[] this->msg.ptr; }
+Error::~Error() noexcept { delete[] this->msg; }
 
-const char *Error::what() const noexcept { return this->msg.ptr; }
+const char *Error::what() const noexcept { return this->msg; }
 
 } // namespace cxxbridge05
 } // namespace rust

From d5712ee32c6366ee087f19fd72f7b68007a9a821 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:10:00 +0000
Subject: [PATCH 1114/2232] Use member initializer lists for Error constructors


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 077f8ce..1bfd8b9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -172,14 +172,10 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 }
 } // extern "C"
 
-Error::Error(const Error &other) {
-  this->msg = cxxbridge05$error(other.msg, other.len);
-  this->len = other.len;
-}
+Error::Error(const Error &other)
+    : msg(cxxbridge05$error(other.msg, other.len)), len(other.len) {}
 
-Error::Error(Error &&other) noexcept {
-  this->msg = other.msg;
-  this->len = other.len;
+Error::Error(Error &&other) noexcept : msg(other.msg), len(other.len) {
   other.msg = nullptr;
   other.len = 0;
 }

From 23c2319bc860aab99222cdaaa60ff5ff665fc60f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:11:48 +0000
Subject: [PATCH 1115/2232] Fill in Error base class constructor calls


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 1bfd8b9..0fba35c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -173,9 +173,11 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 } // extern "C"
 
 Error::Error(const Error &other)
-    : msg(cxxbridge05$error(other.msg, other.len)), len(other.len) {}
+    : std::exception(other), msg(cxxbridge05$error(other.msg, other.len)),
+      len(other.len) {}
 
-Error::Error(Error &&other) noexcept : msg(other.msg), len(other.len) {
+Error::Error(Error &&other) noexcept
+    : std::exception(std::move(other)), msg(other.msg), len(other.len) {
   other.msg = nullptr;
   other.len = 0;
 }

From e58f4270ed8c2e2b3a67c5f9cf74636e4641d128 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:22:36 +0000
Subject: [PATCH 1116/2232] Merge pull request #389 from dtolnay/error


Fill in Error base class constructor calls
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 1bfd8b9..0fba35c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -173,9 +173,11 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 } // extern "C"
 
 Error::Error(const Error &other)
-    : msg(cxxbridge05$error(other.msg, other.len)), len(other.len) {}
+    : std::exception(other), msg(cxxbridge05$error(other.msg, other.len)),
+      len(other.len) {}
 
-Error::Error(Error &&other) noexcept : msg(other.msg), len(other.len) {
+Error::Error(Error &&other) noexcept
+    : std::exception(std::move(other)), msg(other.msg), len(other.len) {
   other.msg = nullptr;
   other.len = 0;
 }

From 7c6ac7195e06a705011e7d9a96818034f05fe98f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:24:32 +0000
Subject: [PATCH 1117/2232] Add copy assignment operator for Error


---

diff --git a/include/cxx.h b/include/cxx.h
index adbc8e6..d43854c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -257,6 +257,9 @@ public:
   Error(const Error &);
   Error(Error &&) noexcept;
   ~Error() noexcept;
+
+  Error &operator=(const Error &);
+
   const char *what() const noexcept override;
 
 private:
diff --git a/src/cxx.cc b/src/cxx.cc
index 0fba35c..7843b29 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -184,6 +184,17 @@ Error::Error(Error &&other) noexcept
 
 Error::~Error() noexcept { delete[] this->msg; }
 
+Error &Error::operator=(const Error &other) {
+  if (this != &other) {
+    std::exception::operator=(other);
+    delete[] this->msg;
+    this->msg = nullptr;
+    this->msg = cxxbridge05$error(other.msg, other.len);
+    this->len = other.len;
+  }
+  return *this;
+}
+
 const char *Error::what() const noexcept { return this->msg; }
 
 } // namespace cxxbridge05

From 1549106cb02a216c2182e3c75cfc8aad13834d13 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:26:23 +0000
Subject: [PATCH 1118/2232] Add move assignment operator for Error


---

diff --git a/include/cxx.h b/include/cxx.h
index d43854c..c545e50 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -259,6 +259,7 @@ public:
   ~Error() noexcept;
 
   Error &operator=(const Error &);
+  Error &operator=(Error &&) noexcept;
 
   const char *what() const noexcept override;
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 7843b29..722a034 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -195,6 +195,17 @@ Error &Error::operator=(const Error &other) {
   return *this;
 }
 
+Error &Error::operator=(Error &&other) noexcept {
+  if (this != &other) {
+    std::exception::operator=(std::move(other));
+    this->msg = other.msg;
+    this->len = other.len;
+    other.msg = nullptr;
+    other.len = 0;
+  }
+  return *this;
+}
+
 const char *Error::what() const noexcept { return this->msg; }
 
 } // namespace cxxbridge05

From 5df1f06eb8c1b7d01920c18246fe746f292efb5d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:31:44 +0000
Subject: [PATCH 1119/2232] Eliminate Str::Repr struct


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 16bb7cd..10c6b40 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -619,7 +619,6 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             write!(out, "::rust::Slice<uint8_t>::Repr(")
         }
@@ -659,7 +658,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -866,7 +865,6 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::Str::Repr("),
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -875,7 +873,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            Type::SliceRefU8(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -939,7 +937,6 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Type::Str(_) => write!(out, "::rust::Str::Repr"),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
         _ => write_type(out, ty),
     }
@@ -967,7 +964,6 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
@@ -980,7 +976,6 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::rust::Str::Repr "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
diff --git a/include/cxx.h b/include/cxx.h
index c545e50..04a63d6 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -79,19 +79,11 @@ public:
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
 
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
+private:
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
-  struct Repr final {
-    const char *ptr;
-    size_t len;
-  };
-  Str(Repr) noexcept;
-  explicit operator Repr() const noexcept;
-
-private:
-  Repr repr;
+  const char *ptr;
+  size_t len;
 };
 #endif // CXXBRIDGE05_RUST_STR
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 722a034..7e9f57e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -115,33 +115,33 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
+Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
-static void initStr(Str::Repr repr) {
-  if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
+static void initStr(const char *ptr, size_t len) {
+  if (!cxxbridge05$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  initStr(this->repr);
+Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
+  initStr(this->ptr, this->len);
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
   assert(s != nullptr);
-  initStr(this->repr);
+  initStr(this->ptr, this->len);
 }
 
 Str::Str(const char *s, size_t len)
-    : repr(
-          Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
-               len}) {
+    : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
+      len(len) {
   assert(s != nullptr || len == 0);
-  initStr(this->repr);
+  initStr(this->ptr, this->len);
 }
 
 Str &Str::operator=(Str other) noexcept {
-  this->repr = other.repr;
+  this->ptr = other.ptr;
+  this->len = other.len;
   return *this;
 }
 
@@ -149,15 +149,11 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-const char *Str::data() const noexcept { return this->repr.ptr; }
-
-size_t Str::size() const noexcept { return this->repr.len; }
-
-size_t Str::length() const noexcept { return this->repr.len; }
+const char *Str::data() const noexcept { return this->ptr; }
 
-Str::Str(Repr repr_) noexcept : repr(repr_) {}
+size_t Str::size() const noexcept { return this->len; }
 
-Str::operator Repr() const noexcept { return this->repr; }
+size_t Str::length() const noexcept { return this->len; }
 
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 527d709..3d3bf0f 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -18,7 +18,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
 }
 
 #[test]
@@ -28,5 +28,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
 }

From 09d2cd9f375513e96c82a87402c3be1dc2df394f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:43:27 +0000
Subject: [PATCH 1120/2232] Merge pull request #391 from dtolnay/str


Eliminate Str::Repr struct
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 16bb7cd..10c6b40 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -619,7 +619,6 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("),
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             write!(out, "::rust::Slice<uint8_t>::Repr(")
         }
@@ -659,7 +658,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -866,7 +865,6 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::Str::Repr("),
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -875,7 +873,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            Type::SliceRefU8(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -939,7 +937,6 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Type::Str(_) => write!(out, "::rust::Str::Repr"),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
         _ => write_type(out, ty),
     }
@@ -967,7 +964,6 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
@@ -980,7 +976,6 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::rust::Str::Repr "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
diff --git a/include/cxx.h b/include/cxx.h
index c545e50..04a63d6 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -79,19 +79,11 @@ public:
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
 
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
+private:
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
-  struct Repr final {
-    const char *ptr;
-    size_t len;
-  };
-  Str(Repr) noexcept;
-  explicit operator Repr() const noexcept;
-
-private:
-  Repr repr;
+  const char *ptr;
+  size_t len;
 };
 #endif // CXXBRIDGE05_RUST_STR
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 722a034..7e9f57e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -115,33 +115,33 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}
+Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
-static void initStr(Str::Repr repr) {
-  if (!cxxbridge05$str$valid(repr.ptr, repr.len)) {
+static void initStr(const char *ptr, size_t len) {
+  if (!cxxbridge05$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
-  initStr(this->repr);
+Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
+  initStr(this->ptr, this->len);
 }
 
-Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
+Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
   assert(s != nullptr);
-  initStr(this->repr);
+  initStr(this->ptr, this->len);
 }
 
 Str::Str(const char *s, size_t len)
-    : repr(
-          Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
-               len}) {
+    : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
+      len(len) {
   assert(s != nullptr || len == 0);
-  initStr(this->repr);
+  initStr(this->ptr, this->len);
 }
 
 Str &Str::operator=(Str other) noexcept {
-  this->repr = other.repr;
+  this->ptr = other.ptr;
+  this->len = other.len;
   return *this;
 }
 
@@ -149,15 +149,11 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-const char *Str::data() const noexcept { return this->repr.ptr; }
-
-size_t Str::size() const noexcept { return this->repr.len; }
-
-size_t Str::length() const noexcept { return this->repr.len; }
+const char *Str::data() const noexcept { return this->ptr; }
 
-Str::Str(Repr repr_) noexcept : repr(repr_) {}
+size_t Str::size() const noexcept { return this->len; }
 
-Str::operator Repr() const noexcept { return this->repr; }
+size_t Str::length() const noexcept { return this->len; }
 
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 527d709..3d3bf0f 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -18,7 +18,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
 }
 
 #[test]
@@ -28,5 +28,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str::Repr foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
 }

From 2d7f1174944fade92075e0402d3924371d24a0b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 00:58:31 +0000
Subject: [PATCH 1121/2232] Make Str, Slice trivially copy assignable


---

diff --git a/include/cxx.h b/include/cxx.h
index 04a63d6..3499fec 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -66,7 +66,7 @@ public:
   Str(const char *, size_t);
   Str(std::string &&) = delete;
 
-  Str &operator=(Str) noexcept;
+  Str &operator=(const Str &) noexcept = default;
 
   explicit operator std::string() const;
 
@@ -94,7 +94,7 @@ public:
   Slice() noexcept;
   Slice(const T *, size_t count) noexcept;
 
-  Slice &operator=(Slice<T>) noexcept;
+  Slice &operator=(const Slice<T> &) noexcept = default;
 
   const T *data() const noexcept;
   size_t size() const noexcept;
@@ -329,12 +329,6 @@ template <typename T>
 Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
 
 template <typename T>
-Slice<T> &Slice<T>::operator=(Slice<T> other) noexcept {
-  this->repr = other.repr;
-  return *this;
-}
-
-template <typename T>
 const T *Slice<T>::data() const noexcept {
   return this->repr.ptr;
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index 7e9f57e..d423ab7 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -139,12 +139,6 @@ Str::Str(const char *s, size_t len)
   initStr(this->ptr, this->len);
 }
 
-Str &Str::operator=(Str other) noexcept {
-  this->ptr = other.ptr;
-  this->len = other.len;
-  return *this;
-}
-
 Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }

From 9ed15c6f692d4fc471e128499d8247c1b144242e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 01:02:03 +0000
Subject: [PATCH 1122/2232] Add static assertions for Str trivial operations


---

diff --git a/src/cxx.cc b/src/cxx.cc
index d423ab7..08ad3ce 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -5,6 +5,7 @@
 #include <iostream>
 #include <memory>
 #include <stdexcept>
+#include <type_traits>
 #include <vector>
 
 extern "C" {
@@ -154,6 +155,12 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+static_assert(std::is_trivially_copy_constructible<Str>::value,
+              "trivial Str(const Str &)");
+static_assert(std::is_trivially_copy_assignable<Str>::value,
+              "trivial operator=(const Str &)");
+static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
+
 extern "C" {
 const char *cxxbridge05$error(const char *ptr, size_t len) {
   char *copy = new char[len];

From 5b1ee1fc4e4606772ab7dce6bbc9011c483072ea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 01:21:39 +0000
Subject: [PATCH 1123/2232] Inline some Str accessors into the header


---

diff --git a/include/cxx.h b/include/cxx.h
index 3499fec..de614d1 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -57,7 +57,6 @@ private:
 #endif // CXXBRIDGE05_RUST_STRING
 
 #ifndef CXXBRIDGE05_RUST_STR
-#define CXXBRIDGE05_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -320,6 +319,15 @@ struct unsafe_bitcopy_t final {
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE05_RUST_BITCOPY
 
+#ifndef CXXBRIDGE05_RUST_STR
+#define CXXBRIDGE05_RUST_STR
+inline const char *Str::data() const noexcept { return this->ptr; }
+
+inline size_t Str::size() const noexcept { return this->len; }
+
+inline size_t Str::length() const noexcept { return this->len; }
+#endif // CXXBRIDGE05_RUST_STR
+
 #ifndef CXXBRIDGE05_RUST_SLICE
 #define CXXBRIDGE05_RUST_SLICE
 template <typename T>
diff --git a/src/cxx.cc b/src/cxx.cc
index 08ad3ce..5877b35 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -144,12 +144,6 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-const char *Str::data() const noexcept { return this->ptr; }
-
-size_t Str::size() const noexcept { return this->len; }
-
-size_t Str::length() const noexcept { return this->len; }
-
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From 54742b7ced559bac4eba72b45ae0c57905ae4215 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 02:43:25 +0000
Subject: [PATCH 1124/2232] Make PtrLen usable for non-char data


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 10c6b40..a06ab62 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -327,7 +327,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     if needs_trycatch || needs_rust_error {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const char *ptr;");
+        writeln!(out, "  const void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
         out.end_block("namespace repr");
@@ -339,7 +339,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "public:");
         writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
         writeln!(out, "    Error error;");
-        writeln!(out, "    error.msg = repr.ptr;");
+        writeln!(out, "    error.msg = static_cast<const char *>(repr.ptr);");
         writeln!(out, "    error.len = repr.len;");
         writeln!(out, "    return error;");
         writeln!(out, "  }}");

From 0356d33acbcee50f41aa8e44157d64b08522bcce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 03:33:39 +0000
Subject: [PATCH 1125/2232] Pass Str in PtrLen representation


MSVC is hesitant about passing private fields in an extern "C" signature.
Repro:

    struct Str1 {
      const char *ptr;
      size_t len;
    };

    struct Str2 {
    private:
      const char *ptr;
      size_t len;
    };

    extern "C" {
      Str1 str1();
      Str2 str2();
    }

Warning from MSVC v19.27:

    warning C4190: 'str2' has C-linkage specified, but returns UDT 'Str2' which is incompatible with C

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index a06ab62..e3e9221 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -324,7 +324,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
 
     out.begin_block("namespace");
 
-    if needs_trycatch || needs_rust_error {
+    if needs_trycatch || needs_rust_error || needs_rust_str && !out.header {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
@@ -333,7 +333,28 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         out.end_block("namespace repr");
     }
 
+    if needs_rust_str && !out.header {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Str> final {{");
+        writeln!(out, "public:");
+        writeln!(
+            out,
+            "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
+        );
+        writeln!(out, "    Str str;");
+        writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
+        writeln!(out, "    str.len = repr.len;");
+        writeln!(out, "    return str;");
+        writeln!(out, "  }}");
+        writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
+        writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+        writeln!(out, "  }}");
+        writeln!(out, "}};");
+    }
+
     if needs_rust_error {
+        out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Error> final {{");
         writeln!(out, "public:");
@@ -619,6 +640,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
+        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::impl<::rust::Str>::repr("),
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             write!(out, "::rust::Slice<uint8_t>::Repr(")
         }
@@ -638,6 +660,12 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
         } else if let Type::UniquePtr(_) = &arg.ty {
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
+        } else if let Type::Str(_) = arg.ty {
+            write!(
+                out,
+                "::rust::impl<::rust::Str>::new_unchecked({})",
+                arg.ident,
+            );
         } else if arg.ty == RustString {
             write!(
                 out,
@@ -658,7 +686,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -850,6 +878,7 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
+            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::new_unchecked("),
             _ => {}
         }
     }
@@ -865,6 +894,7 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
+            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::repr("),
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -873,7 +903,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::SliceRefU8(_) => write!(out, ")"),
+            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -893,7 +923,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) = ret {
                 write!(out, ")");
             }
         }
@@ -964,6 +994,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
+        Some(Type::Str(_)) => write!(out, "::rust::repr::PtrLen "),
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
@@ -976,6 +1007,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
+        Type::Str(_) => write!(out, "::rust::repr::PtrLen "),
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
diff --git a/include/cxx.h b/include/cxx.h
index de614d1..220f45f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -79,6 +79,7 @@ public:
   ~Str() noexcept = default;
 
 private:
+  friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 3d3bf0f..1818af4 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -18,7 +18,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
+    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::repr::PtrLen foo)"));
 }
 
 #[test]
@@ -28,5 +28,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::Str foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::repr::PtrLen foo)"));
 }

From a4eb943093a1e522650d4601dab79eeee063b947 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 03:36:38 +0000
Subject: [PATCH 1126/2232] Write impl<Str> more selectively


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index e3e9221..cadeb4e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -214,20 +214,21 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     let mut needs_manually_drop = false;
     let mut needs_maybe_uninit = false;
     let mut needs_trycatch = false;
+    let mut needs_rust_str_new_unchecked = false;
+    let mut needs_rust_str_repr = false;
     for api in apis {
         match api {
             Api::CxxFunction(efn) if !out.header => {
                 if efn.throws {
                     needs_trycatch = true;
+                } else if let Some(Type::Str(_)) = efn.ret {
+                    needs_rust_str_repr = true;
                 }
                 for arg in &efn.args {
-                    let bitcopy = match arg.ty {
-                        Type::RustVec(_) => true,
-                        _ => arg.ty == RustString,
-                    };
-                    if bitcopy {
-                        needs_unsafe_bitcopy = true;
-                        break;
+                    match arg.ty {
+                        Type::Str(_) => needs_rust_str_new_unchecked = true,
+                        Type::RustVec(_) => needs_unsafe_bitcopy = true,
+                        _ => needs_unsafe_bitcopy |= arg.ty == RustString,
                     }
                 }
             }
@@ -242,12 +243,16 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
                 for arg in &efn.args {
                     if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
                         needs_manually_drop = true;
-                        break;
+                    }
+                    if let Type::Str(_) = arg.ty {
+                        needs_rust_str_repr = true;
                     }
                 }
                 if let Some(ret) = &efn.ret {
                     if out.types.needs_indirect_abi(ret) {
                         needs_maybe_uninit = true;
+                    } else if let Type::Str(_) = ret {
+                        needs_rust_str_new_unchecked = true;
                     }
                 }
             }
@@ -324,7 +329,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
 
     out.begin_block("namespace");
 
-    if needs_trycatch || needs_rust_error || needs_rust_str && !out.header {
+    if needs_trycatch || needs_rust_error || needs_rust_str_new_unchecked || needs_rust_str_repr {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
@@ -333,23 +338,27 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         out.end_block("namespace repr");
     }
 
-    if needs_rust_str && !out.header {
+    if needs_rust_str_new_unchecked || needs_rust_str_repr {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Str> final {{");
         writeln!(out, "public:");
-        writeln!(
-            out,
-            "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
-        );
-        writeln!(out, "    Str str;");
-        writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
-        writeln!(out, "    str.len = repr.len;");
-        writeln!(out, "    return str;");
-        writeln!(out, "  }}");
-        writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-        writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
-        writeln!(out, "  }}");
+        if needs_rust_str_new_unchecked {
+            writeln!(
+                out,
+                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
+            );
+            writeln!(out, "    Str str;");
+            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
+            writeln!(out, "    str.len = repr.len;");
+            writeln!(out, "    return str;");
+            writeln!(out, "  }}");
+        }
+        if needs_rust_str_repr {
+            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
+            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(out, "  }}");
+        }
         writeln!(out, "}};");
     }
 

From 630af887178ee02c9f2671efcb085759920aa6c7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:03:47 +0000
Subject: [PATCH 1127/2232] Clean up unneeded explicit iter()


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index cadeb4e..e612bee 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -54,7 +54,7 @@ fn gen_namespace_contents(
     let apis = ns_entries.entries();
 
     out.next_section();
-    for api in apis.iter() {
+    for api in apis {
         match api {
             Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
@@ -64,7 +64,7 @@ fn gen_namespace_contents(
     }
 
     let mut methods_for_type = HashMap::new();
-    for api in apis.iter() {
+    for api in apis {
         if let Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type

From 9238b706a86a14753123d44f6736ac1f1d4ff7be Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Nov 01 2020 05:15:24 +0000
Subject: [PATCH 1128/2232] Test for namespace order sensitivity.


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fee5bcb..c79aff3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -101,6 +101,16 @@ pub mod ffi {
         z: usize,
     }
 
+    #[namespace = "first"]
+    struct First {
+        second: Box<Second>,
+    }
+
+    #[namespace = "second"]
+    struct Second {
+        i: i32,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 

From f9213628a58e891f27032244ab0cdd0b3a3d269d Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Nov 01 2020 05:25:42 +0000
Subject: [PATCH 1129/2232] Fix namespace forward declarations.


This fixes the case where a lexicographically early namespace
has a reference to a type in a lexicographically later namespace.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index f259222..dfdade2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -32,6 +32,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     let apis_by_namespace = NamespaceEntries::new(apis);
 
+    gen_namespace_forward_declarations(&apis_by_namespace, out);
     gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
 
     if !header {
@@ -44,13 +45,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     out_file
 }
 
-fn gen_namespace_contents(
-    ns_entries: &NamespaceEntries,
-    types: &Types,
-    opt: &Opt,
-    header: bool,
-    out: &mut OutFile,
-) {
+fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut OutFile) {
     let apis = ns_entries.entries();
 
     out.next_section();
@@ -63,6 +58,24 @@ fn gen_namespace_contents(
         }
     }
 
+    out.next_section();
+
+    for (child_ns, child_ns_entries) in ns_entries.children() {
+        writeln!(out, "namespace {} {{", child_ns);
+        gen_namespace_forward_declarations(&child_ns_entries, out);
+        writeln!(out, "}} // namespace {}", child_ns);
+    }
+}
+
+fn gen_namespace_contents(
+    ns_entries: &NamespaceEntries,
+    types: &Types,
+    opt: &Opt,
+    header: bool,
+    out: &mut OutFile,
+) {
+    let apis = ns_entries.entries();
+
     let mut methods_for_type = HashMap::new();
     for api in apis.iter() {
         if let Api::RustFunction(efn) = api {

From 0aa9c773a1d298126ea0972fe33a2b52b92dfbc2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:39:47 +0000
Subject: [PATCH 1130/2232] Merge pull request #392 from adetaylor/namespace-forward-declarations


Namespace forward declarations
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index e612bee..99d5e7d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -32,6 +32,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     let apis_by_namespace = NamespaceEntries::new(apis);
 
+    gen_namespace_forward_declarations(&apis_by_namespace, out);
     gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
 
     if !header {
@@ -44,13 +45,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     out_file
 }
 
-fn gen_namespace_contents(
-    ns_entries: &NamespaceEntries,
-    types: &Types,
-    opt: &Opt,
-    header: bool,
-    out: &mut OutFile,
-) {
+fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut OutFile) {
     let apis = ns_entries.entries();
 
     out.next_section();
@@ -63,6 +58,24 @@ fn gen_namespace_contents(
         }
     }
 
+    out.next_section();
+
+    for (child_ns, child_ns_entries) in ns_entries.children() {
+        writeln!(out, "namespace {} {{", child_ns);
+        gen_namespace_forward_declarations(&child_ns_entries, out);
+        writeln!(out, "}} // namespace {}", child_ns);
+    }
+}
+
+fn gen_namespace_contents(
+    ns_entries: &NamespaceEntries,
+    types: &Types,
+    opt: &Opt,
+    header: bool,
+    out: &mut OutFile,
+) {
+    let apis = ns_entries.entries();
+
     let mut methods_for_type = HashMap::new();
     for api in apis {
         if let Api::RustFunction(efn) = api {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fee5bcb..c79aff3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -101,6 +101,16 @@ pub mod ffi {
         z: usize,
     }
 
+    #[namespace = "first"]
+    struct First {
+        second: Box<Second>,
+    }
+
+    #[namespace = "second"]
+    struct Second {
+        i: i32,
+    }
+
     extern "C" {
         include!("tests/ffi/tests.h");
 

From 4d14842342254c297968bfef3ae1ad4d6c3141fb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:41:37 +0000
Subject: [PATCH 1131/2232] Remove unneeded Types parameter


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 99d5e7d..96e235f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -33,7 +33,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     let apis_by_namespace = NamespaceEntries::new(apis);
 
     gen_namespace_forward_declarations(&apis_by_namespace, out);
-    gen_namespace_contents(&apis_by_namespace, types, opt, header, out);
+    gen_namespace_contents(&apis_by_namespace, opt, header, out);
 
     if !header {
         out.next_section();
@@ -69,7 +69,6 @@ fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut O
 
 fn gen_namespace_contents(
     ns_entries: &NamespaceEntries,
-    types: &Types,
     opt: &Opt,
     header: bool,
     out: &mut OutFile,
@@ -92,13 +91,13 @@ fn gen_namespace_contents(
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                if !types.cxx.contains(&strct.ident.rust) {
+                if !out.types.cxx.contains(&strct.ident.rust) {
                     write_struct(out, strct);
                 }
             }
             Api::Enum(enm) => {
                 out.next_section();
-                if types.cxx.contains(&enm.ident.rust) {
+                if out.types.cxx.contains(&enm.ident.rust) {
                     check_enum(out, enm);
                 } else {
                     write_enum(out, enm);
@@ -117,7 +116,7 @@ fn gen_namespace_contents(
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if types.required_trivial.contains_key(&ety.ident.rust) {
+            if out.types.required_trivial.contains_key(&ety.ident.rust) {
                 check_trivial_extern_type(out, &ety.ident.cxx)
             }
         }
@@ -149,7 +148,7 @@ fn gen_namespace_contents(
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_contents(&child_ns_entries, types, opt, header, out);
+        gen_namespace_contents(&child_ns_entries, opt, header, out);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }

From ce5a91f21467bd983e9b39f52237b526de57e88d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:42:08 +0000
Subject: [PATCH 1132/2232] Remove unneeded header parameter


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 96e235f..809a3af 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -33,7 +33,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     let apis_by_namespace = NamespaceEntries::new(apis);
 
     gen_namespace_forward_declarations(&apis_by_namespace, out);
-    gen_namespace_contents(&apis_by_namespace, opt, header, out);
+    gen_namespace_contents(&apis_by_namespace, opt, out);
 
     if !header {
         out.next_section();
@@ -67,12 +67,7 @@ fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut O
     }
 }
 
-fn gen_namespace_contents(
-    ns_entries: &NamespaceEntries,
-    opt: &Opt,
-    header: bool,
-    out: &mut OutFile,
-) {
+fn gen_namespace_contents(ns_entries: &NamespaceEntries, opt: &Opt, out: &mut OutFile) {
     let apis = ns_entries.entries();
 
     let mut methods_for_type = HashMap::new();
@@ -122,7 +117,7 @@ fn gen_namespace_contents(
         }
     }
 
-    if !header {
+    if !out.header {
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
@@ -148,7 +143,7 @@ fn gen_namespace_contents(
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_contents(&child_ns_entries, opt, header, out);
+        gen_namespace_contents(&child_ns_entries, opt, out);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }

From 04b8165b8c85c4815cadb7983daa13fa4ee4dcc0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:43:25 +0000
Subject: [PATCH 1133/2232] Keep OutFile consistently the first parameter


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 809a3af..4549c21 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -32,8 +32,8 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     let apis_by_namespace = NamespaceEntries::new(apis);
 
-    gen_namespace_forward_declarations(&apis_by_namespace, out);
-    gen_namespace_contents(&apis_by_namespace, opt, out);
+    gen_namespace_forward_declarations(out, &apis_by_namespace);
+    gen_namespace_contents(out, &apis_by_namespace, opt);
 
     if !header {
         out.next_section();
@@ -45,7 +45,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     out_file
 }
 
-fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut OutFile) {
+fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     let apis = ns_entries.entries();
 
     out.next_section();
@@ -62,12 +62,12 @@ fn gen_namespace_forward_declarations(ns_entries: &NamespaceEntries, out: &mut O
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_forward_declarations(&child_ns_entries, out);
+        gen_namespace_forward_declarations(out, &child_ns_entries);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }
 
-fn gen_namespace_contents(ns_entries: &NamespaceEntries, opt: &Opt, out: &mut OutFile) {
+fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt: &Opt) {
     let apis = ns_entries.entries();
 
     let mut methods_for_type = HashMap::new();
@@ -143,7 +143,7 @@ fn gen_namespace_contents(ns_entries: &NamespaceEntries, opt: &Opt, out: &mut Ou
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_contents(&child_ns_entries, opt, out);
+        gen_namespace_contents(out, &child_ns_entries, opt);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }

From ef0473a6287842cb267d49a4cf5a8970c7749d36 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:44:55 +0000
Subject: [PATCH 1134/2232] Clean up redundant child_ns_entries borrows


NamespaceEntries::children returns an iterator of (&Ident, &NamespaceEntries)
so these child_ns_entries are already borrows.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4549c21..6ee6ad7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -62,7 +62,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_forward_declarations(out, &child_ns_entries);
+        gen_namespace_forward_declarations(out, child_ns_entries);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }
@@ -143,7 +143,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
 
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_contents(out, &child_ns_entries, opt);
+        gen_namespace_contents(out, child_ns_entries, opt);
         writeln!(out, "}} // namespace {}", child_ns);
     }
 }

From 3be0e1f53bd4fcc35caaed794c018204e83873e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:46:29 +0000
Subject: [PATCH 1135/2232] Move builtin tracking bools to module


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
new file mode 100644
index 0000000..a120eef
--- /dev/null
+++ b/gen/src/builtin.rs
@@ -0,0 +1,24 @@
+#[derive(Default, PartialEq)]
+pub struct Builtins {
+    pub panic: bool,
+    pub rust_string: bool,
+    pub rust_str: bool,
+    pub rust_slice: bool,
+    pub rust_box: bool,
+    pub rust_vec: bool,
+    pub rust_fn: bool,
+    pub rust_isize: bool,
+    pub unsafe_bitcopy: bool,
+    pub rust_error: bool,
+    pub manually_drop: bool,
+    pub maybe_uninit: bool,
+    pub trycatch: bool,
+    pub rust_str_new_unchecked: bool,
+    pub rust_str_repr: bool,
+}
+
+impl Builtins {
+    pub fn new() -> Self {
+        Builtins::default()
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index e6e2c7c..e969dec 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
+mod builtin;
 mod check;
 pub(super) mod error;
 mod file;
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 94a54e4..055f199 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,3 +1,4 @@
+use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::syntax::Types;
 use std::cell::RefCell;
@@ -7,6 +8,7 @@ pub(crate) struct OutFile<'a> {
     pub header: bool,
     pub types: &'a Types<'a>,
     pub include: Includes,
+    pub builtin: Builtins,
     pub front: Content,
     content: RefCell<Content>,
 }
@@ -23,6 +25,7 @@ impl<'a> OutFile<'a> {
             header,
             types,
             include: Includes::new(),
+            builtin: Builtins::new(),
             front: Content::new(),
             content: RefCell::new(Content::new()),
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6ee6ad7..e638410 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -168,74 +168,59 @@ fn write_includes(out: &mut OutFile) {
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
-    let mut needs_panic = false;
-    let mut needs_rust_string = false;
-    let mut needs_rust_str = false;
-    let mut needs_rust_slice = false;
-    let mut needs_rust_box = false;
-    let mut needs_rust_vec = false;
-    let mut needs_rust_fn = false;
-    let mut needs_rust_isize = false;
-    let mut needs_unsafe_bitcopy = false;
     for ty in out.types {
         match ty {
             Type::RustBox(_) => {
                 out.include.new = true;
                 out.include.type_traits = true;
-                needs_rust_box = true;
+                out.builtin.rust_box = true;
             }
             Type::RustVec(_) => {
                 out.include.array = true;
                 out.include.new = true;
                 out.include.type_traits = true;
-                needs_panic = true;
-                needs_rust_vec = true;
-                needs_unsafe_bitcopy = true;
+                out.builtin.panic = true;
+                out.builtin.rust_vec = true;
+                out.builtin.unsafe_bitcopy = true;
             }
             Type::Str(_) => {
                 out.include.cstdint = true;
                 out.include.string = true;
-                needs_rust_str = true;
+                out.builtin.rust_str = true;
             }
             Type::Fn(_) => {
-                needs_rust_fn = true;
+                out.builtin.rust_fn = true;
             }
             Type::Slice(_) | Type::SliceRefU8(_) => {
-                needs_rust_slice = true;
+                out.builtin.rust_slice = true;
             }
             ty if ty == Isize => {
                 out.include.basetsd = true;
-                needs_rust_isize = true;
+                out.builtin.rust_isize = true;
             }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
                 out.include.string = true;
-                needs_rust_string = true;
+                out.builtin.rust_string = true;
             }
             _ => {}
         }
     }
 
-    let mut needs_rust_error = false;
-    let mut needs_manually_drop = false;
-    let mut needs_maybe_uninit = false;
-    let mut needs_trycatch = false;
-    let mut needs_rust_str_new_unchecked = false;
-    let mut needs_rust_str_repr = false;
     for api in apis {
         match api {
             Api::CxxFunction(efn) if !out.header => {
                 if efn.throws {
-                    needs_trycatch = true;
+                    out.builtin.trycatch = true;
                 } else if let Some(Type::Str(_)) = efn.ret {
-                    needs_rust_str_repr = true;
+                    out.builtin.rust_str_repr = true;
                 }
                 for arg in &efn.args {
                     match arg.ty {
-                        Type::Str(_) => needs_rust_str_new_unchecked = true,
-                        Type::RustVec(_) => needs_unsafe_bitcopy = true,
-                        _ => needs_unsafe_bitcopy |= arg.ty == RustString,
+                        Type::Str(_) => out.builtin.rust_str_new_unchecked = true,
+                        Type::RustVec(_) => out.builtin.unsafe_bitcopy = true,
+                        _ => out.builtin.unsafe_bitcopy |= arg.ty == RustString,
                     }
                 }
             }
@@ -243,23 +228,23 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
                 if efn.throws {
                     out.include.exception = true;
                     out.include.string = true;
-                    needs_rust_str = true;
-                    needs_rust_error = true;
-                    needs_maybe_uninit = true;
+                    out.builtin.rust_str = true;
+                    out.builtin.rust_error = true;
+                    out.builtin.maybe_uninit = true;
                 }
                 for arg in &efn.args {
                     if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
-                        needs_manually_drop = true;
+                        out.builtin.manually_drop = true;
                     }
                     if let Type::Str(_) = arg.ty {
-                        needs_rust_str_repr = true;
+                        out.builtin.rust_str_repr = true;
                     }
                 }
                 if let Some(ret) = &efn.ret {
                     if out.types.needs_indirect_abi(ret) {
-                        needs_maybe_uninit = true;
+                        out.builtin.maybe_uninit = true;
                     } else if let Type::Str(_) = ret {
-                        needs_rust_str_new_unchecked = true;
+                        out.builtin.rust_str_new_unchecked = true;
                     }
                 }
             }
@@ -270,47 +255,35 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");
 
-    if needs_panic
-        || needs_rust_string
-        || needs_rust_str
-        || needs_rust_slice
-        || needs_rust_box
-        || needs_rust_vec
-        || needs_rust_fn
-        || needs_rust_error
-        || needs_rust_isize
-        || needs_unsafe_bitcopy
-        || needs_manually_drop
-        || needs_maybe_uninit
-    {
+    if out.builtin != Default::default() {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    include::write(out, needs_panic, "CXXBRIDGE05_PANIC");
+    include::write(out, out.builtin.panic, "CXXBRIDGE05_PANIC");
 
-    if needs_rust_string {
+    if out.builtin.rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    if needs_rust_error {
+    if out.builtin.rust_error {
         out.begin_block("namespace");
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");
         out.end_block("namespace");
     }
 
-    include::write(out, needs_rust_string, "CXXBRIDGE05_RUST_STRING");
-    include::write(out, needs_rust_str, "CXXBRIDGE05_RUST_STR");
-    include::write(out, needs_rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    include::write(out, needs_rust_box, "CXXBRIDGE05_RUST_BOX");
-    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    include::write(out, needs_rust_vec, "CXXBRIDGE05_RUST_VEC");
-    include::write(out, needs_rust_fn, "CXXBRIDGE05_RUST_FN");
-    include::write(out, needs_rust_error, "CXXBRIDGE05_RUST_ERROR");
-    include::write(out, needs_rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    include::write(out, out.builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    include::write(out, out.builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    include::write(out, out.builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    include::write(out, out.builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    include::write(out, out.builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    include::write(out, out.builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    include::write(out, out.builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    include::write(out, out.builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    include::write(out, out.builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
 
-    if needs_manually_drop {
+    if out.builtin.manually_drop {
         out.next_section();
         out.include.utility = true;
         writeln!(out, "template <typename T>");
@@ -324,7 +297,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
-    if needs_maybe_uninit {
+    if out.builtin.maybe_uninit {
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "union MaybeUninit {{");
@@ -336,7 +309,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
 
     out.begin_block("namespace");
 
-    if needs_trycatch || needs_rust_error || needs_rust_str_new_unchecked || needs_rust_str_repr {
+    if out.builtin.trycatch
+        || out.builtin.rust_error
+        || out.builtin.rust_str_new_unchecked
+        || out.builtin.rust_str_repr
+    {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
@@ -345,12 +322,12 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         out.end_block("namespace repr");
     }
 
-    if needs_rust_str_new_unchecked || needs_rust_str_repr {
+    if out.builtin.rust_str_new_unchecked || out.builtin.rust_str_repr {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Str> final {{");
         writeln!(out, "public:");
-        if needs_rust_str_new_unchecked {
+        if out.builtin.rust_str_new_unchecked {
             writeln!(
                 out,
                 "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
@@ -361,7 +338,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
             writeln!(out, "    return str;");
             writeln!(out, "  }}");
         }
-        if needs_rust_str_repr {
+        if out.builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
             writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
             writeln!(out, "  }}");
@@ -369,7 +346,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
-    if needs_rust_error {
+    if out.builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Error> final {{");
@@ -386,7 +363,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     out.end_block("namespace");
     out.end_block("namespace cxxbridge05");
 
-    if needs_trycatch {
+    if out.builtin.trycatch {
         out.begin_block("namespace behavior");
         out.include.exception = true;
         out.include.type_traits = true;

From d5a5f447e110a52ea422430f302d8fa37be4a9e4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:55:53 +0000
Subject: [PATCH 1136/2232] Merge pull request #393 from dtolnay/builtin


Move builtin tracking bools to module
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
new file mode 100644
index 0000000..a120eef
--- /dev/null
+++ b/gen/src/builtin.rs
@@ -0,0 +1,24 @@
+#[derive(Default, PartialEq)]
+pub struct Builtins {
+    pub panic: bool,
+    pub rust_string: bool,
+    pub rust_str: bool,
+    pub rust_slice: bool,
+    pub rust_box: bool,
+    pub rust_vec: bool,
+    pub rust_fn: bool,
+    pub rust_isize: bool,
+    pub unsafe_bitcopy: bool,
+    pub rust_error: bool,
+    pub manually_drop: bool,
+    pub maybe_uninit: bool,
+    pub trycatch: bool,
+    pub rust_str_new_unchecked: bool,
+    pub rust_str_repr: bool,
+}
+
+impl Builtins {
+    pub fn new() -> Self {
+        Builtins::default()
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index e6e2c7c..e969dec 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
+mod builtin;
 mod check;
 pub(super) mod error;
 mod file;
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 94a54e4..055f199 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,3 +1,4 @@
+use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::syntax::Types;
 use std::cell::RefCell;
@@ -7,6 +8,7 @@ pub(crate) struct OutFile<'a> {
     pub header: bool,
     pub types: &'a Types<'a>,
     pub include: Includes,
+    pub builtin: Builtins,
     pub front: Content,
     content: RefCell<Content>,
 }
@@ -23,6 +25,7 @@ impl<'a> OutFile<'a> {
             header,
             types,
             include: Includes::new(),
+            builtin: Builtins::new(),
             front: Content::new(),
             content: RefCell::new(Content::new()),
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6ee6ad7..e638410 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -168,74 +168,59 @@ fn write_includes(out: &mut OutFile) {
 }
 
 fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
-    let mut needs_panic = false;
-    let mut needs_rust_string = false;
-    let mut needs_rust_str = false;
-    let mut needs_rust_slice = false;
-    let mut needs_rust_box = false;
-    let mut needs_rust_vec = false;
-    let mut needs_rust_fn = false;
-    let mut needs_rust_isize = false;
-    let mut needs_unsafe_bitcopy = false;
     for ty in out.types {
         match ty {
             Type::RustBox(_) => {
                 out.include.new = true;
                 out.include.type_traits = true;
-                needs_rust_box = true;
+                out.builtin.rust_box = true;
             }
             Type::RustVec(_) => {
                 out.include.array = true;
                 out.include.new = true;
                 out.include.type_traits = true;
-                needs_panic = true;
-                needs_rust_vec = true;
-                needs_unsafe_bitcopy = true;
+                out.builtin.panic = true;
+                out.builtin.rust_vec = true;
+                out.builtin.unsafe_bitcopy = true;
             }
             Type::Str(_) => {
                 out.include.cstdint = true;
                 out.include.string = true;
-                needs_rust_str = true;
+                out.builtin.rust_str = true;
             }
             Type::Fn(_) => {
-                needs_rust_fn = true;
+                out.builtin.rust_fn = true;
             }
             Type::Slice(_) | Type::SliceRefU8(_) => {
-                needs_rust_slice = true;
+                out.builtin.rust_slice = true;
             }
             ty if ty == Isize => {
                 out.include.basetsd = true;
-                needs_rust_isize = true;
+                out.builtin.rust_isize = true;
             }
             ty if ty == RustString => {
                 out.include.array = true;
                 out.include.cstdint = true;
                 out.include.string = true;
-                needs_rust_string = true;
+                out.builtin.rust_string = true;
             }
             _ => {}
         }
     }
 
-    let mut needs_rust_error = false;
-    let mut needs_manually_drop = false;
-    let mut needs_maybe_uninit = false;
-    let mut needs_trycatch = false;
-    let mut needs_rust_str_new_unchecked = false;
-    let mut needs_rust_str_repr = false;
     for api in apis {
         match api {
             Api::CxxFunction(efn) if !out.header => {
                 if efn.throws {
-                    needs_trycatch = true;
+                    out.builtin.trycatch = true;
                 } else if let Some(Type::Str(_)) = efn.ret {
-                    needs_rust_str_repr = true;
+                    out.builtin.rust_str_repr = true;
                 }
                 for arg in &efn.args {
                     match arg.ty {
-                        Type::Str(_) => needs_rust_str_new_unchecked = true,
-                        Type::RustVec(_) => needs_unsafe_bitcopy = true,
-                        _ => needs_unsafe_bitcopy |= arg.ty == RustString,
+                        Type::Str(_) => out.builtin.rust_str_new_unchecked = true,
+                        Type::RustVec(_) => out.builtin.unsafe_bitcopy = true,
+                        _ => out.builtin.unsafe_bitcopy |= arg.ty == RustString,
                     }
                 }
             }
@@ -243,23 +228,23 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
                 if efn.throws {
                     out.include.exception = true;
                     out.include.string = true;
-                    needs_rust_str = true;
-                    needs_rust_error = true;
-                    needs_maybe_uninit = true;
+                    out.builtin.rust_str = true;
+                    out.builtin.rust_error = true;
+                    out.builtin.maybe_uninit = true;
                 }
                 for arg in &efn.args {
                     if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
-                        needs_manually_drop = true;
+                        out.builtin.manually_drop = true;
                     }
                     if let Type::Str(_) = arg.ty {
-                        needs_rust_str_repr = true;
+                        out.builtin.rust_str_repr = true;
                     }
                 }
                 if let Some(ret) = &efn.ret {
                     if out.types.needs_indirect_abi(ret) {
-                        needs_maybe_uninit = true;
+                        out.builtin.maybe_uninit = true;
                     } else if let Type::Str(_) = ret {
-                        needs_rust_str_new_unchecked = true;
+                        out.builtin.rust_str_new_unchecked = true;
                     }
                 }
             }
@@ -270,47 +255,35 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");
 
-    if needs_panic
-        || needs_rust_string
-        || needs_rust_str
-        || needs_rust_slice
-        || needs_rust_box
-        || needs_rust_vec
-        || needs_rust_fn
-        || needs_rust_error
-        || needs_rust_isize
-        || needs_unsafe_bitcopy
-        || needs_manually_drop
-        || needs_maybe_uninit
-    {
+    if out.builtin != Default::default() {
         writeln!(out, "// #include \"rust/cxx.h\"");
     }
 
-    include::write(out, needs_panic, "CXXBRIDGE05_PANIC");
+    include::write(out, out.builtin.panic, "CXXBRIDGE05_PANIC");
 
-    if needs_rust_string {
+    if out.builtin.rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    if needs_rust_error {
+    if out.builtin.rust_error {
         out.begin_block("namespace");
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");
         out.end_block("namespace");
     }
 
-    include::write(out, needs_rust_string, "CXXBRIDGE05_RUST_STRING");
-    include::write(out, needs_rust_str, "CXXBRIDGE05_RUST_STR");
-    include::write(out, needs_rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    include::write(out, needs_rust_box, "CXXBRIDGE05_RUST_BOX");
-    include::write(out, needs_unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    include::write(out, needs_rust_vec, "CXXBRIDGE05_RUST_VEC");
-    include::write(out, needs_rust_fn, "CXXBRIDGE05_RUST_FN");
-    include::write(out, needs_rust_error, "CXXBRIDGE05_RUST_ERROR");
-    include::write(out, needs_rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    include::write(out, out.builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    include::write(out, out.builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    include::write(out, out.builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    include::write(out, out.builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    include::write(out, out.builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    include::write(out, out.builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    include::write(out, out.builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    include::write(out, out.builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    include::write(out, out.builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
 
-    if needs_manually_drop {
+    if out.builtin.manually_drop {
         out.next_section();
         out.include.utility = true;
         writeln!(out, "template <typename T>");
@@ -324,7 +297,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
-    if needs_maybe_uninit {
+    if out.builtin.maybe_uninit {
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "union MaybeUninit {{");
@@ -336,7 +309,11 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
 
     out.begin_block("namespace");
 
-    if needs_trycatch || needs_rust_error || needs_rust_str_new_unchecked || needs_rust_str_repr {
+    if out.builtin.trycatch
+        || out.builtin.rust_error
+        || out.builtin.rust_str_new_unchecked
+        || out.builtin.rust_str_repr
+    {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
@@ -345,12 +322,12 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         out.end_block("namespace repr");
     }
 
-    if needs_rust_str_new_unchecked || needs_rust_str_repr {
+    if out.builtin.rust_str_new_unchecked || out.builtin.rust_str_repr {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Str> final {{");
         writeln!(out, "public:");
-        if needs_rust_str_new_unchecked {
+        if out.builtin.rust_str_new_unchecked {
             writeln!(
                 out,
                 "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
@@ -361,7 +338,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
             writeln!(out, "    return str;");
             writeln!(out, "  }}");
         }
-        if needs_rust_str_repr {
+        if out.builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
             writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
             writeln!(out, "  }}");
@@ -369,7 +346,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
         writeln!(out, "}};");
     }
 
-    if needs_rust_error {
+    if out.builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Error> final {{");
@@ -386,7 +363,7 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     out.end_block("namespace");
     out.end_block("namespace cxxbridge05");
 
-    if needs_trycatch {
+    if out.builtin.trycatch {
         out.begin_block("namespace behavior");
         out.include.exception = true;
         out.include.type_traits = true;

From ec66d11dc4c65e3f1dc083c020f04a1b3f7fb9b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:01 +0000
Subject: [PATCH 1137/2232] Split detection and writing of builtins


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index e638410..a0bafc2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -27,6 +27,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     write_includes(out);
     write_include_cxxbridge(out, apis);
+    write_builtins(out);
 
     out.next_section();
 
@@ -251,7 +252,9 @@ fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
             _ => {}
         }
     }
+}
 
+fn write_builtins(out: &mut OutFile) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");
 

From 528200fa16e1a25e621f9fec81a95a48b1b4d2b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:01 +0000
Subject: [PATCH 1138/2232] Merge two functions picking includes and builtins


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index a0bafc2..69f0144 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -25,8 +25,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         }
     }
 
-    write_includes(out);
-    write_include_cxxbridge(out, apis);
+    pick_includes_and_builtins(out, apis);
     write_builtins(out);
 
     out.next_section();
@@ -149,7 +148,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
     }
 }
 
-fn write_includes(out: &mut OutFile) {
+fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     for ty in out.types {
         match ty {
             Type::Ident(ident) => match Atom::from(&ident.rust) {
@@ -166,9 +165,7 @@ fn write_includes(out: &mut OutFile) {
             _ => {}
         }
     }
-}
 
-fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api]) {
     for ty in out.types {
         match ty {
             Type::RustBox(_) => {

From b9da1468b61906d8182dad3a442646875a490468 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:01 +0000
Subject: [PATCH 1139/2232] Combine include-pick loop


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 69f0144..0514554 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -155,19 +155,19 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
                 | Some(I64) => out.include.cstdint = true,
                 Some(Usize) => out.include.cstddef = true,
+                Some(Isize) => {
+                    out.include.basetsd = true;
+                    out.builtin.rust_isize = true;
+                }
                 Some(CxxString) => out.include.string = true,
-                Some(Bool) | Some(Isize) | Some(F32) | Some(F64) | Some(RustString) | None => {}
+                Some(RustString) => {
+                    out.include.array = true;
+                    out.include.cstdint = true;
+                    out.include.string = true;
+                    out.builtin.rust_string = true;
+                }
+                Some(Bool) | Some(F32) | Some(F64) | None => {}
             },
-            Type::RustBox(_) => out.include.type_traits = true,
-            Type::UniquePtr(_) => out.include.memory = true,
-            Type::CxxVector(_) => out.include.vector = true,
-            Type::SliceRefU8(_) => out.include.cstdint = true,
-            _ => {}
-        }
-    }
-
-    for ty in out.types {
-        match ty {
             Type::RustBox(_) => {
                 out.include.new = true;
                 out.include.type_traits = true;
@@ -181,26 +181,22 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 out.builtin.rust_vec = true;
                 out.builtin.unsafe_bitcopy = true;
             }
+            Type::UniquePtr(_) => out.include.memory = true,
             Type::Str(_) => {
                 out.include.cstdint = true;
                 out.include.string = true;
                 out.builtin.rust_str = true;
             }
+            Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => {
                 out.builtin.rust_fn = true;
             }
-            Type::Slice(_) | Type::SliceRefU8(_) => {
+            Type::Slice(_) => {
                 out.builtin.rust_slice = true;
             }
-            ty if ty == Isize => {
-                out.include.basetsd = true;
-                out.builtin.rust_isize = true;
-            }
-            ty if ty == RustString => {
-                out.include.array = true;
+            Type::SliceRefU8(_) => {
                 out.include.cstdint = true;
-                out.include.string = true;
-                out.builtin.rust_string = true;
+                out.builtin.rust_slice = true;
             }
             _ => {}
         }

From 12af7e48a7c5c367fb8e028ae672bc0fcde929a6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:01 +0000
Subject: [PATCH 1140/2232] Move writing includes to write.rs


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 309d8c3..b49cf82 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,6 +1,5 @@
 use crate::gen::out::OutFile;
 use crate::syntax::{self, IncludeKind};
-use std::fmt::{self, Display};
 
 /// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
@@ -64,7 +63,7 @@ pub struct Include {
 
 #[derive(Default, PartialEq)]
 pub struct Includes {
-    custom: Vec<Include>,
+    pub custom: Vec<Include>,
     pub array: bool,
     pub cstddef: bool,
     pub cstdint: bool,
@@ -103,57 +102,3 @@ impl<'a> From<&'a syntax::Include> for Include {
         }
     }
 }
-
-impl Display for Includes {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        for include in &self.custom {
-            match include.kind {
-                IncludeKind::Quoted => {
-                    writeln!(f, "#include \"{}\"", include.path.escape_default())?;
-                }
-                IncludeKind::Bracketed => {
-                    writeln!(f, "#include <{}>", include.path)?;
-                }
-            }
-        }
-        if self.array {
-            writeln!(f, "#include <array>")?;
-        }
-        if self.cstddef {
-            writeln!(f, "#include <cstddef>")?;
-        }
-        if self.cstdint {
-            writeln!(f, "#include <cstdint>")?;
-        }
-        if self.cstring {
-            writeln!(f, "#include <cstring>")?;
-        }
-        if self.exception {
-            writeln!(f, "#include <exception>")?;
-        }
-        if self.memory {
-            writeln!(f, "#include <memory>")?;
-        }
-        if self.new {
-            writeln!(f, "#include <new>")?;
-        }
-        if self.string {
-            writeln!(f, "#include <string>")?;
-        }
-        if self.type_traits {
-            writeln!(f, "#include <type_traits>")?;
-        }
-        if self.utility {
-            writeln!(f, "#include <utility>")?;
-        }
-        if self.vector {
-            writeln!(f, "#include <vector>")?;
-        }
-        if self.basetsd {
-            writeln!(f, "#if defined(_WIN32)")?;
-            writeln!(f, "#include <basetsd.h>")?;
-            writeln!(f, "#endif")?;
-        }
-        Ok(())
-    }
-}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0514554..9a1331e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,11 +1,12 @@
+use crate::gen::include::{self, Includes};
 use crate::gen::namespace_organizer::NamespaceEntries;
-use crate::gen::out::OutFile;
-use crate::gen::{include, Opt};
+use crate::gen::out::{Content, OutFile};
+use crate::gen::Opt;
 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, CppName, Enum, ExternFn, ExternType, IncludeKind, ResolvableName, Signature,
+    Struct, Type, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -40,7 +41,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         write_generic_instantiations(out);
     }
 
-    write!(out.front, "{}", out.include);
+    write_includes(&mut out.front, &out.include);
 
     out_file
 }
@@ -247,6 +248,58 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
+fn write_includes(out: &mut Content, include: &Includes) {
+    for include in &include.custom {
+        match include.kind {
+            IncludeKind::Quoted => {
+                writeln!(out, "#include \"{}\"", include.path.escape_default());
+            }
+            IncludeKind::Bracketed => {
+                writeln!(out, "#include <{}>", include.path);
+            }
+        }
+    }
+
+    if include.array {
+        writeln!(out, "#include <array>");
+    }
+    if include.cstddef {
+        writeln!(out, "#include <cstddef>");
+    }
+    if include.cstdint {
+        writeln!(out, "#include <cstdint>");
+    }
+    if include.cstring {
+        writeln!(out, "#include <cstring>");
+    }
+    if include.exception {
+        writeln!(out, "#include <exception>");
+    }
+    if include.memory {
+        writeln!(out, "#include <memory>");
+    }
+    if include.new {
+        writeln!(out, "#include <new>");
+    }
+    if include.string {
+        writeln!(out, "#include <string>");
+    }
+    if include.type_traits {
+        writeln!(out, "#include <type_traits>");
+    }
+    if include.utility {
+        writeln!(out, "#include <utility>");
+    }
+    if include.vector {
+        writeln!(out, "#include <vector>");
+    }
+    if include.basetsd {
+        writeln!(out, "#if defined(_WIN32)");
+        writeln!(out, "#include <basetsd.h>");
+        writeln!(out, "#endif");
+    }
+}
+
 fn write_builtins(out: &mut OutFile) {
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");

From cb2189f3b196706264d1331cb6dbac8415091869 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1141/2232] Make section and block methods available on Content


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 055f199..9dd4a7d 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -33,23 +33,15 @@ impl<'a> OutFile<'a> {
 
     // Write a blank line if the preceding section had any contents.
     pub fn next_section(&mut self) {
-        let content = self.content.get_mut();
-        content.section_pending = true;
+        self.content.get_mut().next_section();
     }
 
     pub fn begin_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        content.blocks_pending.push(block);
+        self.content.get_mut().begin_block(block);
     }
 
     pub fn end_block(&mut self, block: &'static str) {
-        let content = self.content.get_mut();
-        if content.blocks_pending.pop().is_none() {
-            content.bytes.push_str("} // ");
-            content.bytes.push_str(block);
-            content.bytes.push('\n');
-            content.section_pending = true;
-        }
+        self.content.get_mut().end_block(block);
     }
 
     pub fn write_fmt(&self, args: Arguments) {
@@ -82,10 +74,6 @@ impl Write for Content {
 }
 
 impl Content {
-    pub fn write_fmt(&mut self, args: Arguments) {
-        Write::write_fmt(self, args).unwrap();
-    }
-
     fn new() -> Self {
         Content {
             bytes: String::new(),
@@ -94,6 +82,27 @@ impl Content {
         }
     }
 
+    pub fn next_section(&mut self) {
+        self.section_pending = true;
+    }
+
+    pub fn begin_block(&mut self, block: &'static str) {
+        self.blocks_pending.push(block);
+    }
+
+    pub fn end_block(&mut self, block: &'static str) {
+        if self.blocks_pending.pop().is_none() {
+            self.bytes.push_str("} // ");
+            self.bytes.push_str(block);
+            self.bytes.push('\n');
+            self.section_pending = true;
+        }
+    }
+
+    pub fn write_fmt(&mut self, args: Arguments) {
+        Write::write_fmt(self, args).unwrap();
+    }
+
     fn write(&mut self, b: &str) {
         if !b.is_empty() {
             if !self.blocks_pending.is_empty() {

From 8810a54d80f0d62e46d842010e67e145f9470fe5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1142/2232] Move frontmatter content into Includes


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index b49cf82..ae0b202 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,5 +1,6 @@
-use crate::gen::out::OutFile;
+use crate::gen::out::{Content, OutFile};
 use crate::syntax::{self, IncludeKind};
+use std::ops::{Deref, DerefMut};
 
 /// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
@@ -76,6 +77,7 @@ pub struct Includes {
     pub utility: bool,
     pub vector: bool,
     pub basetsd: bool,
+    pub content: Content,
 }
 
 impl Includes {
@@ -102,3 +104,17 @@ impl<'a> From<&'a syntax::Include> for Include {
         }
     }
 }
+
+impl Deref for Includes {
+    type Target = Content;
+
+    fn deref(&self) -> &Self::Target {
+        &self.content
+    }
+}
+
+impl DerefMut for Includes {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.content
+    }
+}
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 9dd4a7d..6d475fc 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -9,10 +9,10 @@ pub(crate) struct OutFile<'a> {
     pub types: &'a Types<'a>,
     pub include: Includes,
     pub builtin: Builtins,
-    pub front: Content,
     content: RefCell<Content>,
 }
 
+#[derive(Default)]
 pub struct Content {
     bytes: String,
     section_pending: bool,
@@ -26,7 +26,6 @@ impl<'a> OutFile<'a> {
             types,
             include: Includes::new(),
             builtin: Builtins::new(),
-            front: Content::new(),
             content: RefCell::new(Content::new()),
         }
     }
@@ -50,12 +49,12 @@ impl<'a> OutFile<'a> {
     }
 
     pub fn content(&self) -> Vec<u8> {
-        let front = &self.front.bytes;
+        let include = &self.include.content.bytes;
         let content = &self.content.borrow().bytes;
-        let len = front.len() + content.len() + 1;
+        let len = include.len() + content.len() + 1;
         let mut out = String::with_capacity(len);
-        out.push_str(front);
-        if !front.is_empty() && !content.is_empty() {
+        out.push_str(include);
+        if !include.is_empty() && !content.is_empty() {
             out.push('\n');
         }
         out.push_str(content);
@@ -73,13 +72,15 @@ impl Write for Content {
     }
 }
 
+impl PartialEq for Content {
+    fn eq(&self, _other: &Content) -> bool {
+        true
+    }
+}
+
 impl Content {
     fn new() -> Self {
-        Content {
-            bytes: String::new(),
-            section_pending: false,
-            blocks_pending: Vec::new(),
-        }
+        Content::default()
     }
 
     pub fn next_section(&mut self) {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9a1331e..f32cb5b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,7 +1,6 @@
-use crate::gen::include::{self, Includes};
 use crate::gen::namespace_organizer::NamespaceEntries;
-use crate::gen::out::{Content, OutFile};
-use crate::gen::Opt;
+use crate::gen::out::OutFile;
+use crate::gen::{include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -16,7 +15,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     let out = &mut out_file;
 
     if header {
-        writeln!(out.front, "#pragma once");
+        writeln!(out.include, "#pragma once");
     }
 
     out.include.extend(&opt.include);
@@ -41,7 +40,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         write_generic_instantiations(out);
     }
 
-    write_includes(&mut out.front, &out.include);
+    write_includes(out);
 
     out_file
 }
@@ -248,7 +247,10 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_includes(out: &mut Content, include: &Includes) {
+fn write_includes(out: &mut OutFile) {
+    let include = &mut out.include;
+    let out = &mut include.content;
+
     for include in &include.custom {
         match include.kind {
             IncludeKind::Quoted => {

From 8c14d9a638135113809f3179520ab569ef779781 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1143/2232] Add content block inside Builtins


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index a120eef..e28a62c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -1,3 +1,5 @@
+use crate::gen::out::Content;
+
 #[derive(Default, PartialEq)]
 pub struct Builtins {
     pub panic: bool,
@@ -15,6 +17,7 @@ pub struct Builtins {
     pub trycatch: bool,
     pub rust_str_new_unchecked: bool,
     pub rust_str_repr: bool,
+    pub content: Content,
 }
 
 impl Builtins {
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 6d475fc..99aecc2 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -50,11 +50,16 @@ impl<'a> OutFile<'a> {
 
     pub fn content(&self) -> Vec<u8> {
         let include = &self.include.content.bytes;
+        let builtin = &self.builtin.content.bytes;
         let content = &self.content.borrow().bytes;
-        let len = include.len() + content.len() + 1;
+        let len = include.len() + builtin.len() + content.len() + 2;
         let mut out = String::with_capacity(len);
         out.push_str(include);
-        if !include.is_empty() && !content.is_empty() {
+        if !out.is_empty() && !builtin.is_empty() {
+            out.push('\n');
+        }
+        out.push_str(builtin);
+        if !out.is_empty() && !content.is_empty() {
             out.push('\n');
         }
         out.push_str(content);

From fd68e562fa83ab772046c3432747a0db4bc6bb05 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1144/2232] Write builtins directly to Builtins frontmatter


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index ae0b202..0ccb4d0 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,11 +1,11 @@
-use crate::gen::out::{Content, OutFile};
+use crate::gen::out::Content;
 use crate::syntax::{self, IncludeKind};
 use std::ops::{Deref, DerefMut};
 
 /// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
 
-pub(super) fn write(out: &mut OutFile, needed: bool, guard: &str) {
+pub(super) fn write(out: &mut Content, needed: bool, guard: &str) {
     let ifndef = format!("#ifndef {}", guard);
     let define = format!("#define {}", guard);
     let endif = format!("#endif // {}", guard);
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f32cb5b..1b30446 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -303,40 +303,45 @@ fn write_includes(out: &mut OutFile) {
 }
 
 fn write_builtins(out: &mut OutFile) {
+    if out.builtin == Default::default() {
+        return;
+    }
+
+    let include = &mut out.include;
+    let builtin = &mut out.builtin;
+    let out = &mut builtin.content;
+
     out.begin_block("namespace rust");
     out.begin_block("inline namespace cxxbridge05");
+    writeln!(out, "// #include \"rust/cxx.h\"");
 
-    if out.builtin != Default::default() {
-        writeln!(out, "// #include \"rust/cxx.h\"");
-    }
-
-    include::write(out, out.builtin.panic, "CXXBRIDGE05_PANIC");
+    include::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
 
-    if out.builtin.rust_string {
+    if builtin.rust_string {
         out.next_section();
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    if out.builtin.rust_error {
+    if builtin.rust_error {
         out.begin_block("namespace");
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");
         out.end_block("namespace");
     }
 
-    include::write(out, out.builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
-    include::write(out, out.builtin.rust_str, "CXXBRIDGE05_RUST_STR");
-    include::write(out, out.builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    include::write(out, out.builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
-    include::write(out, out.builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    include::write(out, out.builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
-    include::write(out, out.builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
-    include::write(out, out.builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
-    include::write(out, out.builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    include::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    include::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    include::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    include::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    include::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    include::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    include::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    include::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    include::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
 
-    if out.builtin.manually_drop {
+    if builtin.manually_drop {
         out.next_section();
-        out.include.utility = true;
+        include.utility = true;
         writeln!(out, "template <typename T>");
         writeln!(out, "union ManuallyDrop {{");
         writeln!(out, "  T value;");
@@ -348,7 +353,7 @@ fn write_builtins(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    if out.builtin.maybe_uninit {
+    if builtin.maybe_uninit {
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "union MaybeUninit {{");
@@ -360,10 +365,10 @@ fn write_builtins(out: &mut OutFile) {
 
     out.begin_block("namespace");
 
-    if out.builtin.trycatch
-        || out.builtin.rust_error
-        || out.builtin.rust_str_new_unchecked
-        || out.builtin.rust_str_repr
+    if builtin.trycatch
+        || builtin.rust_error
+        || builtin.rust_str_new_unchecked
+        || builtin.rust_str_repr
     {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
@@ -373,12 +378,12 @@ fn write_builtins(out: &mut OutFile) {
         out.end_block("namespace repr");
     }
 
-    if out.builtin.rust_str_new_unchecked || out.builtin.rust_str_repr {
+    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Str> final {{");
         writeln!(out, "public:");
-        if out.builtin.rust_str_new_unchecked {
+        if builtin.rust_str_new_unchecked {
             writeln!(
                 out,
                 "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
@@ -389,7 +394,7 @@ fn write_builtins(out: &mut OutFile) {
             writeln!(out, "    return str;");
             writeln!(out, "  }}");
         }
-        if out.builtin.rust_str_repr {
+        if builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
             writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
             writeln!(out, "  }}");
@@ -397,7 +402,7 @@ fn write_builtins(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    if out.builtin.rust_error {
+    if builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
         writeln!(out, "class impl<Error> final {{");
@@ -414,11 +419,11 @@ fn write_builtins(out: &mut OutFile) {
     out.end_block("namespace");
     out.end_block("namespace cxxbridge05");
 
-    if out.builtin.trycatch {
+    if builtin.trycatch {
         out.begin_block("namespace behavior");
-        out.include.exception = true;
-        out.include.type_traits = true;
-        out.include.utility = true;
+        include.exception = true;
+        include.type_traits = true;
+        include.utility = true;
         writeln!(out, "class missing {{}};");
         writeln!(out, "missing trycatch(...);");
         writeln!(out);

From e629c6453a3171b60feeaf2e47e492abc810c981 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1145/2232] Defer writing builtins until after main content


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1b30446..9696a49 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -18,6 +18,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         writeln!(out.include, "#pragma once");
     }
 
+    pick_includes_and_builtins(out, apis);
     out.include.extend(&opt.include);
     for api in apis {
         if let Api::Include(include) = api {
@@ -25,11 +26,6 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         }
     }
 
-    pick_includes_and_builtins(out, apis);
-    write_builtins(out);
-
-    out.next_section();
-
     let apis_by_namespace = NamespaceEntries::new(apis);
 
     gen_namespace_forward_declarations(out, &apis_by_namespace);
@@ -40,6 +36,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         write_generic_instantiations(out);
     }
 
+    write_builtins(out);
     write_includes(out);
 
     out_file

From 880d1f86e56da711cbf288cee49f19c7b8dc1484 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1146/2232] Handle Api::Include as part of root namespace contents


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9696a49..095b2c2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -20,11 +20,6 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     pick_includes_and_builtins(out, apis);
     out.include.extend(&opt.include);
-    for api in apis {
-        if let Api::Include(include) = api {
-            out.include.insert(include);
-        }
-    }
 
     let apis_by_namespace = NamespaceEntries::new(apis);
 
@@ -48,6 +43,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     out.next_section();
     for api in apis {
         match api {
+            Api::Include(include) => out.include.insert(include),
             Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
             Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
             Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),

From 3e278d72520767c73f705c48734cf4b768f86ea0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1147/2232] Move ifndef extractor to module


---

diff --git a/gen/src/ifndef.rs b/gen/src/ifndef.rs
new file mode 100644
index 0000000..b436266
--- /dev/null
+++ b/gen/src/ifndef.rs
@@ -0,0 +1,46 @@
+use crate::gen::include::HEADER;
+use crate::gen::out::Content;
+
+pub(super) fn write(out: &mut Content, needed: bool, guard: &str) {
+    let ifndef = format!("#ifndef {}", guard);
+    let define = format!("#define {}", guard);
+    let endif = format!("#endif // {}", guard);
+
+    let mut offset = 0;
+    loop {
+        let begin = find_line(offset, &ifndef);
+        let end = find_line(offset, &endif);
+        if let (Some(begin), Some(end)) = (begin, end) {
+            if !needed {
+                return;
+            }
+            out.next_section();
+            if offset == 0 {
+                writeln!(out, "{}", ifndef);
+                writeln!(out, "{}", define);
+            }
+            for line in HEADER[begin + ifndef.len()..end].trim().lines() {
+                if line != define && !line.trim_start().starts_with("//") {
+                    writeln!(out, "{}", line);
+                }
+            }
+            offset = end + endif.len();
+        } else if offset == 0 {
+            panic!("not found in cxx.h header: {}", guard)
+        } else {
+            writeln!(out, "{}", endif);
+            return;
+        }
+    }
+}
+
+fn find_line(mut offset: usize, line: &str) -> Option<usize> {
+    loop {
+        offset += HEADER[offset..].find(line)?;
+        let rest = &HEADER[offset + line.len()..];
+        if rest.starts_with('\n') || rest.starts_with('\r') {
+            return Some(offset);
+        }
+        offset += line.len();
+    }
+}
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 0ccb4d0..091f6c8 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -5,50 +5,6 @@ use std::ops::{Deref, DerefMut};
 /// The complete contents of the "rust/cxx.h" header.
 pub static HEADER: &str = include_str!("include/cxx.h");
 
-pub(super) fn write(out: &mut Content, needed: bool, guard: &str) {
-    let ifndef = format!("#ifndef {}", guard);
-    let define = format!("#define {}", guard);
-    let endif = format!("#endif // {}", guard);
-
-    let mut offset = 0;
-    loop {
-        let begin = find_line(offset, &ifndef);
-        let end = find_line(offset, &endif);
-        if let (Some(begin), Some(end)) = (begin, end) {
-            if !needed {
-                return;
-            }
-            out.next_section();
-            if offset == 0 {
-                writeln!(out, "{}", ifndef);
-                writeln!(out, "{}", define);
-            }
-            for line in HEADER[begin + ifndef.len()..end].trim().lines() {
-                if line != define && !line.trim_start().starts_with("//") {
-                    writeln!(out, "{}", line);
-                }
-            }
-            offset = end + endif.len();
-        } else if offset == 0 {
-            panic!("not found in cxx.h header: {}", guard)
-        } else {
-            writeln!(out, "{}", endif);
-            return;
-        }
-    }
-}
-
-fn find_line(mut offset: usize, line: &str) -> Option<usize> {
-    loop {
-        offset += HEADER[offset..].find(line)?;
-        let rest = &HEADER[offset + line.len()..];
-        if rest.starts_with('\n') || rest.starts_with('\r') {
-            return Some(offset);
-        }
-        offset += line.len();
-    }
-}
-
 /// A header to #include.
 ///
 /// The cxxbridge tool does not parse or even require the given paths to exist;
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index e969dec..d79a465 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -6,6 +6,7 @@ mod check;
 pub(super) mod error;
 mod file;
 pub(super) mod fs;
+mod ifndef;
 pub(super) mod include;
 mod namespace_organizer;
 pub(super) mod out;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 095b2c2..2af11c6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,6 +1,6 @@
 use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{include, Opt};
+use crate::gen::{ifndef, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -308,7 +308,7 @@ fn write_builtins(out: &mut OutFile) {
     out.begin_block("inline namespace cxxbridge05");
     writeln!(out, "// #include \"rust/cxx.h\"");
 
-    include::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
+    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
 
     if builtin.rust_string {
         out.next_section();
@@ -322,15 +322,15 @@ fn write_builtins(out: &mut OutFile) {
         out.end_block("namespace");
     }
 
-    include::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
-    include::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
-    include::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    include::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
-    include::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    include::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
-    include::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
-    include::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
-    include::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
 
     if builtin.manually_drop {
         out.next_section();

From 2f3e90b10e88c02ed51f5e29f187664144f8ceb6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:02 +0000
Subject: [PATCH 1148/2232] Move include-related writes to include module


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 091f6c8..8dc7146 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -1,4 +1,4 @@
-use crate::gen::out::Content;
+use crate::gen::out::{Content, OutFile};
 use crate::syntax::{self, IncludeKind};
 use std::ops::{Deref, DerefMut};
 
@@ -46,6 +46,61 @@ impl Includes {
     }
 }
 
+pub(super) fn write(out: &mut OutFile) {
+    let include = &mut out.include;
+    let out = &mut include.content;
+
+    for include in &include.custom {
+        match include.kind {
+            IncludeKind::Quoted => {
+                writeln!(out, "#include \"{}\"", include.path.escape_default());
+            }
+            IncludeKind::Bracketed => {
+                writeln!(out, "#include <{}>", include.path);
+            }
+        }
+    }
+
+    if include.array {
+        writeln!(out, "#include <array>");
+    }
+    if include.cstddef {
+        writeln!(out, "#include <cstddef>");
+    }
+    if include.cstdint {
+        writeln!(out, "#include <cstdint>");
+    }
+    if include.cstring {
+        writeln!(out, "#include <cstring>");
+    }
+    if include.exception {
+        writeln!(out, "#include <exception>");
+    }
+    if include.memory {
+        writeln!(out, "#include <memory>");
+    }
+    if include.new {
+        writeln!(out, "#include <new>");
+    }
+    if include.string {
+        writeln!(out, "#include <string>");
+    }
+    if include.type_traits {
+        writeln!(out, "#include <type_traits>");
+    }
+    if include.utility {
+        writeln!(out, "#include <utility>");
+    }
+    if include.vector {
+        writeln!(out, "#include <vector>");
+    }
+    if include.basetsd {
+        writeln!(out, "#if defined(_WIN32)");
+        writeln!(out, "#include <basetsd.h>");
+        writeln!(out, "#endif");
+    }
+}
+
 impl<'a> Extend<&'a Include> for Includes {
     fn extend<I: IntoIterator<Item = &'a Include>>(&mut self, iter: I) {
         self.custom.extend(iter.into_iter().cloned());
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2af11c6..fc093e7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,11 +1,11 @@
 use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{ifndef, Opt};
+use crate::gen::{ifndef, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    mangle, Api, CppName, Enum, ExternFn, ExternType, IncludeKind, ResolvableName, Signature,
-    Struct, Type, Types, Var,
+    mangle, Api, CppName, Enum, ExternFn, ExternType, ResolvableName, Signature, Struct, Type,
+    Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::HashMap;
@@ -32,7 +32,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     }
 
     write_builtins(out);
-    write_includes(out);
+    include::write(out);
 
     out_file
 }
@@ -240,61 +240,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_includes(out: &mut OutFile) {
-    let include = &mut out.include;
-    let out = &mut include.content;
-
-    for include in &include.custom {
-        match include.kind {
-            IncludeKind::Quoted => {
-                writeln!(out, "#include \"{}\"", include.path.escape_default());
-            }
-            IncludeKind::Bracketed => {
-                writeln!(out, "#include <{}>", include.path);
-            }
-        }
-    }
-
-    if include.array {
-        writeln!(out, "#include <array>");
-    }
-    if include.cstddef {
-        writeln!(out, "#include <cstddef>");
-    }
-    if include.cstdint {
-        writeln!(out, "#include <cstdint>");
-    }
-    if include.cstring {
-        writeln!(out, "#include <cstring>");
-    }
-    if include.exception {
-        writeln!(out, "#include <exception>");
-    }
-    if include.memory {
-        writeln!(out, "#include <memory>");
-    }
-    if include.new {
-        writeln!(out, "#include <new>");
-    }
-    if include.string {
-        writeln!(out, "#include <string>");
-    }
-    if include.type_traits {
-        writeln!(out, "#include <type_traits>");
-    }
-    if include.utility {
-        writeln!(out, "#include <utility>");
-    }
-    if include.vector {
-        writeln!(out, "#include <vector>");
-    }
-    if include.basetsd {
-        writeln!(out, "#if defined(_WIN32)");
-        writeln!(out, "#include <basetsd.h>");
-        writeln!(out, "#endif");
-    }
-}
-
 fn write_builtins(out: &mut OutFile) {
     if out.builtin == Default::default() {
         return;

From 3374d8d51bf11353a4359d70a931411274b09f92 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 05:56:03 +0000
Subject: [PATCH 1149/2232] Move builtin-related writes to builtin module


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index e28a62c..a1393b5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -1,4 +1,5 @@
-use crate::gen::out::Content;
+use crate::gen::ifndef;
+use crate::gen::out::{Content, OutFile};
 
 #[derive(Default, PartialEq)]
 pub struct Builtins {
@@ -25,3 +26,146 @@ impl Builtins {
         Builtins::default()
     }
 }
+
+pub(super) fn write(out: &mut OutFile) {
+    if out.builtin == Default::default() {
+        return;
+    }
+
+    let include = &mut out.include;
+    let builtin = &mut out.builtin;
+    let out = &mut builtin.content;
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge05");
+    writeln!(out, "// #include \"rust/cxx.h\"");
+
+    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
+
+    if builtin.rust_string {
+        out.next_section();
+        writeln!(out, "struct unsafe_bitcopy_t;");
+    }
+
+    if builtin.rust_error {
+        out.begin_block("namespace");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl;");
+        out.end_block("namespace");
+    }
+
+    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+
+    if builtin.manually_drop {
+        out.next_section();
+        include.utility = true;
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union ManuallyDrop {{");
+        writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
+        );
+        writeln!(out, "  ~ManuallyDrop() {{}}");
+        writeln!(out, "}};");
+    }
+
+    if builtin.maybe_uninit {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union MaybeUninit {{");
+        writeln!(out, "  T value;");
+        writeln!(out, "  MaybeUninit() {{}}");
+        writeln!(out, "  ~MaybeUninit() {{}}");
+        writeln!(out, "}};");
+    }
+
+    out.begin_block("namespace");
+
+    if builtin.trycatch
+        || builtin.rust_error
+        || builtin.rust_str_new_unchecked
+        || builtin.rust_str_repr
+    {
+        out.begin_block("namespace repr");
+        writeln!(out, "struct PtrLen final {{");
+        writeln!(out, "  const void *ptr;");
+        writeln!(out, "  size_t len;");
+        writeln!(out, "}};");
+        out.end_block("namespace repr");
+    }
+
+    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Str> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_str_new_unchecked {
+            writeln!(
+                out,
+                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
+            );
+            writeln!(out, "    Str str;");
+            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
+            writeln!(out, "    str.len = repr.len;");
+            writeln!(out, "    return str;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_str_repr {
+            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
+            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(out, "  }}");
+        }
+        writeln!(out, "}};");
+    }
+
+    if builtin.rust_error {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Error> final {{");
+        writeln!(out, "public:");
+        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
+        writeln!(out, "    Error error;");
+        writeln!(out, "    error.msg = static_cast<const char *>(repr.ptr);");
+        writeln!(out, "    error.len = repr.len;");
+        writeln!(out, "    return error;");
+        writeln!(out, "  }}");
+        writeln!(out, "}};");
+    }
+
+    out.end_block("namespace");
+    out.end_block("namespace cxxbridge05");
+
+    if builtin.trycatch {
+        out.begin_block("namespace behavior");
+        include.exception = true;
+        include.type_traits = true;
+        include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
+        writeln!(out);
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename ::std::enable_if<");
+        writeln!(
+            out,
+            "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
+        );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+        out.end_block("namespace behavior");
+    }
+
+    out.end_block("namespace rust");
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index fc093e7..5dcf91c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,6 +1,6 @@
 use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{ifndef, include, Opt};
+use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -31,7 +31,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         write_generic_instantiations(out);
     }
 
-    write_builtins(out);
+    builtin::write(out);
     include::write(out);
 
     out_file
@@ -240,149 +240,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_builtins(out: &mut OutFile) {
-    if out.builtin == Default::default() {
-        return;
-    }
-
-    let include = &mut out.include;
-    let builtin = &mut out.builtin;
-    let out = &mut builtin.content;
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
-    writeln!(out, "// #include \"rust/cxx.h\"");
-
-    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
-
-    if builtin.rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
-
-    if builtin.rust_error {
-        out.begin_block("namespace");
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl;");
-        out.end_block("namespace");
-    }
-
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
-
-    if builtin.manually_drop {
-        out.next_section();
-        include.utility = true;
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union ManuallyDrop {{");
-        writeln!(out, "  T value;");
-        writeln!(
-            out,
-            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
-        );
-        writeln!(out, "  ~ManuallyDrop() {{}}");
-        writeln!(out, "}};");
-    }
-
-    if builtin.maybe_uninit {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union MaybeUninit {{");
-        writeln!(out, "  T value;");
-        writeln!(out, "  MaybeUninit() {{}}");
-        writeln!(out, "  ~MaybeUninit() {{}}");
-        writeln!(out, "}};");
-    }
-
-    out.begin_block("namespace");
-
-    if builtin.trycatch
-        || builtin.rust_error
-        || builtin.rust_str_new_unchecked
-        || builtin.rust_str_repr
-    {
-        out.begin_block("namespace repr");
-        writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const void *ptr;");
-        writeln!(out, "  size_t len;");
-        writeln!(out, "}};");
-        out.end_block("namespace repr");
-    }
-
-    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Str> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_str_new_unchecked {
-            writeln!(
-                out,
-                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    Str str;");
-            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
-            writeln!(out, "    str.len = repr.len;");
-            writeln!(out, "    return str;");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_str_repr {
-            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
-    if builtin.rust_error {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Error> final {{");
-        writeln!(out, "public:");
-        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
-        writeln!(out, "    Error error;");
-        writeln!(out, "    error.msg = static_cast<const char *>(repr.ptr);");
-        writeln!(out, "    error.len = repr.len;");
-        writeln!(out, "    return error;");
-        writeln!(out, "  }}");
-        writeln!(out, "}};");
-    }
-
-    out.end_block("namespace");
-    out.end_block("namespace cxxbridge05");
-
-    if builtin.trycatch {
-        out.begin_block("namespace behavior");
-        include.exception = true;
-        include.type_traits = true;
-        include.utility = true;
-        writeln!(out, "class missing {{}};");
-        writeln!(out, "missing trycatch(...);");
-        writeln!(out);
-        writeln!(out, "template <typename Try, typename Fail>");
-        writeln!(out, "static typename ::std::enable_if<");
-        writeln!(
-            out,
-            "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
-        );
-        writeln!(out, "                 missing>::value>::type");
-        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
-        writeln!(out, "  func();");
-        writeln!(out, "}} catch (const ::std::exception &e) {{");
-        writeln!(out, "  fail(e.what());");
-        writeln!(out, "}}");
-        out.end_block("namespace behavior");
-    }
-
-    out.end_block("namespace rust");
-}
-
 fn write_struct(out: &mut OutFile, strct: &Struct) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);

From bc6ebde31ef0d214cfcf3464a85f4564916c0d8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:05:32 +0000
Subject: [PATCH 1150/2232] Merge pull request #394 from dtolnay/builtin


Move builtin-related writes to builtin module
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index e28a62c..a1393b5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -1,4 +1,5 @@
-use crate::gen::out::Content;
+use crate::gen::ifndef;
+use crate::gen::out::{Content, OutFile};
 
 #[derive(Default, PartialEq)]
 pub struct Builtins {
@@ -25,3 +26,146 @@ impl Builtins {
         Builtins::default()
     }
 }
+
+pub(super) fn write(out: &mut OutFile) {
+    if out.builtin == Default::default() {
+        return;
+    }
+
+    let include = &mut out.include;
+    let builtin = &mut out.builtin;
+    let out = &mut builtin.content;
+
+    out.begin_block("namespace rust");
+    out.begin_block("inline namespace cxxbridge05");
+    writeln!(out, "// #include \"rust/cxx.h\"");
+
+    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
+
+    if builtin.rust_string {
+        out.next_section();
+        writeln!(out, "struct unsafe_bitcopy_t;");
+    }
+
+    if builtin.rust_error {
+        out.begin_block("namespace");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl;");
+        out.end_block("namespace");
+    }
+
+    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
+    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
+    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
+    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
+    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
+    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
+    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
+    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
+    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+
+    if builtin.manually_drop {
+        out.next_section();
+        include.utility = true;
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union ManuallyDrop {{");
+        writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
+        );
+        writeln!(out, "  ~ManuallyDrop() {{}}");
+        writeln!(out, "}};");
+    }
+
+    if builtin.maybe_uninit {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "union MaybeUninit {{");
+        writeln!(out, "  T value;");
+        writeln!(out, "  MaybeUninit() {{}}");
+        writeln!(out, "  ~MaybeUninit() {{}}");
+        writeln!(out, "}};");
+    }
+
+    out.begin_block("namespace");
+
+    if builtin.trycatch
+        || builtin.rust_error
+        || builtin.rust_str_new_unchecked
+        || builtin.rust_str_repr
+    {
+        out.begin_block("namespace repr");
+        writeln!(out, "struct PtrLen final {{");
+        writeln!(out, "  const void *ptr;");
+        writeln!(out, "  size_t len;");
+        writeln!(out, "}};");
+        out.end_block("namespace repr");
+    }
+
+    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Str> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_str_new_unchecked {
+            writeln!(
+                out,
+                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
+            );
+            writeln!(out, "    Str str;");
+            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
+            writeln!(out, "    str.len = repr.len;");
+            writeln!(out, "    return str;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_str_repr {
+            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
+            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(out, "  }}");
+        }
+        writeln!(out, "}};");
+    }
+
+    if builtin.rust_error {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Error> final {{");
+        writeln!(out, "public:");
+        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
+        writeln!(out, "    Error error;");
+        writeln!(out, "    error.msg = static_cast<const char *>(repr.ptr);");
+        writeln!(out, "    error.len = repr.len;");
+        writeln!(out, "    return error;");
+        writeln!(out, "  }}");
+        writeln!(out, "}};");
+    }
+
+    out.end_block("namespace");
+    out.end_block("namespace cxxbridge05");
+
+    if builtin.trycatch {
+        out.begin_block("namespace behavior");
+        include.exception = true;
+        include.type_traits = true;
+        include.utility = true;
+        writeln!(out, "class missing {{}};");
+        writeln!(out, "missing trycatch(...);");
+        writeln!(out);
+        writeln!(out, "template <typename Try, typename Fail>");
+        writeln!(out, "static typename ::std::enable_if<");
+        writeln!(
+            out,
+            "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
+        );
+        writeln!(out, "                 missing>::value>::type");
+        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
+        writeln!(out, "  func();");
+        writeln!(out, "}} catch (const ::std::exception &e) {{");
+        writeln!(out, "  fail(e.what());");
+        writeln!(out, "}}");
+        out.end_block("namespace behavior");
+    }
+
+    out.end_block("namespace rust");
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index fc093e7..5dcf91c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,6 +1,6 @@
 use crate::gen::namespace_organizer::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{ifndef, include, Opt};
+use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -31,7 +31,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         write_generic_instantiations(out);
     }
 
-    write_builtins(out);
+    builtin::write(out);
     include::write(out);
 
     out_file
@@ -240,149 +240,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_builtins(out: &mut OutFile) {
-    if out.builtin == Default::default() {
-        return;
-    }
-
-    let include = &mut out.include;
-    let builtin = &mut out.builtin;
-    let out = &mut builtin.content;
-
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
-    writeln!(out, "// #include \"rust/cxx.h\"");
-
-    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
-
-    if builtin.rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
-
-    if builtin.rust_error {
-        out.begin_block("namespace");
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl;");
-        out.end_block("namespace");
-    }
-
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
-
-    if builtin.manually_drop {
-        out.next_section();
-        include.utility = true;
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union ManuallyDrop {{");
-        writeln!(out, "  T value;");
-        writeln!(
-            out,
-            "  ManuallyDrop(T &&value) : value(::std::move(value)) {{}}",
-        );
-        writeln!(out, "  ~ManuallyDrop() {{}}");
-        writeln!(out, "}};");
-    }
-
-    if builtin.maybe_uninit {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "union MaybeUninit {{");
-        writeln!(out, "  T value;");
-        writeln!(out, "  MaybeUninit() {{}}");
-        writeln!(out, "  ~MaybeUninit() {{}}");
-        writeln!(out, "}};");
-    }
-
-    out.begin_block("namespace");
-
-    if builtin.trycatch
-        || builtin.rust_error
-        || builtin.rust_str_new_unchecked
-        || builtin.rust_str_repr
-    {
-        out.begin_block("namespace repr");
-        writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const void *ptr;");
-        writeln!(out, "  size_t len;");
-        writeln!(out, "}};");
-        out.end_block("namespace repr");
-    }
-
-    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Str> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_str_new_unchecked {
-            writeln!(
-                out,
-                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    Str str;");
-            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
-            writeln!(out, "    str.len = repr.len;");
-            writeln!(out, "    return str;");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_str_repr {
-            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
-    if builtin.rust_error {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Error> final {{");
-        writeln!(out, "public:");
-        writeln!(out, "  static Error error(repr::PtrLen repr) noexcept {{");
-        writeln!(out, "    Error error;");
-        writeln!(out, "    error.msg = static_cast<const char *>(repr.ptr);");
-        writeln!(out, "    error.len = repr.len;");
-        writeln!(out, "    return error;");
-        writeln!(out, "  }}");
-        writeln!(out, "}};");
-    }
-
-    out.end_block("namespace");
-    out.end_block("namespace cxxbridge05");
-
-    if builtin.trycatch {
-        out.begin_block("namespace behavior");
-        include.exception = true;
-        include.type_traits = true;
-        include.utility = true;
-        writeln!(out, "class missing {{}};");
-        writeln!(out, "missing trycatch(...);");
-        writeln!(out);
-        writeln!(out, "template <typename Try, typename Fail>");
-        writeln!(out, "static typename ::std::enable_if<");
-        writeln!(
-            out,
-            "    ::std::is_same<decltype(trycatch(::std::declval<Try>(), ::std::declval<Fail>())),",
-        );
-        writeln!(out, "                 missing>::value>::type");
-        writeln!(out, "trycatch(Try &&func, Fail &&fail) noexcept try {{");
-        writeln!(out, "  func();");
-        writeln!(out, "}} catch (const ::std::exception &e) {{");
-        writeln!(out, "  fail(e.what());");
-        writeln!(out, "}}");
-        out.end_block("namespace behavior");
-    }
-
-    out.end_block("namespace rust");
-}
-
 fn write_struct(out: &mut OutFile, strct: &Struct) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);

From 74d6d514391a52ffb7cb49e061f954fd0c01e2bb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:05:39 +0000
Subject: [PATCH 1151/2232] Select builtins lazily during code generation


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5dcf91c..c690995 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -18,7 +18,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         writeln!(out.include, "#pragma once");
     }
 
-    pick_includes_and_builtins(out, apis);
+    pick_includes_and_builtins(out);
     out.include.extend(&opt.include);
 
     let apis_by_namespace = NamespaceEntries::new(apis);
@@ -141,7 +141,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
     }
 }
 
-fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
+fn pick_includes_and_builtins(out: &mut OutFile) {
     for ty in out.types {
         match ty {
             Type::Ident(ident) => match Atom::from(&ident.rust) {
@@ -194,50 +194,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             _ => {}
         }
     }
-
-    for api in apis {
-        match api {
-            Api::CxxFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.builtin.trycatch = true;
-                } else if let Some(Type::Str(_)) = efn.ret {
-                    out.builtin.rust_str_repr = true;
-                }
-                for arg in &efn.args {
-                    match arg.ty {
-                        Type::Str(_) => out.builtin.rust_str_new_unchecked = true,
-                        Type::RustVec(_) => out.builtin.unsafe_bitcopy = true,
-                        _ => out.builtin.unsafe_bitcopy |= arg.ty == RustString,
-                    }
-                }
-            }
-            Api::RustFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.include.exception = true;
-                    out.include.string = true;
-                    out.builtin.rust_str = true;
-                    out.builtin.rust_error = true;
-                    out.builtin.maybe_uninit = true;
-                }
-                for arg in &efn.args {
-                    if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
-                        out.builtin.manually_drop = true;
-                    }
-                    if let Type::Str(_) = arg.ty {
-                        out.builtin.rust_str_repr = true;
-                    }
-                }
-                if let Some(ret) = &efn.ret {
-                    if out.types.needs_indirect_abi(ret) {
-                        out.builtin.maybe_uninit = true;
-                    } else if let Type::Str(_) = ret {
-                        out.builtin.rust_str_new_unchecked = true;
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
@@ -469,6 +425,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
+        out.builtin.trycatch = true;
         writeln!(out, "::rust::repr::PtrLen throw$;");
         writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
@@ -484,7 +441,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::impl<::rust::Str>::repr("),
+        Some(Type::Str(_)) if !indirect_return => {
+            out.builtin.rust_str_repr = true;
+            write!(out, "::rust::impl<::rust::Str>::repr(");
+        }
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             write!(out, "::rust::Slice<uint8_t>::Repr(")
         }
@@ -505,18 +465,21 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
         } else if let Type::Str(_) = arg.ty {
+            out.builtin.rust_str_new_unchecked = true;
             write!(
                 out,
                 "::rust::impl<::rust::Str>::new_unchecked({})",
                 arg.ident,
             );
         } else if arg.ty == RustString {
+            out.builtin.unsafe_bitcopy = true;
             write!(
                 out,
                 "::rust::String(::rust::unsafe_bitcopy, *{})",
                 arg.ident,
             );
         } else if let Type::RustVec(_) = arg.ty {
+            out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
@@ -698,6 +661,7 @@ fn write_rust_function_shim_impl(
     for arg in &sig.args {
         if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
+            out.builtin.manually_drop = true;
             write!(out, "  ::rust::ManuallyDrop<");
             write_type(out, &arg.ty);
             writeln!(out, "> {}$(::std::move({0}));", arg.ident);
@@ -706,6 +670,7 @@ fn write_rust_function_shim_impl(
     write!(out, "  ");
     let indirect_return = indirect_return(sig, out.types);
     if indirect_return {
+        out.builtin.maybe_uninit = true;
         write!(out, "::rust::MaybeUninit<");
         write_type(out, sig.ret.as_ref().unwrap());
         writeln!(out, "> return$;");
@@ -722,7 +687,10 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::new_unchecked("),
+            Type::Str(_) => {
+                out.builtin.rust_str_new_unchecked = true;
+                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
+            }
             _ => {}
         }
     }
@@ -738,7 +706,10 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::repr("),
+            Type::Str(_) => {
+                out.builtin.rust_str_repr = true;
+                write!(out, "::rust::impl<::rust::Str>::repr(");
+            }
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -774,6 +745,8 @@ fn write_rust_function_shim_impl(
     }
     writeln!(out, ";");
     if sig.throws {
+        out.include.exception = true;
+        out.builtin.rust_error = true;
         writeln!(out, "  if (error$.ptr) {{");
         writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
         writeln!(out, "  }}");

From 6890ea4d9d5f221f6795678533a04f4a6e4e2735 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:12:14 +0000
Subject: [PATCH 1152/2232] Merge pull request #395 from dtolnay/builtin


Select builtins lazily during code generation
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5dcf91c..c690995 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -18,7 +18,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
         writeln!(out.include, "#pragma once");
     }
 
-    pick_includes_and_builtins(out, apis);
+    pick_includes_and_builtins(out);
     out.include.extend(&opt.include);
 
     let apis_by_namespace = NamespaceEntries::new(apis);
@@ -141,7 +141,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
     }
 }
 
-fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
+fn pick_includes_and_builtins(out: &mut OutFile) {
     for ty in out.types {
         match ty {
             Type::Ident(ident) => match Atom::from(&ident.rust) {
@@ -194,50 +194,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             _ => {}
         }
     }
-
-    for api in apis {
-        match api {
-            Api::CxxFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.builtin.trycatch = true;
-                } else if let Some(Type::Str(_)) = efn.ret {
-                    out.builtin.rust_str_repr = true;
-                }
-                for arg in &efn.args {
-                    match arg.ty {
-                        Type::Str(_) => out.builtin.rust_str_new_unchecked = true,
-                        Type::RustVec(_) => out.builtin.unsafe_bitcopy = true,
-                        _ => out.builtin.unsafe_bitcopy |= arg.ty == RustString,
-                    }
-                }
-            }
-            Api::RustFunction(efn) if !out.header => {
-                if efn.throws {
-                    out.include.exception = true;
-                    out.include.string = true;
-                    out.builtin.rust_str = true;
-                    out.builtin.rust_error = true;
-                    out.builtin.maybe_uninit = true;
-                }
-                for arg in &efn.args {
-                    if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
-                        out.builtin.manually_drop = true;
-                    }
-                    if let Type::Str(_) = arg.ty {
-                        out.builtin.rust_str_repr = true;
-                    }
-                }
-                if let Some(ret) = &efn.ret {
-                    if out.types.needs_indirect_abi(ret) {
-                        out.builtin.maybe_uninit = true;
-                    } else if let Type::Str(_) = ret {
-                        out.builtin.rust_str_new_unchecked = true;
-                    }
-                }
-            }
-            _ => {}
-        }
-    }
 }
 
 fn write_struct(out: &mut OutFile, strct: &Struct) {
@@ -469,6 +425,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
+        out.builtin.trycatch = true;
         writeln!(out, "::rust::repr::PtrLen throw$;");
         writeln!(out, "  ::rust::behavior::trycatch(");
         writeln!(out, "      [&] {{");
@@ -484,7 +441,10 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::impl<::rust::Str>::repr("),
+        Some(Type::Str(_)) if !indirect_return => {
+            out.builtin.rust_str_repr = true;
+            write!(out, "::rust::impl<::rust::Str>::repr(");
+        }
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             write!(out, "::rust::Slice<uint8_t>::Repr(")
         }
@@ -505,18 +465,21 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
             write_type(out, &arg.ty);
             write!(out, "({})", arg.ident);
         } else if let Type::Str(_) = arg.ty {
+            out.builtin.rust_str_new_unchecked = true;
             write!(
                 out,
                 "::rust::impl<::rust::Str>::new_unchecked({})",
                 arg.ident,
             );
         } else if arg.ty == RustString {
+            out.builtin.unsafe_bitcopy = true;
             write!(
                 out,
                 "::rust::String(::rust::unsafe_bitcopy, *{})",
                 arg.ident,
             );
         } else if let Type::RustVec(_) = arg.ty {
+            out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
@@ -698,6 +661,7 @@ fn write_rust_function_shim_impl(
     for arg in &sig.args {
         if arg.ty != RustString && out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
+            out.builtin.manually_drop = true;
             write!(out, "  ::rust::ManuallyDrop<");
             write_type(out, &arg.ty);
             writeln!(out, "> {}$(::std::move({0}));", arg.ident);
@@ -706,6 +670,7 @@ fn write_rust_function_shim_impl(
     write!(out, "  ");
     let indirect_return = indirect_return(sig, out.types);
     if indirect_return {
+        out.builtin.maybe_uninit = true;
         write!(out, "::rust::MaybeUninit<");
         write_type(out, sig.ret.as_ref().unwrap());
         writeln!(out, "> return$;");
@@ -722,7 +687,10 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::new_unchecked("),
+            Type::Str(_) => {
+                out.builtin.rust_str_new_unchecked = true;
+                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
+            }
             _ => {}
         }
     }
@@ -738,7 +706,10 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => write!(out, "::rust::impl<::rust::Str>::repr("),
+            Type::Str(_) => {
+                out.builtin.rust_str_repr = true;
+                write!(out, "::rust::impl<::rust::Str>::repr(");
+            }
             Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -774,6 +745,8 @@ fn write_rust_function_shim_impl(
     }
     writeln!(out, ";");
     if sig.throws {
+        out.include.exception = true;
+        out.builtin.rust_error = true;
         writeln!(out, "  if (error$.ptr) {{");
         writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");
         writeln!(out, "  }}");

From 919085cd8b104460df58a761fed1c14ed8eedcb9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:12:25 +0000
Subject: [PATCH 1153/2232] Add builtin for PtrLen


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index a1393b5..8a65b5f 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -16,6 +16,7 @@ pub struct Builtins {
     pub manually_drop: bool,
     pub maybe_uninit: bool,
     pub trycatch: bool,
+    pub ptr_len: bool,
     pub rust_str_new_unchecked: bool,
     pub rust_str_repr: bool,
     pub content: Content,
@@ -90,11 +91,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     out.begin_block("namespace");
 
-    if builtin.trycatch
-        || builtin.rust_error
-        || builtin.rust_str_new_unchecked
-        || builtin.rust_str_repr
-    {
+    if builtin.ptr_len {
         out.begin_block("namespace repr");
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c690995..8af2fe5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -353,6 +353,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
         write!(out, "{} ", annotation);
     }
     if efn.throws {
+        out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &efn.ret);
@@ -425,6 +426,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
     writeln!(out, ";");
     write!(out, "  ");
     if efn.throws {
+        out.builtin.ptr_len = true;
         out.builtin.trycatch = true;
         writeln!(out, "::rust::repr::PtrLen throw$;");
         writeln!(out, "  ::rust::behavior::trycatch(");
@@ -551,6 +553,7 @@ fn write_rust_function_decl_impl(
     indirect_call: bool,
 ) {
     if sig.throws {
+        out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen ");
     } else {
         write_extern_return_type_space(out, &sig.ret);
@@ -695,6 +698,7 @@ fn write_rust_function_shim_impl(
         }
     }
     if sig.throws {
+        out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
@@ -811,7 +815,10 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => write!(out, "::rust::repr::PtrLen "),
+        Some(Type::Str(_)) => {
+            out.builtin.ptr_len = true;
+            write!(out, "::rust::repr::PtrLen ");
+        }
         Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
@@ -824,7 +831,10 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => write!(out, "::rust::repr::PtrLen "),
+        Type::Str(_) => {
+            out.builtin.ptr_len = true;
+            write!(out, "::rust::repr::PtrLen ");
+        }
         Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }

From 36aa9e0bd861a83e9f9313524eaa8223626be3dc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:24:31 +0000
Subject: [PATCH 1154/2232] Eliminate Slice<T>::Repr struct


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8a65b5f..448b6f8 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -19,6 +19,8 @@ pub struct Builtins {
     pub ptr_len: bool,
     pub rust_str_new_unchecked: bool,
     pub rust_str_repr: bool,
+    pub rust_slice_new: bool,
+    pub rust_slice_repr: bool,
     pub content: Content,
 }
 
@@ -124,6 +126,33 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
+    if builtin.rust_slice_new || builtin.rust_slice_repr {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class impl<Slice<T>> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_slice_new {
+            writeln!(
+                out,
+                "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
+            );
+            writeln!(
+                out,
+                "    return {{static_cast<const T *>(repr.ptr), repr.len}};",
+            );
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_slice_repr {
+            writeln!(
+                out,
+                "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
+            );
+            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
+            writeln!(out, "  }}");
+        }
+        writeln!(out, "}};");
+    }
+
     if builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8af2fe5..194241a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -448,7 +448,8 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
             write!(out, "::rust::impl<::rust::Str>::repr(");
         }
         Some(Type::SliceRefU8(_)) if !indirect_return => {
-            write!(out, "::rust::Slice<uint8_t>::Repr(")
+            out.builtin.rust_slice_repr = true;
+            write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(")
         }
         _ => {}
     }
@@ -484,6 +485,12 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: 
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
+        } else if let Type::SliceRefU8(_) = arg.ty {
+            write!(
+                out,
+                "::rust::Slice<uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
+                arg.ident,
+            );
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -694,6 +701,10 @@ fn write_rust_function_shim_impl(
                 out.builtin.rust_str_new_unchecked = true;
                 write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
             }
+            Type::SliceRefU8(_) => {
+                out.builtin.rust_slice_new = true;
+                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::slice(");
+            }
             _ => {}
         }
     }
@@ -714,7 +725,10 @@ fn write_rust_function_shim_impl(
                 out.builtin.rust_str_repr = true;
                 write!(out, "::rust::impl<::rust::Str>::repr(");
             }
-            Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr("),
+            Type::SliceRefU8(_) => {
+                out.builtin.rust_slice_repr = true;
+                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(");
+            }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
         }
@@ -742,7 +756,8 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) = ret
+            {
                 write!(out, ")");
             }
         }
@@ -788,7 +803,6 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr"),
         _ => write_type(out, ty),
     }
 }
@@ -815,11 +829,10 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) => {
+        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
-        Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -831,11 +844,10 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) => {
+        Type::Str(_) | Type::SliceRefU8(_) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
-        Type::SliceRefU8(_) => write!(out, "::rust::Slice<uint8_t>::Repr "),
         _ => write_type_space(out, &arg.ty),
     }
     if out.types.needs_indirect_abi(&arg.ty) {
diff --git a/include/cxx.h b/include/cxx.h
index 220f45f..45c3828 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -104,20 +104,12 @@ public:
   Slice(const Slice<T> &) noexcept = default;
   ~Slice() noexcept = default;
 
-  // Repr is PRIVATE; must not be used other than by our generated code.
-  //
-  // At present this class is only used for &[u8] slices.
-  // Not necessarily ABI compatible with &[u8]. Codegen will translate to
-  // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
-  struct Repr final {
-    const T *ptr;
-    size_t len;
-  };
-  Slice(Repr) noexcept;
-  explicit operator Repr() const noexcept;
-
 private:
-  Repr repr;
+  friend impl<Slice>;
+  // Not necessarily ABI compatible with &[T]. Codegen will translate to
+  // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
+  const T *ptr;
+  size_t len;
 };
 #endif // CXXBRIDGE05_RUST_SLICE
 
@@ -332,32 +324,24 @@ inline size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE05_RUST_SLICE
 #define CXXBRIDGE05_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : repr(Repr{reinterpret_cast<const T *>(this), 0}) {}
+Slice<T>::Slice() noexcept : ptr(reinterpret_cast<const T *>(this)), len(0) {}
 
 template <typename T>
-Slice<T>::Slice(const T *s, size_t count) noexcept : repr(Repr{s, count}) {}
+Slice<T>::Slice(const T *s, size_t count) noexcept : ptr(s), len(count) {}
 
 template <typename T>
 const T *Slice<T>::data() const noexcept {
-  return this->repr.ptr;
+  return this->ptr;
 }
 
 template <typename T>
 size_t Slice<T>::size() const noexcept {
-  return this->repr.len;
+  return this->len;
 }
 
 template <typename T>
 size_t Slice<T>::length() const noexcept {
-  return this->repr.len;
-}
-
-template <typename T>
-Slice<T>::Slice(Repr repr_) noexcept : repr(repr_) {}
-
-template <typename T>
-Slice<T>::operator Repr() const noexcept {
-  return this->repr;
+  return this->len;
 }
 #endif // CXXBRIDGE05_RUST_SLICE
 

From 98f2b5f6cd9b3842f0cd4e37831f9d70cc89cd42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:38:01 +0000
Subject: [PATCH 1155/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index d07cda2..403b275 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.44/src/**"]),
+    srcs = glob(["vendor/syn-1.0.48/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index a539bd2..bdded93 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.44/src/**"]),
+    srcs = glob(["vendor/syn-1.0.48/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 3a32f05..f9c5f60 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -174,9 +174,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.79"
+version = "0.2.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
+checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
 
 [[package]]
 name = "link-cplusplus"
@@ -207,14 +207,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9bdc5e856e51e685846fb6c13a1f5e5432946c2c90501bdc76a1319f19e29da"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
 
 [[package]]
 name = "ryu"
@@ -267,9 +262,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.44"
+version = "1.0.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd"
+checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
 dependencies = [
  "proc-macro2",
  "quote",

From ace45fa9423735accfa303919d49461e7c0a075a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:38:49 +0000
Subject: [PATCH 1156/2232] Re-enable c_take_callback test


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c79aff3..742062d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -169,10 +169,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
-        /*
-        // https://github.com/dtolnay/cxx/issues/232
         fn c_take_callback(callback: fn(String) -> usize);
-        */
         fn c_take_enum(e: Enum);
         fn c_take_ns_enum(e: AEnum);
         fn c_take_nested_ns_enum(e: ABEnum);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4abc456..a03ec2b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -385,12 +385,9 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
-*/
 
 void c_take_enum(Enum e) {
   if (e == Enum::AVal) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6b1ec1e..e551048 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -134,10 +134,7 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
-*/
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
diff --git a/tests/test.rs b/tests/test.rs
index b651feb..a90b8fc 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,8 +149,6 @@ fn test_c_take() {
     check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 #[test]
 fn test_c_callback() {
     fn callback(s: String) -> usize {
@@ -162,7 +160,6 @@ fn test_c_callback() {
 
     check!(ffi::c_take_callback(callback));
 }
-*/
 
 #[test]
 fn test_c_call_r() {

From b8ebeb0e8406e3a8cb20795e1e90fdc43e9ce492 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 06:54:26 +0000
Subject: [PATCH 1157/2232] Fix fn arg representation to eliminate warning on rust 1.46+


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bcaa1e..b25d830 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -594,7 +594,7 @@ fn expand_rust_function_shim_impl(
                 quote!(#receiver_type::#ident)
             }
         },
-        None => quote!(__extern),
+        None => quote!(::std::mem::transmute::<*const (), #sig>(__extern)),
     };
     call.extend(quote! { (#(#vars),*) });
 
@@ -662,7 +662,7 @@ fn expand_rust_function_shim_impl(
     };
 
     let pointer = match invoke {
-        None => Some(quote!(__extern: #sig)),
+        None => Some(quote!(__extern: *const ())),
         Some(_) => None,
     };
 

From 7fa9d633365eca13acf47505f74849054ce32735 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:01:32 +0000
Subject: [PATCH 1158/2232] Merge pull request #396 from dtolnay/fn


Fix fn arg representation to eliminate warning on rust 1.46+
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1bcaa1e..b25d830 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -594,7 +594,7 @@ fn expand_rust_function_shim_impl(
                 quote!(#receiver_type::#ident)
             }
         },
-        None => quote!(__extern),
+        None => quote!(::std::mem::transmute::<*const (), #sig>(__extern)),
     };
     call.extend(quote! { (#(#vars),*) });
 
@@ -662,7 +662,7 @@ fn expand_rust_function_shim_impl(
     };
 
     let pointer = match invoke {
-        None => Some(quote!(__extern: #sig)),
+        None => Some(quote!(__extern: *const ())),
         Some(_) => None,
     };
 
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c79aff3..742062d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -169,10 +169,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
-        /*
-        // https://github.com/dtolnay/cxx/issues/232
         fn c_take_callback(callback: fn(String) -> usize);
-        */
         fn c_take_enum(e: Enum);
         fn c_take_ns_enum(e: AEnum);
         fn c_take_nested_ns_enum(e: ABEnum);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4abc456..a03ec2b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -385,12 +385,9 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
-*/
 
 void c_take_enum(Enum e) {
   if (e == Enum::AVal) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6b1ec1e..e551048 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -134,10 +134,7 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
-/*
-// https://github.com/dtolnay/cxx/issues/232
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
-*/
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
diff --git a/tests/test.rs b/tests/test.rs
index b651feb..a90b8fc 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,8 +149,6 @@ fn test_c_take() {
     check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal));
 }
 
-/*
-// https://github.com/dtolnay/cxx/issues/232
 #[test]
 fn test_c_callback() {
     fn callback(s: String) -> usize {
@@ -162,7 +160,6 @@ fn test_c_callback() {
 
     check!(ffi::c_take_callback(callback));
 }
-*/
 
 #[test]
 fn test_c_call_r() {

From 1192653a45bfd4e7fef7767a03b399070eaf5824 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:06:10 +0000
Subject: [PATCH 1159/2232] Move proc-macro2 fallback to before starting to parse


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index d79a465..ac8224e 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -102,12 +102,12 @@ fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
         let shebang_end = source.find('\n').unwrap_or(source.len());
         source = &source[shebang_end..];
     }
+    proc_macro2::fallback::force();
     let syntax: File = syn::parse_str(source)?;
     generate(syntax, opt)
 }
 
 pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
-    proc_macro2::fallback::force();
     let ref mut errors = Errors::new();
     let bridge = syntax
         .modules

From 9ca2ff26d23e4aa4526880bc88448bf89f67caa8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:10:47 +0000
Subject: [PATCH 1160/2232] Wrap gen::generate comment to 80 columns


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index ac8224e..33ab9c9 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -122,9 +122,9 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     errors.propagate()?;
     check::typecheck(errors, apis, types);
     errors.propagate()?;
-    // Some callers may wish to generate both header and C++
-    // from the same token stream to avoid parsing twice. But others
-    // only need to generate one or the other.
+    // Some callers may wish to generate both header and implementation from the
+    // same token stream to avoid parsing twice. Others only need to generate
+    // one or the other.
     Ok(GeneratedCode {
         header: if opt.gen_header {
             write::gen(apis, types, opt, true).content()

From 42e0d6fecd08c33f2c3246261826067b238d99d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:11:07 +0000
Subject: [PATCH 1161/2232] Collect apis from multiple cxx::bridge in the same file


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 33ab9c9..9b732d2 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -108,20 +108,24 @@ fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
 }
 
 pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
+    if syntax.modules.is_empty() {
+        return Err(Error::NoBridgeMod);
+    }
+
+    let ref mut apis = Vec::new();
     let ref mut errors = Errors::new();
-    let bridge = syntax
-        .modules
-        .into_iter()
-        .next()
-        .ok_or(Error::NoBridgeMod)?;
-    let ref namespace = bridge.namespace;
-    let trusted = bridge.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
+    for bridge in syntax.modules {
+        let ref namespace = bridge.namespace;
+        let trusted = bridge.unsafety.is_some();
+        apis.extend(syntax::parse_items(errors, bridge.content, trusted, namespace));
+    }
+
     let ref types = Types::collect(errors, apis);
     check::precheck(errors, apis, opt);
     errors.propagate()?;
     check::typecheck(errors, apis, types);
     errors.propagate()?;
+
     // Some callers may wish to generate both header and implementation from the
     // same token stream to avoid parsing twice. Others only need to generate
     // one or the other.

From 299731330ce9c69d64b42365817c3c662b3eb0fb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:25:16 +0000
Subject: [PATCH 1162/2232] Merge pull request #397 from dtolnay/multiple


Collect apis from multiple cxx::bridge in the same file
---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 33ab9c9..9b732d2 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -108,20 +108,24 @@ fn generate_from_string(source: &str, opt: &Opt) -> Result<GeneratedCode> {
 }
 
 pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
+    if syntax.modules.is_empty() {
+        return Err(Error::NoBridgeMod);
+    }
+
+    let ref mut apis = Vec::new();
     let ref mut errors = Errors::new();
-    let bridge = syntax
-        .modules
-        .into_iter()
-        .next()
-        .ok_or(Error::NoBridgeMod)?;
-    let ref namespace = bridge.namespace;
-    let trusted = bridge.unsafety.is_some();
-    let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
+    for bridge in syntax.modules {
+        let ref namespace = bridge.namespace;
+        let trusted = bridge.unsafety.is_some();
+        apis.extend(syntax::parse_items(errors, bridge.content, trusted, namespace));
+    }
+
     let ref types = Types::collect(errors, apis);
     check::precheck(errors, apis, opt);
     errors.propagate()?;
     check::typecheck(errors, apis, types);
     errors.propagate()?;
+
     // Some callers may wish to generate both header and implementation from the
     // same token stream to avoid parsing twice. Others only need to generate
     // one or the other.

From f6fa7b1a2221301bfec450bd8bcf47e489b1f641 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 07:29:46 +0000
Subject: [PATCH 1163/2232] Skip ui tests on macOS builder too


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 50c9b65..f8f66dc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,12 +35,13 @@ jobs:
         with:
           toolchain: ${{matrix.rust}}
       - name: Determine test suite subset
-        # Our Windows jobs are the longest running, so exclude the relatively
-        # slow compiletest from them to speed up end-to-end CI time, except
-        # during cron builds when no human is presumably waiting on the build.
-        # The extra coverage is not particularly valuable and we can still
-        # ensure the test is kept passing on the basis of the scheduled builds.
-        if: matrix.os == 'windows' && github.event_name != 'schedule'
+        # Our Windows and macOS jobs are the longest running, so exclude the
+        # relatively slow compiletest from them to speed up end-to-end CI time,
+        # except during cron builds when no human is presumably waiting on the
+        # build. The extra coverage is not particularly valuable and we can
+        # still ensure the test is kept passing on the basis of the scheduled
+        # builds.
+        if: matrix.os && github.event_name != 'schedule'
         run: echo '::set-env name=RUSTFLAGS::--cfg skip_ui_tests'
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite

From 7907966838d67d1ada820ea4c056251abfc41185 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 17:12:05 +0000
Subject: [PATCH 1164/2232] Switch to namespace = "quoted::path" in docs and tests


To preserve parity with item-level #[namespace = "..."] which is
currently restricted by rustc to a quoted string.

---

diff --git a/demo/src/main.rs b/demo/src/main.rs
index ee7e093..8f62084 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -1,4 +1,4 @@
-#[cxx::bridge(namespace = org::example)]
+#[cxx::bridge(namespace = "org::example")]
 mod ffi {
     struct SharedThing {
         z: i32,
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 4d9b986..3796431 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -32,7 +32,7 @@ use syn::parse_macro_input;
 /// attribute macro.
 ///
 /// ```
-/// #[cxx::bridge(namespace = mycompany::rust)]
+/// #[cxx::bridge(namespace = "mycompany::rust")]
 /// # mod ffi {}
 /// ```
 ///
diff --git a/src/extern_type.rs b/src/extern_type.rs
index b9c5386..f92ff40 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -28,7 +28,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// ```no_run
 /// // file1.rs
 /// # mod file1 {
-/// #[cxx::bridge(namespace = example)]
+/// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
 ///     extern "C" {
 ///         type Demo;
@@ -39,7 +39,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// # }
 ///
 /// // file2.rs
-/// #[cxx::bridge(namespace = example)]
+/// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
 ///     extern "C" {
 ///         type Demo = crate::file1::ffi::Demo;
@@ -78,7 +78,7 @@ use self::kind::{Kind, Opaque, Trivial};
 ///     type Kind = cxx::kind::Opaque;
 /// }
 ///
-/// #[cxx::bridge(namespace = folly)]
+/// #[cxx::bridge(namespace = "folly")]
 /// pub mod ffi {
 ///     extern "C" {
 ///         include!("rust_cxx_bindings.h");
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index a11970d..cd76a7d 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -8,7 +8,7 @@
 // Rustfmt mangles the extern type alias.
 // https://github.com/rust-lang/rustfmt/issues/4159
 #[rustfmt::skip]
-#[cxx::bridge(namespace = tests)]
+#[cxx::bridge(namespace = "tests")]
 pub mod ffi2 {
     impl UniquePtr<D> {}
     impl UniquePtr<E> {}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 742062d..f40ec6c 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -62,7 +62,7 @@ mod other {
     }
 }
 
-#[cxx::bridge(namespace = tests)]
+#[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     #[derive(Clone)]
     struct Shared {
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 77bae06..899d45b 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,7 +1,7 @@
 // Rustfmt mangles the extern type alias.
 // https://github.com/rust-lang/rustfmt/issues/4159
 #[rustfmt::skip]
-#[cxx::bridge(namespace = tests)]
+#[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     extern "C" {
         include!("tests/ffi/tests.h");
diff --git a/tests/ui/wrong_type_id.rs b/tests/ui/wrong_type_id.rs
index 81a9b3f..e3d1380 100644
--- a/tests/ui/wrong_type_id.rs
+++ b/tests/ui/wrong_type_id.rs
@@ -1,11 +1,11 @@
-#[cxx::bridge(namespace = folly)]
+#[cxx::bridge(namespace = "folly")]
 mod here {
     extern "C" {
         type StringPiece;
     }
 }
 
-#[cxx::bridge(namespace = folly)]
+#[cxx::bridge(namespace = "folly")]
 mod there {
     extern "C" {
         type ByteRange = crate::here::StringPiece;

From 159e712a542017e96dad3563b39717041c233425 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:35:44 +0000
Subject: [PATCH 1165/2232] Format with rustfmt 1.4.22-beta


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 9b732d2..453f47b 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -117,7 +117,12 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     for bridge in syntax.modules {
         let ref namespace = bridge.namespace;
         let trusted = bridge.unsafety.is_some();
-        apis.extend(syntax::parse_items(errors, bridge.content, trusted, namespace));
+        apis.extend(syntax::parse_items(
+            errors,
+            bridge.content,
+            trusted,
+            namespace,
+        ));
     }
 
     let ref types = Types::collect(errors, apis);

From f9d34a11ed565d8818497879de42c02e0d11daeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:35:53 +0000
Subject: [PATCH 1166/2232] Allow non-static string used as block header


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 99aecc2..337bc93 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -16,7 +16,7 @@ pub(crate) struct OutFile<'a> {
 pub struct Content {
     bytes: String,
     section_pending: bool,
-    blocks_pending: Vec<&'static str>,
+    blocks_pending: Vec<String>,
 }
 
 impl<'a> OutFile<'a> {
@@ -35,11 +35,11 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().next_section();
     }
 
-    pub fn begin_block(&mut self, block: &'static str) {
+    pub fn begin_block(&mut self, block: &str) {
         self.content.get_mut().begin_block(block);
     }
 
-    pub fn end_block(&mut self, block: &'static str) {
+    pub fn end_block(&mut self, block: &str) {
         self.content.get_mut().end_block(block);
     }
 
@@ -92,11 +92,11 @@ impl Content {
         self.section_pending = true;
     }
 
-    pub fn begin_block(&mut self, block: &'static str) {
-        self.blocks_pending.push(block);
+    pub fn begin_block(&mut self, block: &str) {
+        self.blocks_pending.push(block.to_owned());
     }
 
-    pub fn end_block(&mut self, block: &'static str) {
+    pub fn end_block(&mut self, block: &str) {
         if self.blocks_pending.pop().is_none() {
             self.bytes.push_str("} // ");
             self.bytes.push_str(block);
@@ -116,7 +116,7 @@ impl Content {
                     self.bytes.push('\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    self.bytes.push_str(block);
+                    self.bytes.push_str(&block);
                     self.bytes.push_str(" {\n");
                 }
                 self.section_pending = false;

From 9de98d40eeb5313fc8e4bb0787e85f095410eaa4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:35:54 +0000
Subject: [PATCH 1167/2232] Clean up section spacing around namespace entries


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 194241a..9046d69 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -22,7 +22,6 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
     out.include.extend(&opt.include);
 
     let apis_by_namespace = NamespaceEntries::new(apis);
-
     gen_namespace_forward_declarations(out, &apis_by_namespace);
     gen_namespace_contents(out, &apis_by_namespace, opt);
 
@@ -132,12 +131,11 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
         }
     }
 
-    out.next_section();
-
     for (child_ns, child_ns_entries) in ns_entries.children() {
-        writeln!(out, "namespace {} {{", child_ns);
+        let block = format!("namespace {}", child_ns);
+        out.begin_block(&block);
         gen_namespace_contents(out, child_ns_entries, opt);
-        writeln!(out, "}} // namespace {}", child_ns);
+        out.end_block(&block);
     }
 }
 

From fe40ff2b2811efe4ed0fc8dad9279f087626268c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:35:54 +0000
Subject: [PATCH 1168/2232] Tighten spacing in between forward declarations


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9046d69..7c6d098 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -39,7 +39,6 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     let apis = ns_entries.entries();
 
-    out.next_section();
     for api in apis {
         match api {
             Api::Include(include) => out.include.insert(include),
@@ -50,8 +49,6 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
         }
     }
 
-    out.next_section();
-
     for (child_ns, child_ns_entries) in ns_entries.children() {
         writeln!(out, "namespace {} {{", child_ns);
         gen_namespace_forward_declarations(out, child_ns_entries);

From 60e7aa67e28f3cd81a63fa6b9d5198d4f232e738 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:37:28 +0000
Subject: [PATCH 1169/2232] Move non-boilerplate impls out of impls.rs


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index f4c5b05..a4b393a 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,13 +1,8 @@
-use crate::syntax::{
-    Api, CppName, ExternFn, Impl, Include, Namespace, Pair, Receiver, Ref, ResolvableName,
-    Signature, Slice, Symbol, Ty1, Type, Types,
-};
-use proc_macro2::{Ident, Span};
+use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
-use syn::Token;
 
 impl PartialEq for Include {
     fn eq(&self, other: &Include) -> bool {
@@ -297,86 +292,3 @@ impl Borrow<Type> for &Impl {
         &self.ty
     }
 }
-
-impl Pair {
-    /// Use this constructor when the item can't have a different
-    /// name in Rust and C++.
-    pub fn new(ns: Namespace, ident: Ident) -> Self {
-        Self {
-            rust: ident.clone(),
-            cxx: CppName::new(ns, ident),
-        }
-    }
-
-    /// 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(ns: Namespace, cxx_ident: Ident, rust_ident: Ident) -> Self {
-        Self {
-            rust: rust_ident,
-            cxx: CppName::new(ns, cxx_ident),
-        }
-    }
-}
-
-impl ResolvableName {
-    pub fn new(ident: Ident) -> Self {
-        Self { rust: ident }
-    }
-
-    pub fn make_self(span: Span) -> Self {
-        Self {
-            rust: Token![Self](span).into(),
-        }
-    }
-
-    pub fn is_self(&self) -> bool {
-        self.rust == "Self"
-    }
-
-    pub fn span(&self) -> Span {
-        self.rust.span()
-    }
-
-    pub fn to_symbol(&self, types: &Types) -> Symbol {
-        types.resolve(self).to_symbol()
-    }
-}
-
-impl Api {
-    pub fn get_namespace(&self) -> Option<&Namespace> {
-        match self {
-            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
-            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
-            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
-            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
-            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
-            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
-            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
-        }
-    }
-}
-
-impl CppName {
-    pub fn new(ns: Namespace, ident: Ident) -> Self {
-        Self { ns, ident }
-    }
-
-    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
-        self.ns.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/mod.rs b/syntax/mod.rs
index 8d3b8a2..90af17f 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -11,6 +11,7 @@ pub mod file;
 pub mod ident;
 mod impls;
 pub mod mangle;
+mod names;
 pub mod namespace;
 mod parse;
 pub mod qualified;
diff --git a/syntax/names.rs b/syntax/names.rs
new file mode 100644
index 0000000..a61ffc3
--- /dev/null
+++ b/syntax/names.rs
@@ -0,0 +1,72 @@
+use crate::syntax::{CppName, Namespace, Pair, ResolvableName, Symbol, Types};
+use proc_macro2::{Ident, Span};
+use syn::Token;
+
+impl Pair {
+    /// Use this constructor when the item can't have a different
+    /// name in Rust and C++.
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self {
+            rust: ident.clone(),
+            cxx: CppName::new(ns, ident),
+        }
+    }
+
+    /// 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(ns: Namespace, cxx_ident: Ident, rust_ident: Ident) -> Self {
+        Self {
+            rust: rust_ident,
+            cxx: CppName::new(ns, cxx_ident),
+        }
+    }
+}
+
+impl ResolvableName {
+    pub fn new(ident: Ident) -> Self {
+        Self { rust: ident }
+    }
+
+    pub fn make_self(span: Span) -> Self {
+        Self {
+            rust: Token![Self](span).into(),
+        }
+    }
+
+    pub fn is_self(&self) -> bool {
+        self.rust == "Self"
+    }
+
+    pub fn span(&self) -> Span {
+        self.rust.span()
+    }
+
+    pub fn to_symbol(&self, types: &Types) -> Symbol {
+        types.resolve(self).to_symbol()
+    }
+}
+
+impl CppName {
+    pub fn new(ns: Namespace, ident: Ident) -> Self {
+        Self { ns, ident }
+    }
+
+    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
+        self.ns.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/namespace.rs b/syntax/namespace.rs
index 5eb203a..41a38dd 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,4 +1,5 @@
 use crate::syntax::qualified::QualifiedName;
+use crate::syntax::Api;
 #[cfg(test)]
 use proc_macro2::Span;
 use quote::IdentFragment;
@@ -79,3 +80,17 @@ impl<'a> IntoIterator for &'a Namespace {
         self.iter()
     }
 }
+
+impl Api {
+    pub fn get_namespace(&self) -> Option<&Namespace> {
+        match self {
+            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
+            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
+            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
+            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
+            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
+            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
+            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
+        }
+    }
+}

From 6ec411103838868dc72f836f757206e8ffbaf4d3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:40:38 +0000
Subject: [PATCH 1170/2232] Condense get_namespace's match


---

diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 41a38dd..5f368e8 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -84,12 +84,10 @@ impl<'a> IntoIterator for &'a Namespace {
 impl Api {
     pub fn get_namespace(&self) -> Option<&Namespace> {
         match self {
-            Api::CxxFunction(cfn) => Some(&cfn.ident.cxx.ns),
-            Api::CxxType(cty) => Some(&cty.ident.cxx.ns),
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.ns),
+            Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.ns),
             Api::Enum(enm) => Some(&enm.ident.cxx.ns),
             Api::Struct(strct) => Some(&strct.ident.cxx.ns),
-            Api::RustType(rty) => Some(&rty.ident.cxx.ns),
-            Api::RustFunction(rfn) => Some(&rfn.ident.cxx.ns),
             Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
         }
     }

From 68a12180a86f66e4c72138ad70e4e3dc9833ec8e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:42:03 +0000
Subject: [PATCH 1171/2232] Clean up get_ prefix from accessor method name


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index 525c367..59a58ad 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -29,7 +29,7 @@ impl<'a> NamespaceEntries<'a> {
 
         let mut kids_by_child_ns = BTreeMap::new();
         for api in apis {
-            if let Some(ns) = api.get_namespace() {
+            if let Some(ns) = api.namespace() {
                 let first_ns_elem = ns.iter().nth(depth);
                 if let Some(first_ns_elem) = first_ns_elem {
                     let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 5f368e8..4a37f7a 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -82,7 +82,7 @@ impl<'a> IntoIterator for &'a Namespace {
 }
 
 impl Api {
-    pub fn get_namespace(&self) -> Option<&Namespace> {
+    pub fn namespace(&self) -> Option<&Namespace> {
         match self {
             Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.ns),
             Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.ns),

From f8df1bed74a624d66613017bdd6a94c3fd7b693a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:44:36 +0000
Subject: [PATCH 1172/2232] Condense an iter + collect into from_iter


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index 59a58ad..aaf0722 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -1,6 +1,7 @@
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
+use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
     entries: Vec<&'a Api>,
@@ -9,7 +10,7 @@ pub struct NamespaceEntries<'a> {
 
 impl<'a> NamespaceEntries<'a> {
     pub fn new(apis: &'a [Api]) -> Self {
-        let api_refs = apis.iter().collect::<Vec<_>>();
+        let api_refs = Vec::from_iter(apis);
         Self::sort_by_inner_namespace(api_refs, 0)
     }
 

From 9e4e7504a05f745ad918a7adf16fb2f13d3e1a64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:47:42 +0000
Subject: [PATCH 1173/2232] Clarify the distinction of NamespaceEntries contents


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index aaf0722..b4c8a93 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -4,8 +4,8 @@ use std::collections::BTreeMap;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
-    entries: Vec<&'a Api>,
-    children: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+    direct: Vec<&'a Api>,
+    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
 
 impl<'a> NamespaceEntries<'a> {
@@ -14,18 +14,18 @@ impl<'a> NamespaceEntries<'a> {
         Self::sort_by_inner_namespace(api_refs, 0)
     }
 
-    pub fn entries(&self) -> &[&'a Api] {
-        &self.entries
+    pub fn direct_content(&self) -> &[&'a Api] {
+        &self.direct
     }
 
-    pub fn children(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
-        self.children.iter().map(|(k, entries)| (*k, entries))
+    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
+        self.nested.iter().map(|(k, entries)| (*k, entries))
     }
 
     fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
         let mut root = NamespaceEntries {
-            entries: Vec::new(),
-            children: BTreeMap::new(),
+            direct: Vec::new(),
+            nested: BTreeMap::new(),
         };
 
         let mut kids_by_child_ns = BTreeMap::new();
@@ -38,11 +38,11 @@ impl<'a> NamespaceEntries<'a> {
                     continue;
                 }
             }
-            root.entries.push(api);
+            root.direct.push(api);
         }
 
         for (k, v) in kids_by_child_ns.into_iter() {
-            root.children
+            root.nested
                 .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
         }
 
@@ -73,32 +73,32 @@ mod tests {
             make_api(Some("D"), "J"),
         ];
         let ns = NamespaceEntries::new(&entries);
-        let root_entries = ns.entries();
+        let root_entries = ns.direct_content();
         assert_eq!(root_entries.len(), 3);
         assert_ident(root_entries[0], "C");
         assert_ident(root_entries[1], "A");
         assert_ident(root_entries[2], "B");
-        let mut kids = ns.children();
+        let mut kids = ns.nested_content();
         let (d_id, d_nse) = kids.next().unwrap();
         assert_eq!(d_id.to_string(), "D");
         let (g_id, g_nse) = kids.next().unwrap();
         assert_eq!(g_id.to_string(), "G");
         assert!(kids.next().is_none());
-        let d_nse_entries = d_nse.entries();
+        let d_nse_entries = d_nse.direct_content();
         assert_eq!(d_nse_entries.len(), 3);
         assert_ident(d_nse_entries[0], "F");
         assert_ident(d_nse_entries[1], "I");
         assert_ident(d_nse_entries[2], "J");
-        let g_nse_entries = g_nse.entries();
+        let g_nse_entries = g_nse.direct_content();
         assert_eq!(g_nse_entries.len(), 2);
         assert_ident(g_nse_entries[0], "E");
         assert_ident(g_nse_entries[1], "H");
-        let mut g_kids = g_nse.children();
+        let mut g_kids = g_nse.nested_content();
         assert!(g_kids.next().is_none());
-        let mut d_kids = d_nse.children();
+        let mut d_kids = d_nse.nested_content();
         let (k_id, k_nse) = d_kids.next().unwrap();
         assert_eq!(k_id.to_string(), "K");
-        let k_nse_entries = k_nse.entries();
+        let k_nse_entries = k_nse.direct_content();
         assert_eq!(k_nse_entries.len(), 2);
         assert_ident(k_nse_entries[0], "L");
         assert_ident(k_nse_entries[1], "M");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7c6d098..5ca3dc5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -37,7 +37,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 }
 
 fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
-    let apis = ns_entries.entries();
+    let apis = ns_entries.direct_content();
 
     for api in apis {
         match api {
@@ -49,7 +49,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
         }
     }
 
-    for (child_ns, child_ns_entries) in ns_entries.children() {
+    for (child_ns, child_ns_entries) in ns_entries.nested_content() {
         writeln!(out, "namespace {} {{", child_ns);
         gen_namespace_forward_declarations(out, child_ns_entries);
         writeln!(out, "}} // namespace {}", child_ns);
@@ -57,7 +57,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
 }
 
 fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt: &Opt) {
-    let apis = ns_entries.entries();
+    let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
     for api in apis {
@@ -128,7 +128,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
         }
     }
 
-    for (child_ns, child_ns_entries) in ns_entries.children() {
+    for (child_ns, child_ns_entries) in ns_entries.nested_content() {
         let block = format!("namespace {}", child_ns);
         out.begin_block(&block);
         gen_namespace_contents(out, child_ns_entries, opt);

From 7943e504d9d0e9af66200903232f0f4fda827cab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 20:51:31 +0000
Subject: [PATCH 1174/2232] Remove 'child' naming


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5ca3dc5..9f57f7d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -49,10 +49,10 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
         }
     }
 
-    for (child_ns, child_ns_entries) in ns_entries.nested_content() {
-        writeln!(out, "namespace {} {{", child_ns);
-        gen_namespace_forward_declarations(out, child_ns_entries);
-        writeln!(out, "}} // namespace {}", child_ns);
+    for (namespace, nested_ns_entries) in ns_entries.nested_content() {
+        writeln!(out, "namespace {} {{", namespace);
+        gen_namespace_forward_declarations(out, nested_ns_entries);
+        writeln!(out, "}} // namespace {}", namespace);
     }
 }
 
@@ -128,10 +128,10 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
         }
     }
 
-    for (child_ns, child_ns_entries) in ns_entries.nested_content() {
-        let block = format!("namespace {}", child_ns);
+    for (namespace, nested_ns_entries) in ns_entries.nested_content() {
+        let block = format!("namespace {}", namespace);
         out.begin_block(&block);
-        gen_namespace_contents(out, child_ns_entries, opt);
+        gen_namespace_contents(out, nested_ns_entries, opt);
         out.end_block(&block);
     }
 }

From ef796967e88117d037b8e2d37c39ea9dcaa77504 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:01:33 +0000
Subject: [PATCH 1175/2232] Remove 'kids' naming


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index b4c8a93..ed3c91f 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -28,12 +28,12 @@ impl<'a> NamespaceEntries<'a> {
             nested: BTreeMap::new(),
         };
 
-        let mut kids_by_child_ns = BTreeMap::new();
+        let mut nested_namespaces = BTreeMap::new();
         for api in apis {
             if let Some(ns) = api.namespace() {
                 let first_ns_elem = ns.iter().nth(depth);
                 if let Some(first_ns_elem) = first_ns_elem {
-                    let list = kids_by_child_ns.entry(first_ns_elem).or_insert(Vec::new());
+                    let list = nested_namespaces.entry(first_ns_elem).or_insert(Vec::new());
                     list.push(api);
                     continue;
                 }
@@ -41,7 +41,7 @@ impl<'a> NamespaceEntries<'a> {
             root.direct.push(api);
         }
 
-        for (k, v) in kids_by_child_ns.into_iter() {
+        for (k, v) in nested_namespaces.into_iter() {
             root.nested
                 .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
         }

From 945c3cb9032b9ec239b2ce2ed9dd3fe35ed334cc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:05:01 +0000
Subject: [PATCH 1176/2232] Touch up sort_by_inner_namespace implementation


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index ed3c91f..16beba1 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -23,30 +23,28 @@ impl<'a> NamespaceEntries<'a> {
     }
 
     fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
-        let mut root = NamespaceEntries {
-            direct: Vec::new(),
-            nested: BTreeMap::new(),
-        };
-
+        let mut direct = Vec::new();
         let mut nested_namespaces = BTreeMap::new();
         for api in apis {
             if let Some(ns) = api.namespace() {
                 let first_ns_elem = ns.iter().nth(depth);
                 if let Some(first_ns_elem) = first_ns_elem {
-                    let list = nested_namespaces.entry(first_ns_elem).or_insert(Vec::new());
-                    list.push(api);
+                    nested_namespaces
+                        .entry(first_ns_elem)
+                        .or_insert_with(Vec::new)
+                        .push(api);
                     continue;
                 }
             }
-            root.direct.push(api);
+            direct.push(api);
         }
 
-        for (k, v) in nested_namespaces.into_iter() {
-            root.nested
-                .insert(k, Self::sort_by_inner_namespace(v, depth + 1));
-        }
+        let nested = nested_namespaces
+            .into_iter()
+            .map(|(k, apis)| (k, Self::sort_by_inner_namespace(apis, depth + 1)))
+            .collect();
 
-        root
+        NamespaceEntries { direct, nested }
     }
 }
 

From 73de7d0d527a2ae01810876a88d5ae9a3c468657 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:07:21 +0000
Subject: [PATCH 1177/2232] Detach sort_by_inner_namespace from NamespaceEntries


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index 16beba1..ce63de5 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -11,7 +11,7 @@ pub struct NamespaceEntries<'a> {
 impl<'a> NamespaceEntries<'a> {
     pub fn new(apis: &'a [Api]) -> Self {
         let api_refs = Vec::from_iter(apis);
-        Self::sort_by_inner_namespace(api_refs, 0)
+        sort_by_inner_namespace(api_refs, 0)
     }
 
     pub fn direct_content(&self) -> &[&'a Api] {
@@ -21,31 +21,31 @@ impl<'a> NamespaceEntries<'a> {
     pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
         self.nested.iter().map(|(k, entries)| (*k, entries))
     }
+}
 
-    fn sort_by_inner_namespace(apis: Vec<&'a Api>, depth: usize) -> Self {
-        let mut direct = Vec::new();
-        let mut nested_namespaces = BTreeMap::new();
-        for api in apis {
-            if let Some(ns) = api.namespace() {
-                let first_ns_elem = ns.iter().nth(depth);
-                if let Some(first_ns_elem) = first_ns_elem {
-                    nested_namespaces
-                        .entry(first_ns_elem)
-                        .or_insert_with(Vec::new)
-                        .push(api);
-                    continue;
-                }
+fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
+    let mut direct = Vec::new();
+    let mut nested_namespaces = BTreeMap::new();
+    for api in apis {
+        if let Some(ns) = api.namespace() {
+            let first_ns_elem = ns.iter().nth(depth);
+            if let Some(first_ns_elem) = first_ns_elem {
+                nested_namespaces
+                    .entry(first_ns_elem)
+                    .or_insert_with(Vec::new)
+                    .push(api);
+                continue;
             }
-            direct.push(api);
         }
+        direct.push(api);
+    }
 
-        let nested = nested_namespaces
-            .into_iter()
-            .map(|(k, apis)| (k, Self::sort_by_inner_namespace(apis, depth + 1)))
-            .collect();
+    let nested = nested_namespaces
+        .into_iter()
+        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
+        .collect();
 
-        NamespaceEntries { direct, nested }
-    }
+    NamespaceEntries { direct, nested }
 }
 
 #[cfg(test)]

From caab991cbcd96e3d62c965eb7101604526137a4e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:22:40 +0000
Subject: [PATCH 1178/2232] Clean up namespace_organizer unit test


---

diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
index ce63de5..343acf7 100644
--- a/gen/src/namespace_organizer.rs
+++ b/gen/src/namespace_organizer.rs
@@ -58,7 +58,7 @@ mod tests {
 
     #[test]
     fn test_ns_entries_sort() {
-        let entries = vec![
+        let apis = &[
             make_api(None, "C"),
             make_api(None, "A"),
             make_api(Some("G"), "E"),
@@ -70,58 +70,66 @@ mod tests {
             make_api(Some("D"), "I"),
             make_api(Some("D"), "J"),
         ];
-        let ns = NamespaceEntries::new(&entries);
-        let root_entries = ns.direct_content();
-        assert_eq!(root_entries.len(), 3);
-        assert_ident(root_entries[0], "C");
-        assert_ident(root_entries[1], "A");
-        assert_ident(root_entries[2], "B");
-        let mut kids = ns.nested_content();
-        let (d_id, d_nse) = kids.next().unwrap();
-        assert_eq!(d_id.to_string(), "D");
-        let (g_id, g_nse) = kids.next().unwrap();
-        assert_eq!(g_id.to_string(), "G");
-        assert!(kids.next().is_none());
-        let d_nse_entries = d_nse.direct_content();
-        assert_eq!(d_nse_entries.len(), 3);
-        assert_ident(d_nse_entries[0], "F");
-        assert_ident(d_nse_entries[1], "I");
-        assert_ident(d_nse_entries[2], "J");
-        let g_nse_entries = g_nse.direct_content();
-        assert_eq!(g_nse_entries.len(), 2);
-        assert_ident(g_nse_entries[0], "E");
-        assert_ident(g_nse_entries[1], "H");
-        let mut g_kids = g_nse.nested_content();
-        assert!(g_kids.next().is_none());
-        let mut d_kids = d_nse.nested_content();
-        let (k_id, k_nse) = d_kids.next().unwrap();
-        assert_eq!(k_id.to_string(), "K");
-        let k_nse_entries = k_nse.direct_content();
-        assert_eq!(k_nse_entries.len(), 2);
-        assert_ident(k_nse_entries[0], "L");
-        assert_ident(k_nse_entries[1], "M");
+
+        let root = NamespaceEntries::new(apis);
+
+        // ::
+        let root_direct = root.direct_content();
+        assert_eq!(root_direct.len(), 3);
+        assert_ident(root_direct[0], "C");
+        assert_ident(root_direct[1], "A");
+        assert_ident(root_direct[2], "B");
+
+        let mut root_nested = root.nested_content();
+        let (id, d) = root_nested.next().unwrap();
+        assert_eq!(id, "D");
+        let (id, g) = root_nested.next().unwrap();
+        assert_eq!(id, "G");
+        assert!(root_nested.next().is_none());
+
+        // ::D
+        let d_direct = d.direct_content();
+        assert_eq!(d_direct.len(), 3);
+        assert_ident(d_direct[0], "F");
+        assert_ident(d_direct[1], "I");
+        assert_ident(d_direct[2], "J");
+
+        let mut d_nested = d.nested_content();
+        let (id, k) = d_nested.next().unwrap();
+        assert_eq!(id, "K");
+
+        // ::D::K
+        let k_direct = k.direct_content();
+        assert_eq!(k_direct.len(), 2);
+        assert_ident(k_direct[0], "L");
+        assert_ident(k_direct[1], "M");
+
+        // ::G
+        let g_direct = g.direct_content();
+        assert_eq!(g_direct.len(), 2);
+        assert_ident(g_direct[0], "E");
+        assert_ident(g_direct[1], "H");
+
+        let mut g_nested = g.nested_content();
+        assert!(g_nested.next().is_none());
     }
 
     fn assert_ident(api: &Api, expected: &str) {
         if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.ident.cxx.ident.to_string(), expected);
+            assert_eq!(cxx_type.ident.cxx.ident, expected);
         } else {
             unreachable!()
         }
     }
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
-        let ns = match ns {
-            Some(st) => Namespace::from_str(st),
-            None => Namespace::none(),
-        };
-        let ident = Pair::new(ns, Ident::new(ident, Span::call_site()));
+        let ns = ns.map_or_else(Namespace::none, Namespace::from_str);
         Api::CxxType(ExternType {
             doc: Doc::new(),
             type_token: Token![type](Span::call_site()),
-            ident,
+            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
             semi_token: Token![;](Span::call_site()),
-            trusted: true,
+            trusted: false,
         })
     }
 }

From bd9608fd66fbbcf974799e3f95539962cd60683a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:24:19 +0000
Subject: [PATCH 1179/2232] Move namespace sorter to alphasort module


To make room for an upcoming topological sorter in a toposort module.

---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
new file mode 100644
index 0000000..343acf7
--- /dev/null
+++ b/gen/src/alphasort.rs
@@ -0,0 +1,135 @@
+use crate::syntax::Api;
+use proc_macro2::Ident;
+use std::collections::BTreeMap;
+use std::iter::FromIterator;
+
+pub struct NamespaceEntries<'a> {
+    direct: Vec<&'a Api>,
+    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+}
+
+impl<'a> NamespaceEntries<'a> {
+    pub fn new(apis: &'a [Api]) -> Self {
+        let api_refs = Vec::from_iter(apis);
+        sort_by_inner_namespace(api_refs, 0)
+    }
+
+    pub fn direct_content(&self) -> &[&'a Api] {
+        &self.direct
+    }
+
+    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
+        self.nested.iter().map(|(k, entries)| (*k, entries))
+    }
+}
+
+fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
+    let mut direct = Vec::new();
+    let mut nested_namespaces = BTreeMap::new();
+    for api in apis {
+        if let Some(ns) = api.namespace() {
+            let first_ns_elem = ns.iter().nth(depth);
+            if let Some(first_ns_elem) = first_ns_elem {
+                nested_namespaces
+                    .entry(first_ns_elem)
+                    .or_insert_with(Vec::new)
+                    .push(api);
+                continue;
+            }
+        }
+        direct.push(api);
+    }
+
+    let nested = nested_namespaces
+        .into_iter()
+        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
+        .collect();
+
+    NamespaceEntries { direct, nested }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::NamespaceEntries;
+    use crate::syntax::namespace::Namespace;
+    use crate::syntax::{Api, Doc, ExternType, Pair};
+    use proc_macro2::{Ident, Span};
+    use syn::Token;
+
+    #[test]
+    fn test_ns_entries_sort() {
+        let apis = &[
+            make_api(None, "C"),
+            make_api(None, "A"),
+            make_api(Some("G"), "E"),
+            make_api(Some("D"), "F"),
+            make_api(Some("G"), "H"),
+            make_api(Some("D::K"), "L"),
+            make_api(Some("D::K"), "M"),
+            make_api(None, "B"),
+            make_api(Some("D"), "I"),
+            make_api(Some("D"), "J"),
+        ];
+
+        let root = NamespaceEntries::new(apis);
+
+        // ::
+        let root_direct = root.direct_content();
+        assert_eq!(root_direct.len(), 3);
+        assert_ident(root_direct[0], "C");
+        assert_ident(root_direct[1], "A");
+        assert_ident(root_direct[2], "B");
+
+        let mut root_nested = root.nested_content();
+        let (id, d) = root_nested.next().unwrap();
+        assert_eq!(id, "D");
+        let (id, g) = root_nested.next().unwrap();
+        assert_eq!(id, "G");
+        assert!(root_nested.next().is_none());
+
+        // ::D
+        let d_direct = d.direct_content();
+        assert_eq!(d_direct.len(), 3);
+        assert_ident(d_direct[0], "F");
+        assert_ident(d_direct[1], "I");
+        assert_ident(d_direct[2], "J");
+
+        let mut d_nested = d.nested_content();
+        let (id, k) = d_nested.next().unwrap();
+        assert_eq!(id, "K");
+
+        // ::D::K
+        let k_direct = k.direct_content();
+        assert_eq!(k_direct.len(), 2);
+        assert_ident(k_direct[0], "L");
+        assert_ident(k_direct[1], "M");
+
+        // ::G
+        let g_direct = g.direct_content();
+        assert_eq!(g_direct.len(), 2);
+        assert_ident(g_direct[0], "E");
+        assert_ident(g_direct[1], "H");
+
+        let mut g_nested = g.nested_content();
+        assert!(g_nested.next().is_none());
+    }
+
+    fn assert_ident(api: &Api, expected: &str) {
+        if let Api::CxxType(cxx_type) = api {
+            assert_eq!(cxx_type.ident.cxx.ident, expected);
+        } else {
+            unreachable!()
+        }
+    }
+
+    fn make_api(ns: Option<&str>, ident: &str) -> Api {
+        let ns = ns.map_or_else(Namespace::none, Namespace::from_str);
+        Api::CxxType(ExternType {
+            doc: Doc::new(),
+            type_token: Token![type](Span::call_site()),
+            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            semi_token: Token![;](Span::call_site()),
+            trusted: false,
+        })
+    }
+}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 453f47b..2cd4e56 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,6 +1,7 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
+mod alphasort;
 mod builtin;
 mod check;
 pub(super) mod error;
@@ -8,7 +9,6 @@ mod file;
 pub(super) mod fs;
 mod ifndef;
 pub(super) mod include;
-mod namespace_organizer;
 pub(super) mod out;
 mod write;
 
diff --git a/gen/src/namespace_organizer.rs b/gen/src/namespace_organizer.rs
deleted file mode 100644
index 343acf7..0000000
--- a/gen/src/namespace_organizer.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-use crate::syntax::Api;
-use proc_macro2::Ident;
-use std::collections::BTreeMap;
-use std::iter::FromIterator;
-
-pub struct NamespaceEntries<'a> {
-    direct: Vec<&'a Api>,
-    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
-}
-
-impl<'a> NamespaceEntries<'a> {
-    pub fn new(apis: &'a [Api]) -> Self {
-        let api_refs = Vec::from_iter(apis);
-        sort_by_inner_namespace(api_refs, 0)
-    }
-
-    pub fn direct_content(&self) -> &[&'a Api] {
-        &self.direct
-    }
-
-    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
-        self.nested.iter().map(|(k, entries)| (*k, entries))
-    }
-}
-
-fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
-    let mut direct = Vec::new();
-    let mut nested_namespaces = BTreeMap::new();
-    for api in apis {
-        if let Some(ns) = api.namespace() {
-            let first_ns_elem = ns.iter().nth(depth);
-            if let Some(first_ns_elem) = first_ns_elem {
-                nested_namespaces
-                    .entry(first_ns_elem)
-                    .or_insert_with(Vec::new)
-                    .push(api);
-                continue;
-            }
-        }
-        direct.push(api);
-    }
-
-    let nested = nested_namespaces
-        .into_iter()
-        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
-        .collect();
-
-    NamespaceEntries { direct, nested }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::NamespaceEntries;
-    use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Pair};
-    use proc_macro2::{Ident, Span};
-    use syn::Token;
-
-    #[test]
-    fn test_ns_entries_sort() {
-        let apis = &[
-            make_api(None, "C"),
-            make_api(None, "A"),
-            make_api(Some("G"), "E"),
-            make_api(Some("D"), "F"),
-            make_api(Some("G"), "H"),
-            make_api(Some("D::K"), "L"),
-            make_api(Some("D::K"), "M"),
-            make_api(None, "B"),
-            make_api(Some("D"), "I"),
-            make_api(Some("D"), "J"),
-        ];
-
-        let root = NamespaceEntries::new(apis);
-
-        // ::
-        let root_direct = root.direct_content();
-        assert_eq!(root_direct.len(), 3);
-        assert_ident(root_direct[0], "C");
-        assert_ident(root_direct[1], "A");
-        assert_ident(root_direct[2], "B");
-
-        let mut root_nested = root.nested_content();
-        let (id, d) = root_nested.next().unwrap();
-        assert_eq!(id, "D");
-        let (id, g) = root_nested.next().unwrap();
-        assert_eq!(id, "G");
-        assert!(root_nested.next().is_none());
-
-        // ::D
-        let d_direct = d.direct_content();
-        assert_eq!(d_direct.len(), 3);
-        assert_ident(d_direct[0], "F");
-        assert_ident(d_direct[1], "I");
-        assert_ident(d_direct[2], "J");
-
-        let mut d_nested = d.nested_content();
-        let (id, k) = d_nested.next().unwrap();
-        assert_eq!(id, "K");
-
-        // ::D::K
-        let k_direct = k.direct_content();
-        assert_eq!(k_direct.len(), 2);
-        assert_ident(k_direct[0], "L");
-        assert_ident(k_direct[1], "M");
-
-        // ::G
-        let g_direct = g.direct_content();
-        assert_eq!(g_direct.len(), 2);
-        assert_ident(g_direct[0], "E");
-        assert_ident(g_direct[1], "H");
-
-        let mut g_nested = g.nested_content();
-        assert!(g_nested.next().is_none());
-    }
-
-    fn assert_ident(api: &Api, expected: &str) {
-        if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.ident.cxx.ident, expected);
-        } else {
-            unreachable!()
-        }
-    }
-
-    fn make_api(ns: Option<&str>, ident: &str) -> Api {
-        let ns = ns.map_or_else(Namespace::none, Namespace::from_str);
-        Api::CxxType(ExternType {
-            doc: Doc::new(),
-            type_token: Token![type](Span::call_site()),
-            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
-            semi_token: Token![;](Span::call_site()),
-            trusted: false,
-        })
-    }
-}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9f57f7d..e857d21 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,4 @@
-use crate::gen::namespace_organizer::NamespaceEntries;
+use crate::gen::alphasort::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};

From e1476af7615b4cf7cf6a2810f75e5a13dad9f55c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:49:04 +0000
Subject: [PATCH 1180/2232] Make Opt accessible via OutFile


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 337bc93..6ba44aa 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,11 +1,13 @@
 use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
+use crate::gen::Opt;
 use crate::syntax::Types;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
 
 pub(crate) struct OutFile<'a> {
     pub header: bool,
+    pub opt: &'a Opt,
     pub types: &'a Types<'a>,
     pub include: Includes,
     pub builtin: Builtins,
@@ -20,9 +22,10 @@ pub struct Content {
 }
 
 impl<'a> OutFile<'a> {
-    pub fn new(header: bool, types: &'a Types) -> Self {
+    pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
         OutFile {
             header,
+            opt,
             types,
             include: Includes::new(),
             builtin: Builtins::new(),
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e857d21..dcaec40 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -10,8 +10,8 @@ use crate::syntax::{
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
-pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -> OutFile<'a> {
-    let mut out_file = OutFile::new(header, types);
+pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &'a Opt, header: bool) -> OutFile<'a> {
+    let mut out_file = OutFile::new(header, opt, types);
     let out = &mut out_file;
 
     if header {
@@ -23,7 +23,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &Opt, header: bool) -
 
     let apis_by_namespace = NamespaceEntries::new(apis);
     gen_namespace_forward_declarations(out, &apis_by_namespace);
-    gen_namespace_contents(out, &apis_by_namespace, opt);
+    gen_namespace_contents(out, &apis_by_namespace);
 
     if !header {
         out.next_section();
@@ -56,7 +56,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     }
 }
 
-fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt: &Opt) {
+fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -110,13 +110,13 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
-            let (efn, write): (_, fn(_, _, _)) = match api {
+            let (efn, write): (_, fn(_, _)) = match api {
                 Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
                 Api::RustFunction(efn) => (efn, write_rust_function_decl),
                 _ => continue,
             };
             out.next_section();
-            write(out, efn, &opt.cxx_impl_annotations);
+            write(out, efn);
         }
         out.end_block("extern \"C\"");
     }
@@ -131,7 +131,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries, opt:
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
         let block = format!("namespace {}", namespace);
         out.begin_block(&block);
-        gen_namespace_contents(out, nested_ns_entries, opt);
+        gen_namespace_contents(out, nested_ns_entries);
         out.end_block(&block);
     }
 }
@@ -343,8 +343,8 @@ fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
     }
 }
 
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, impl_annotations: &Option<String>) {
-    if let Some(annotation) = impl_annotations {
+fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
+    if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
     }
     if efn.throws {
@@ -542,7 +542,7 @@ fn write_function_pointer_trampoline(
     write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
 }
 
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, _: &Option<String>) {
+fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn) {
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, indirect_call);

From 047707440c17d07512b53bfd7561fb48e8279d42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 21:52:18 +0000
Subject: [PATCH 1181/2232] Simplify gen_namespace_contents' extern block code


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index dcaec40..c008fcb 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -110,13 +110,11 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
         out.begin_block("extern \"C\"");
         write_exception_glue(out, apis);
         for api in apis {
-            let (efn, write): (_, fn(_, _)) = match api {
-                Api::CxxFunction(efn) => (efn, write_cxx_function_shim),
-                Api::RustFunction(efn) => (efn, write_rust_function_decl),
-                _ => continue,
-            };
-            out.next_section();
-            write(out, efn);
+            match api {
+                Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
+                Api::RustFunction(efn) => write_rust_function_decl(out, efn),
+                _ => {}
+            }
         }
         out.end_block("extern \"C\"");
     }
@@ -344,6 +342,7 @@ fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
 }
 
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
+    out.next_section();
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
     }
@@ -532,7 +531,6 @@ fn write_function_pointer_trampoline(
     var: &Ident,
     f: &Signature,
 ) {
-    out.next_section();
     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);
@@ -554,6 +552,7 @@ fn write_rust_function_decl_impl(
     sig: &Signature,
     indirect_call: bool,
 ) {
+    out.next_section();
     if sig.throws {
         out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen ");

From ce7b37ccb7508831a67575ec85b20ce5e3686bb2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 22:09:07 +0000
Subject: [PATCH 1182/2232] Remove unneeded cfg test stringified Namespace parser


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 343acf7..8d67d07 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -123,7 +123,7 @@ mod tests {
     }
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
-        let ns = ns.map_or_else(Namespace::none, Namespace::from_str);
+        let ns = ns.map_or_else(Namespace::none, |ns| syn::parse_str(ns).unwrap());
         Api::CxxType(ExternType {
             doc: Doc::new(),
             type_token: Token![type](Span::call_site()),
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 4a37f7a..a9ef43c 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,7 +1,5 @@
 use crate::syntax::qualified::QualifiedName;
 use crate::syntax::Api;
-#[cfg(test)]
-use proc_macro2::Span;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::slice::Iter;
@@ -39,16 +37,6 @@ impl Namespace {
         input.parse::<Option<Token![,]>>()?;
         Ok(ns)
     }
-
-    #[cfg(test)]
-    pub fn from_str(ns: &str) -> Self {
-        Namespace {
-            segments: ns
-                .split("::")
-                .map(|x| Ident::new(x, Span::call_site()))
-                .collect(),
-        }
-    }
 }
 
 impl Parse for Namespace {

From 4ebde54fd38d5a635ae927287ec86e2a8fb746ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 01 2020 22:24:11 +0000
Subject: [PATCH 1183/2232] Rename Namespace::none() to const Namespace::ROOT


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 8d67d07..12251d5 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -123,7 +123,7 @@ mod tests {
     }
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
-        let ns = ns.map_or_else(Namespace::none, |ns| syn::parse_str(ns).unwrap());
+        let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
         Api::CxxType(ExternType {
             doc: Doc::new(),
             type_token: Token![type](Span::call_site()),
diff --git a/gen/src/file.rs b/gen/src/file.rs
index 1b324cb..46616fb 100644
--- a/gen/src/file.rs
+++ b/gen/src/file.rs
@@ -20,7 +20,7 @@ impl Parse for File {
 fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
     while !input.is_empty() {
         let mut cxx_bridge = false;
-        let mut namespace = Namespace::none();
+        let mut namespace = Namespace::ROOT;
         let mut attrs = input.call(Attribute::parse_outer)?;
         for attr in &attrs {
             let path = &attr.path.segments;
@@ -65,7 +65,7 @@ fn parse(input: ParseStream, modules: &mut Vec<Module>) -> Result<()> {
 
 fn parse_args(attr: &Attribute) -> Result<Namespace> {
     if attr.tokens.is_empty() {
-        Ok(Namespace::none())
+        Ok(Namespace::ROOT)
     } else {
         attr.parse_args_with(Namespace::parse_bridge_attr_namespace)
     }
diff --git a/syntax/file.rs b/syntax/file.rs
index 931ce6e..33340d8 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -36,7 +36,7 @@ pub struct ItemForeignMod {
 
 impl Parse for Module {
     fn parse(input: ParseStream) -> Result<Self> {
-        let namespace = Namespace::none();
+        let namespace = Namespace::ROOT;
         let mut attrs = input.call(Attribute::parse_outer)?;
         let vis: Visibility = input.parse()?;
         let unsafety: Option<Token![unsafe]> = input.parse()?;
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index a9ef43c..834a1d5 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -16,11 +16,9 @@ pub struct Namespace {
 }
 
 impl Namespace {
-    pub fn none() -> Self {
-        Namespace {
-            segments: Vec::new(),
-        }
-    }
+    pub const ROOT: Self = Namespace {
+        segments: Vec::new(),
+    };
 
     pub fn iter(&self) -> Iter<Ident> {
         self.segments.iter()
@@ -28,7 +26,7 @@ impl Namespace {
 
     pub fn parse_bridge_attr_namespace(input: ParseStream) -> Result<Namespace> {
         if input.is_empty() {
-            return Ok(Namespace::none());
+            return Ok(Namespace::ROOT);
         }
 
         input.parse::<kw::namespace>()?;

From 98565a2535b9246c677d131b0972b199904cdb88 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 00:52:08 +0000
Subject: [PATCH 1184/2232] Keep apis usable later in sort_by_inner_namespace


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 12251d5..ea911f8 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -26,18 +26,18 @@ impl<'a> NamespaceEntries<'a> {
 fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
     let mut direct = Vec::new();
     let mut nested_namespaces = BTreeMap::new();
-    for api in apis {
+    for api in &apis {
         if let Some(ns) = api.namespace() {
             let first_ns_elem = ns.iter().nth(depth);
             if let Some(first_ns_elem) = first_ns_elem {
                 nested_namespaces
                     .entry(first_ns_elem)
                     .or_insert_with(Vec::new)
-                    .push(api);
+                    .push(*api);
                 continue;
             }
         }
-        direct.push(api);
+        direct.push(*api);
     }
 
     let nested = nested_namespaces

From ac7188c8717e7aeb1535e876682e5038dc0ffcc7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 00:58:16 +0000
Subject: [PATCH 1185/2232] Eliminate need for lifetimes in write::gen signature


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 2cd4e56..554334c 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -136,12 +136,12 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     // one or the other.
     Ok(GeneratedCode {
         header: if opt.gen_header {
-            write::gen(apis, types, opt, true).content()
+            write::gen(apis, types, opt, true)
         } else {
             Vec::new()
         },
         implementation: if opt.gen_implementation {
-            write::gen(apis, types, opt, false).content()
+            write::gen(apis, types, opt, false)
         } else {
             Vec::new()
         },
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c008fcb..57c699c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -10,7 +10,7 @@ use crate::syntax::{
 use proc_macro2::Ident;
 use std::collections::HashMap;
 
-pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &'a Opt, header: bool) -> OutFile<'a> {
+pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
     let mut out_file = OutFile::new(header, opt, types);
     let out = &mut out_file;
 
@@ -33,7 +33,7 @@ pub(super) fn gen<'a>(apis: &[Api], types: &'a Types, opt: &'a Opt, header: bool
     builtin::write(out);
     include::write(out);
 
-    out_file
+    out_file.content()
 }
 
 fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {

From 0c033e39173f1b563a664c965c55f75ab9b07689 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 01:31:56 +0000
Subject: [PATCH 1186/2232] Preserve meaning of block boundaries


---

diff --git a/gen/src/block.rs b/gen/src/block.rs
new file mode 100644
index 0000000..e7f7c63
--- /dev/null
+++ b/gen/src/block.rs
@@ -0,0 +1,44 @@
+use proc_macro2::Ident;
+
+pub enum Block {
+    AnonymousNamespace,
+    Namespace(&'static str),
+    UserDefinedNamespace(Ident),
+    InlineNamespace(&'static str),
+    ExternC,
+}
+
+impl Block {
+    pub fn write_begin(&self, out: &mut String) {
+        if let Block::InlineNamespace(_) = self {
+            out.push_str("inline ");
+        }
+        self.write_common(out);
+        out.push_str(" {\n");
+    }
+
+    pub fn write_end(&self, out: &mut String) {
+        out.push_str("} // ");
+        self.write_common(out);
+        out.push('\n');
+    }
+
+    fn write_common(&self, out: &mut String) {
+        match self {
+            Block::AnonymousNamespace => out.push_str("namespace"),
+            Block::Namespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(name);
+            }
+            Block::UserDefinedNamespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(&name.to_string());
+            }
+            Block::InlineNamespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(name);
+            }
+            Block::ExternC => out.push_str("extern \"C\""),
+        }
+    }
+}
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 448b6f8..e755e10 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -1,3 +1,4 @@
+use crate::gen::block::Block;
 use crate::gen::ifndef;
 use crate::gen::out::{Content, OutFile};
 
@@ -39,8 +40,8 @@ pub(super) fn write(out: &mut OutFile) {
     let builtin = &mut out.builtin;
     let out = &mut builtin.content;
 
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
+    out.begin_block(Block::Namespace("rust"));
+    out.begin_block(Block::InlineNamespace("cxxbridge05"));
     writeln!(out, "// #include \"rust/cxx.h\"");
 
     ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
@@ -51,10 +52,10 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_error {
-        out.begin_block("namespace");
+        out.begin_block(Block::AnonymousNamespace);
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");
-        out.end_block("namespace");
+        out.end_block(Block::AnonymousNamespace);
     }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
@@ -91,15 +92,15 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    out.begin_block("namespace");
+    out.begin_block(Block::AnonymousNamespace);
 
     if builtin.ptr_len {
-        out.begin_block("namespace repr");
+        out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
-        out.end_block("namespace repr");
+        out.end_block(Block::Namespace("repr"));
     }
 
     if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
@@ -167,11 +168,11 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace");
-    out.end_block("namespace cxxbridge05");
+    out.end_block(Block::AnonymousNamespace);
+    out.end_block(Block::InlineNamespace("cxxbridge05"));
 
     if builtin.trycatch {
-        out.begin_block("namespace behavior");
+        out.begin_block(Block::Namespace("behavior"));
         include.exception = true;
         include.type_traits = true;
         include.utility = true;
@@ -190,8 +191,8 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}} catch (const ::std::exception &e) {{");
         writeln!(out, "  fail(e.what());");
         writeln!(out, "}}");
-        out.end_block("namespace behavior");
+        out.end_block(Block::Namespace("behavior"));
     }
 
-    out.end_block("namespace rust");
+    out.end_block(Block::Namespace("rust"));
 }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a4a159d..8626058 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -2,6 +2,7 @@
 // the cxxbridge CLI command.
 
 mod alphasort;
+mod block;
 mod builtin;
 mod check;
 pub(super) mod error;
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 6ba44aa..606a586 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,3 +1,4 @@
+use crate::gen::block::Block;
 use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::gen::Opt;
@@ -18,7 +19,7 @@ pub(crate) struct OutFile<'a> {
 pub struct Content {
     bytes: String,
     section_pending: bool,
-    blocks_pending: Vec<String>,
+    blocks_pending: Vec<Block>,
 }
 
 impl<'a> OutFile<'a> {
@@ -38,11 +39,11 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().next_section();
     }
 
-    pub fn begin_block(&mut self, block: &str) {
+    pub fn begin_block(&mut self, block: Block) {
         self.content.get_mut().begin_block(block);
     }
 
-    pub fn end_block(&mut self, block: &str) {
+    pub fn end_block(&mut self, block: Block) {
         self.content.get_mut().end_block(block);
     }
 
@@ -95,15 +96,13 @@ impl Content {
         self.section_pending = true;
     }
 
-    pub fn begin_block(&mut self, block: &str) {
-        self.blocks_pending.push(block.to_owned());
+    pub fn begin_block(&mut self, block: Block) {
+        self.blocks_pending.push(block);
     }
 
-    pub fn end_block(&mut self, block: &str) {
+    pub fn end_block(&mut self, block: Block) {
         if self.blocks_pending.pop().is_none() {
-            self.bytes.push_str("} // ");
-            self.bytes.push_str(block);
-            self.bytes.push('\n');
+            Block::write_end(&block, &mut self.bytes);
             self.section_pending = true;
         }
     }
@@ -119,8 +118,7 @@ impl Content {
                     self.bytes.push('\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    self.bytes.push_str(&block);
-                    self.bytes.push_str(" {\n");
+                    Block::write_begin(&block, &mut self.bytes);
                 }
                 self.section_pending = false;
             } else if self.section_pending {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 57c699c..a1f168f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,5 @@
 use crate::gen::alphasort::NamespaceEntries;
+use crate::gen::block::Block;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -107,7 +108,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     if !out.header {
-        out.begin_block("extern \"C\"");
+        out.begin_block(Block::ExternC);
         write_exception_glue(out, apis);
         for api in apis {
             match api {
@@ -116,7 +117,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
                 _ => {}
             }
         }
-        out.end_block("extern \"C\"");
+        out.end_block(Block::ExternC);
     }
 
     for api in apis {
@@ -127,10 +128,9 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        let block = format!("namespace {}", namespace);
-        out.begin_block(&block);
+        out.begin_block(Block::UserDefinedNamespace(namespace.clone()));
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(&block);
+        out.end_block(Block::UserDefinedNamespace(namespace.clone()));
     }
 }
 
@@ -973,7 +973,7 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
-    out.begin_block("extern \"C\"");
+    out.begin_block(Block::ExternC);
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1009,10 +1009,10 @@ fn write_generic_instantiations(out: &mut OutFile) {
             }
         }
     }
-    out.end_block("extern \"C\"");
+    out.end_block(Block::ExternC);
 
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
+    out.begin_block(Block::Namespace("rust"));
+    out.begin_block(Block::InlineNamespace("cxxbridge05"));
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1026,8 +1026,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
             }
         }
     }
-    out.end_block("namespace cxxbridge05");
-    out.end_block("namespace rust");
+    out.end_block(Block::InlineNamespace("cxxbridge05"));
+    out.end_block(Block::Namespace("rust"));
 }
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {

From 92b7b6d5757bb9a80424cb60a2b87e09e52b04a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 01:31:56 +0000
Subject: [PATCH 1187/2232] Condense creation of GeneratedCode


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 554334c..a4a159d 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -134,16 +134,15 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
     // Some callers may wish to generate both header and implementation from the
     // same token stream to avoid parsing twice. Others only need to generate
     // one or the other.
+    let (mut header, mut implementation) = Default::default();
+    if opt.gen_header {
+        header = write::gen(apis, types, opt, true);
+    }
+    if opt.gen_implementation {
+        implementation = write::gen(apis, types, opt, false);
+    }
     Ok(GeneratedCode {
-        header: if opt.gen_header {
-            write::gen(apis, types, opt, true)
-        } else {
-            Vec::new()
-        },
-        implementation: if opt.gen_implementation {
-            write::gen(apis, types, opt, false)
-        } else {
-            Vec::new()
-        },
+        header,
+        implementation,
     })
 }

From 97c5b86913bc7c5dd53ca4af8bb8a300fc638257 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 01:31:56 +0000
Subject: [PATCH 1188/2232] Borrow syntax tree idents to make Block copyable


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index ea911f8..95b49a6 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -18,7 +18,7 @@ impl<'a> NamespaceEntries<'a> {
         &self.direct
     }
 
-    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
+    pub fn nested_content(&self) -> impl Iterator<Item = (&'a Ident, &NamespaceEntries<'a>)> {
         self.nested.iter().map(|(k, entries)| (*k, entries))
     }
 }
diff --git a/gen/src/block.rs b/gen/src/block.rs
index e7f7c63..7775c52 100644
--- a/gen/src/block.rs
+++ b/gen/src/block.rs
@@ -1,14 +1,15 @@
 use proc_macro2::Ident;
 
-pub enum Block {
+#[derive(Copy, Clone)]
+pub enum Block<'a> {
     AnonymousNamespace,
     Namespace(&'static str),
-    UserDefinedNamespace(Ident),
+    UserDefinedNamespace(&'a Ident),
     InlineNamespace(&'static str),
     ExternC,
 }
 
-impl Block {
+impl<'a> Block<'a> {
     pub fn write_begin(&self, out: &mut String) {
         if let Block::InlineNamespace(_) = self {
             out.push_str("inline ");
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index e755e10..4b8dce5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -3,7 +3,7 @@ use crate::gen::ifndef;
 use crate::gen::out::{Content, OutFile};
 
 #[derive(Default, PartialEq)]
-pub struct Builtins {
+pub struct Builtins<'a> {
     pub panic: bool,
     pub rust_string: bool,
     pub rust_str: bool,
@@ -22,10 +22,10 @@ pub struct Builtins {
     pub rust_str_repr: bool,
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
-    pub content: Content,
+    pub content: Content<'a>,
 }
 
-impl Builtins {
+impl<'a> Builtins<'a> {
     pub fn new() -> Self {
         Builtins::default()
     }
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 8dc7146..d88c12d 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -19,7 +19,7 @@ pub struct Include {
 }
 
 #[derive(Default, PartialEq)]
-pub struct Includes {
+pub struct Includes<'a> {
     pub custom: Vec<Include>,
     pub array: bool,
     pub cstddef: bool,
@@ -33,10 +33,10 @@ pub struct Includes {
     pub utility: bool,
     pub vector: bool,
     pub basetsd: bool,
-    pub content: Content,
+    pub content: Content<'a>,
 }
 
-impl Includes {
+impl<'a> Includes<'a> {
     pub fn new() -> Self {
         Includes::default()
     }
@@ -101,13 +101,13 @@ pub(super) fn write(out: &mut OutFile) {
     }
 }
 
-impl<'a> Extend<&'a Include> for Includes {
-    fn extend<I: IntoIterator<Item = &'a Include>>(&mut self, iter: I) {
+impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
+    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
         self.custom.extend(iter.into_iter().cloned());
     }
 }
 
-impl<'a> From<&'a syntax::Include> for Include {
+impl<'i> From<&'i syntax::Include> for Include {
     fn from(include: &syntax::Include) -> Self {
         Include {
             path: include.path.clone(),
@@ -116,15 +116,15 @@ impl<'a> From<&'a syntax::Include> for Include {
     }
 }
 
-impl Deref for Includes {
-    type Target = Content;
+impl<'a> Deref for Includes<'a> {
+    type Target = Content<'a>;
 
     fn deref(&self) -> &Self::Target {
         &self.content
     }
 }
 
-impl DerefMut for Includes {
+impl<'a> DerefMut for Includes<'a> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.content
     }
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 606a586..6867a76 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -10,16 +10,16 @@ pub(crate) struct OutFile<'a> {
     pub header: bool,
     pub opt: &'a Opt,
     pub types: &'a Types<'a>,
-    pub include: Includes,
-    pub builtin: Builtins,
-    content: RefCell<Content>,
+    pub include: Includes<'a>,
+    pub builtin: Builtins<'a>,
+    content: RefCell<Content<'a>>,
 }
 
 #[derive(Default)]
-pub struct Content {
+pub struct Content<'a> {
     bytes: String,
     section_pending: bool,
-    blocks_pending: Vec<Block>,
+    blocks_pending: Vec<Block<'a>>,
 }
 
 impl<'a> OutFile<'a> {
@@ -39,11 +39,11 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().next_section();
     }
 
-    pub fn begin_block(&mut self, block: Block) {
+    pub fn begin_block(&mut self, block: Block<'a>) {
         self.content.get_mut().begin_block(block);
     }
 
-    pub fn end_block(&mut self, block: Block) {
+    pub fn end_block(&mut self, block: Block<'a>) {
         self.content.get_mut().end_block(block);
     }
 
@@ -74,20 +74,20 @@ impl<'a> OutFile<'a> {
     }
 }
 
-impl Write for Content {
+impl<'a> Write for Content<'a> {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         self.write(s);
         Ok(())
     }
 }
 
-impl PartialEq for Content {
+impl<'a> PartialEq for Content<'a> {
     fn eq(&self, _other: &Content) -> bool {
         true
     }
 }
 
-impl Content {
+impl<'a> Content<'a> {
     fn new() -> Self {
         Content::default()
     }
@@ -96,11 +96,11 @@ impl Content {
         self.section_pending = true;
     }
 
-    pub fn begin_block(&mut self, block: Block) {
+    pub fn begin_block(&mut self, block: Block<'a>) {
         self.blocks_pending.push(block);
     }
 
-    pub fn end_block(&mut self, block: Block) {
+    pub fn end_block(&mut self, block: Block<'a>) {
         if self.blocks_pending.pop().is_none() {
             Block::write_end(&block, &mut self.bytes);
             self.section_pending = true;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a1f168f..0b6a5aa 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -57,7 +57,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     }
 }
 
-fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
+fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntries<'a>) {
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -128,9 +128,10 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        out.begin_block(Block::UserDefinedNamespace(namespace.clone()));
+        let block = Block::UserDefinedNamespace(namespace);
+        out.begin_block(block);
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(Block::UserDefinedNamespace(namespace.clone()));
+        out.end_block(block);
     }
 }
 

From 8da98ca66b38af411a93d967fd92cf9ed8e77191 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 01:43:57 +0000
Subject: [PATCH 1189/2232] Merge pull request #399 from dtolnay/block


Preserve meaning of block boundaries
---

diff --git a/gen/src/block.rs b/gen/src/block.rs
new file mode 100644
index 0000000..e7f7c63
--- /dev/null
+++ b/gen/src/block.rs
@@ -0,0 +1,44 @@
+use proc_macro2::Ident;
+
+pub enum Block {
+    AnonymousNamespace,
+    Namespace(&'static str),
+    UserDefinedNamespace(Ident),
+    InlineNamespace(&'static str),
+    ExternC,
+}
+
+impl Block {
+    pub fn write_begin(&self, out: &mut String) {
+        if let Block::InlineNamespace(_) = self {
+            out.push_str("inline ");
+        }
+        self.write_common(out);
+        out.push_str(" {\n");
+    }
+
+    pub fn write_end(&self, out: &mut String) {
+        out.push_str("} // ");
+        self.write_common(out);
+        out.push('\n');
+    }
+
+    fn write_common(&self, out: &mut String) {
+        match self {
+            Block::AnonymousNamespace => out.push_str("namespace"),
+            Block::Namespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(name);
+            }
+            Block::UserDefinedNamespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(&name.to_string());
+            }
+            Block::InlineNamespace(name) => {
+                out.push_str("namespace ");
+                out.push_str(name);
+            }
+            Block::ExternC => out.push_str("extern \"C\""),
+        }
+    }
+}
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 448b6f8..e755e10 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -1,3 +1,4 @@
+use crate::gen::block::Block;
 use crate::gen::ifndef;
 use crate::gen::out::{Content, OutFile};
 
@@ -39,8 +40,8 @@ pub(super) fn write(out: &mut OutFile) {
     let builtin = &mut out.builtin;
     let out = &mut builtin.content;
 
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
+    out.begin_block(Block::Namespace("rust"));
+    out.begin_block(Block::InlineNamespace("cxxbridge05"));
     writeln!(out, "// #include \"rust/cxx.h\"");
 
     ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
@@ -51,10 +52,10 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_error {
-        out.begin_block("namespace");
+        out.begin_block(Block::AnonymousNamespace);
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");
-        out.end_block("namespace");
+        out.end_block(Block::AnonymousNamespace);
     }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
@@ -91,15 +92,15 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    out.begin_block("namespace");
+    out.begin_block(Block::AnonymousNamespace);
 
     if builtin.ptr_len {
-        out.begin_block("namespace repr");
+        out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  const void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
-        out.end_block("namespace repr");
+        out.end_block(Block::Namespace("repr"));
     }
 
     if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
@@ -167,11 +168,11 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    out.end_block("namespace");
-    out.end_block("namespace cxxbridge05");
+    out.end_block(Block::AnonymousNamespace);
+    out.end_block(Block::InlineNamespace("cxxbridge05"));
 
     if builtin.trycatch {
-        out.begin_block("namespace behavior");
+        out.begin_block(Block::Namespace("behavior"));
         include.exception = true;
         include.type_traits = true;
         include.utility = true;
@@ -190,8 +191,8 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}} catch (const ::std::exception &e) {{");
         writeln!(out, "  fail(e.what());");
         writeln!(out, "}}");
-        out.end_block("namespace behavior");
+        out.end_block(Block::Namespace("behavior"));
     }
 
-    out.end_block("namespace rust");
+    out.end_block(Block::Namespace("rust"));
 }
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index a4a159d..8626058 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -2,6 +2,7 @@
 // the cxxbridge CLI command.
 
 mod alphasort;
+mod block;
 mod builtin;
 mod check;
 pub(super) mod error;
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 6ba44aa..606a586 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -1,3 +1,4 @@
+use crate::gen::block::Block;
 use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::gen::Opt;
@@ -18,7 +19,7 @@ pub(crate) struct OutFile<'a> {
 pub struct Content {
     bytes: String,
     section_pending: bool,
-    blocks_pending: Vec<String>,
+    blocks_pending: Vec<Block>,
 }
 
 impl<'a> OutFile<'a> {
@@ -38,11 +39,11 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().next_section();
     }
 
-    pub fn begin_block(&mut self, block: &str) {
+    pub fn begin_block(&mut self, block: Block) {
         self.content.get_mut().begin_block(block);
     }
 
-    pub fn end_block(&mut self, block: &str) {
+    pub fn end_block(&mut self, block: Block) {
         self.content.get_mut().end_block(block);
     }
 
@@ -95,15 +96,13 @@ impl Content {
         self.section_pending = true;
     }
 
-    pub fn begin_block(&mut self, block: &str) {
-        self.blocks_pending.push(block.to_owned());
+    pub fn begin_block(&mut self, block: Block) {
+        self.blocks_pending.push(block);
     }
 
-    pub fn end_block(&mut self, block: &str) {
+    pub fn end_block(&mut self, block: Block) {
         if self.blocks_pending.pop().is_none() {
-            self.bytes.push_str("} // ");
-            self.bytes.push_str(block);
-            self.bytes.push('\n');
+            Block::write_end(&block, &mut self.bytes);
             self.section_pending = true;
         }
     }
@@ -119,8 +118,7 @@ impl Content {
                     self.bytes.push('\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    self.bytes.push_str(&block);
-                    self.bytes.push_str(" {\n");
+                    Block::write_begin(&block, &mut self.bytes);
                 }
                 self.section_pending = false;
             } else if self.section_pending {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 57c699c..a1f168f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,5 @@
 use crate::gen::alphasort::NamespaceEntries;
+use crate::gen::block::Block;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
@@ -107,7 +108,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     if !out.header {
-        out.begin_block("extern \"C\"");
+        out.begin_block(Block::ExternC);
         write_exception_glue(out, apis);
         for api in apis {
             match api {
@@ -116,7 +117,7 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
                 _ => {}
             }
         }
-        out.end_block("extern \"C\"");
+        out.end_block(Block::ExternC);
     }
 
     for api in apis {
@@ -127,10 +128,9 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        let block = format!("namespace {}", namespace);
-        out.begin_block(&block);
+        out.begin_block(Block::UserDefinedNamespace(namespace.clone()));
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(&block);
+        out.end_block(Block::UserDefinedNamespace(namespace.clone()));
     }
 }
 
@@ -973,7 +973,7 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
-    out.begin_block("extern \"C\"");
+    out.begin_block(Block::ExternC);
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1009,10 +1009,10 @@ fn write_generic_instantiations(out: &mut OutFile) {
             }
         }
     }
-    out.end_block("extern \"C\"");
+    out.end_block(Block::ExternC);
 
-    out.begin_block("namespace rust");
-    out.begin_block("inline namespace cxxbridge05");
+    out.begin_block(Block::Namespace("rust"));
+    out.begin_block(Block::InlineNamespace("cxxbridge05"));
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1026,8 +1026,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
             }
         }
     }
-    out.end_block("namespace cxxbridge05");
-    out.end_block("namespace rust");
+    out.end_block(Block::InlineNamespace("cxxbridge05"));
+    out.end_block(Block::Namespace("rust"));
 }
 
 fn write_rust_box_extern(out: &mut OutFile, ident: &CppName) {

From 53e593f309cb35d49843695c72f1cb55980f35d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:09:16 +0000
Subject: [PATCH 1190/2232] Merge pull request #400 from dtolnay/blockcopy


Borrow syntax tree idents to make Block copyable
---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index ea911f8..95b49a6 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -18,7 +18,7 @@ impl<'a> NamespaceEntries<'a> {
         &self.direct
     }
 
-    pub fn nested_content(&self) -> impl Iterator<Item = (&Ident, &NamespaceEntries)> {
+    pub fn nested_content(&self) -> impl Iterator<Item = (&'a Ident, &NamespaceEntries<'a>)> {
         self.nested.iter().map(|(k, entries)| (*k, entries))
     }
 }
diff --git a/gen/src/block.rs b/gen/src/block.rs
index e7f7c63..7775c52 100644
--- a/gen/src/block.rs
+++ b/gen/src/block.rs
@@ -1,14 +1,15 @@
 use proc_macro2::Ident;
 
-pub enum Block {
+#[derive(Copy, Clone)]
+pub enum Block<'a> {
     AnonymousNamespace,
     Namespace(&'static str),
-    UserDefinedNamespace(Ident),
+    UserDefinedNamespace(&'a Ident),
     InlineNamespace(&'static str),
     ExternC,
 }
 
-impl Block {
+impl<'a> Block<'a> {
     pub fn write_begin(&self, out: &mut String) {
         if let Block::InlineNamespace(_) = self {
             out.push_str("inline ");
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index e755e10..4b8dce5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -3,7 +3,7 @@ use crate::gen::ifndef;
 use crate::gen::out::{Content, OutFile};
 
 #[derive(Default, PartialEq)]
-pub struct Builtins {
+pub struct Builtins<'a> {
     pub panic: bool,
     pub rust_string: bool,
     pub rust_str: bool,
@@ -22,10 +22,10 @@ pub struct Builtins {
     pub rust_str_repr: bool,
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
-    pub content: Content,
+    pub content: Content<'a>,
 }
 
-impl Builtins {
+impl<'a> Builtins<'a> {
     pub fn new() -> Self {
         Builtins::default()
     }
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 8dc7146..d88c12d 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -19,7 +19,7 @@ pub struct Include {
 }
 
 #[derive(Default, PartialEq)]
-pub struct Includes {
+pub struct Includes<'a> {
     pub custom: Vec<Include>,
     pub array: bool,
     pub cstddef: bool,
@@ -33,10 +33,10 @@ pub struct Includes {
     pub utility: bool,
     pub vector: bool,
     pub basetsd: bool,
-    pub content: Content,
+    pub content: Content<'a>,
 }
 
-impl Includes {
+impl<'a> Includes<'a> {
     pub fn new() -> Self {
         Includes::default()
     }
@@ -101,13 +101,13 @@ pub(super) fn write(out: &mut OutFile) {
     }
 }
 
-impl<'a> Extend<&'a Include> for Includes {
-    fn extend<I: IntoIterator<Item = &'a Include>>(&mut self, iter: I) {
+impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
+    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
         self.custom.extend(iter.into_iter().cloned());
     }
 }
 
-impl<'a> From<&'a syntax::Include> for Include {
+impl<'i> From<&'i syntax::Include> for Include {
     fn from(include: &syntax::Include) -> Self {
         Include {
             path: include.path.clone(),
@@ -116,15 +116,15 @@ impl<'a> From<&'a syntax::Include> for Include {
     }
 }
 
-impl Deref for Includes {
-    type Target = Content;
+impl<'a> Deref for Includes<'a> {
+    type Target = Content<'a>;
 
     fn deref(&self) -> &Self::Target {
         &self.content
     }
 }
 
-impl DerefMut for Includes {
+impl<'a> DerefMut for Includes<'a> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         &mut self.content
     }
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 606a586..6867a76 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -10,16 +10,16 @@ pub(crate) struct OutFile<'a> {
     pub header: bool,
     pub opt: &'a Opt,
     pub types: &'a Types<'a>,
-    pub include: Includes,
-    pub builtin: Builtins,
-    content: RefCell<Content>,
+    pub include: Includes<'a>,
+    pub builtin: Builtins<'a>,
+    content: RefCell<Content<'a>>,
 }
 
 #[derive(Default)]
-pub struct Content {
+pub struct Content<'a> {
     bytes: String,
     section_pending: bool,
-    blocks_pending: Vec<Block>,
+    blocks_pending: Vec<Block<'a>>,
 }
 
 impl<'a> OutFile<'a> {
@@ -39,11 +39,11 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().next_section();
     }
 
-    pub fn begin_block(&mut self, block: Block) {
+    pub fn begin_block(&mut self, block: Block<'a>) {
         self.content.get_mut().begin_block(block);
     }
 
-    pub fn end_block(&mut self, block: Block) {
+    pub fn end_block(&mut self, block: Block<'a>) {
         self.content.get_mut().end_block(block);
     }
 
@@ -74,20 +74,20 @@ impl<'a> OutFile<'a> {
     }
 }
 
-impl Write for Content {
+impl<'a> Write for Content<'a> {
     fn write_str(&mut self, s: &str) -> fmt::Result {
         self.write(s);
         Ok(())
     }
 }
 
-impl PartialEq for Content {
+impl<'a> PartialEq for Content<'a> {
     fn eq(&self, _other: &Content) -> bool {
         true
     }
 }
 
-impl Content {
+impl<'a> Content<'a> {
     fn new() -> Self {
         Content::default()
     }
@@ -96,11 +96,11 @@ impl Content {
         self.section_pending = true;
     }
 
-    pub fn begin_block(&mut self, block: Block) {
+    pub fn begin_block(&mut self, block: Block<'a>) {
         self.blocks_pending.push(block);
     }
 
-    pub fn end_block(&mut self, block: Block) {
+    pub fn end_block(&mut self, block: Block<'a>) {
         if self.blocks_pending.pop().is_none() {
             Block::write_end(&block, &mut self.bytes);
             self.section_pending = true;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a1f168f..0b6a5aa 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -57,7 +57,7 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     }
 }
 
-fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
+fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntries<'a>) {
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -128,9 +128,10 @@ fn gen_namespace_contents(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     }
 
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        out.begin_block(Block::UserDefinedNamespace(namespace.clone()));
+        let block = Block::UserDefinedNamespace(namespace);
+        out.begin_block(block);
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(Block::UserDefinedNamespace(namespace.clone()));
+        out.end_block(block);
     }
 }
 

From f02146e4e2d0d3b6bd942e386d84bad2b75b720e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:09:25 +0000
Subject: [PATCH 1191/2232] Validate that block begins and ends are correctly paired


---

diff --git a/gen/src/block.rs b/gen/src/block.rs
index 19dc8b1..96a9a6e 100644
--- a/gen/src/block.rs
+++ b/gen/src/block.rs
@@ -1,6 +1,6 @@
 use proc_macro2::Ident;
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum Block<'a> {
     AnonymousNamespace,
     Namespace(&'static str),
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 7498c69..0f12e89 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -18,8 +18,9 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
+    blocks: Vec<Block<'a>>,
     section_pending: bool,
-    blocks_pending: Vec<Block<'a>>,
+    blocks_pending: usize,
 }
 
 impl<'a> OutFile<'a> {
@@ -97,11 +98,18 @@ impl<'a> Content<'a> {
     }
 
     pub fn begin_block(&mut self, block: Block<'a>) {
-        self.blocks_pending.push(block);
+        self.blocks.push(block);
+        self.blocks_pending += 1;
     }
 
     pub fn end_block(&mut self, block: Block<'a>) {
-        if self.blocks_pending.pop().is_none() {
+        let begin_block = self.blocks.pop().unwrap();
+        let end_block = block;
+        assert_eq!(begin_block, end_block);
+
+        if self.blocks_pending > 0 {
+            self.blocks_pending -= 1;
+        } else {
             Block::write_end(block, &mut self.bytes);
             self.section_pending = true;
         }
@@ -113,21 +121,20 @@ impl<'a> Content<'a> {
 
     fn write(&mut self, b: &str) {
         if !b.is_empty() {
-            if !self.blocks_pending.is_empty() {
+            if self.blocks_pending > 0 {
                 if !self.bytes.is_empty() {
                     self.bytes.push('\n');
                 }
-                for block in self.blocks_pending.drain(..) {
-                    Block::write_begin(block, &mut self.bytes);
-                }
-                self.section_pending = false;
-            } else if self.section_pending {
-                if !self.bytes.is_empty() {
-                    self.bytes.push('\n');
+                let pending = self.blocks.len() - self.blocks_pending..;
+                for block in &self.blocks[pending] {
+                    Block::write_begin(*block, &mut self.bytes);
                 }
-                self.section_pending = false;
+            } else if self.section_pending && !self.bytes.is_empty() {
+                self.bytes.push('\n');
             }
             self.bytes.push_str(b);
+            self.section_pending = false;
+            self.blocks_pending = 0;
         }
     }
 }

From 2a160e4effc070b48a0a789b94e545ff8054483e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:09:25 +0000
Subject: [PATCH 1192/2232] Pass Block only by Copy


---

diff --git a/gen/src/block.rs b/gen/src/block.rs
index 7775c52..19dc8b1 100644
--- a/gen/src/block.rs
+++ b/gen/src/block.rs
@@ -10,7 +10,7 @@ pub enum Block<'a> {
 }
 
 impl<'a> Block<'a> {
-    pub fn write_begin(&self, out: &mut String) {
+    pub fn write_begin(self, out: &mut String) {
         if let Block::InlineNamespace(_) = self {
             out.push_str("inline ");
         }
@@ -18,13 +18,13 @@ impl<'a> Block<'a> {
         out.push_str(" {\n");
     }
 
-    pub fn write_end(&self, out: &mut String) {
+    pub fn write_end(self, out: &mut String) {
         out.push_str("} // ");
         self.write_common(out);
         out.push('\n');
     }
 
-    fn write_common(&self, out: &mut String) {
+    fn write_common(self, out: &mut String) {
         match self {
             Block::AnonymousNamespace => out.push_str("namespace"),
             Block::Namespace(name) => {
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 6867a76..7498c69 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -102,7 +102,7 @@ impl<'a> Content<'a> {
 
     pub fn end_block(&mut self, block: Block<'a>) {
         if self.blocks_pending.pop().is_none() {
-            Block::write_end(&block, &mut self.bytes);
+            Block::write_end(block, &mut self.bytes);
             self.section_pending = true;
         }
     }
@@ -118,7 +118,7 @@ impl<'a> Content<'a> {
                     self.bytes.push('\n');
                 }
                 for block in self.blocks_pending.drain(..) {
-                    Block::write_begin(&block, &mut self.bytes);
+                    Block::write_begin(block, &mut self.bytes);
                 }
                 self.section_pending = false;
             } else if self.section_pending {

From e3b39820d12b89e926d9542216c3a7454164af91 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:09:25 +0000
Subject: [PATCH 1193/2232] Recognize identical block being closed and opened


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 0f12e89..2733c32 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -18,11 +18,17 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
-    blocks: Vec<Block<'a>>,
+    blocks: Vec<BlockBoundary<'a>>,
     section_pending: bool,
     blocks_pending: usize,
 }
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+enum BlockBoundary<'a> {
+    Begin(Block<'a>),
+    End(Block<'a>),
+}
+
 impl<'a> OutFile<'a> {
     pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
         OutFile {
@@ -53,10 +59,11 @@ impl<'a> OutFile<'a> {
         Write::write_fmt(content, args).unwrap();
     }
 
-    pub fn content(&self) -> Vec<u8> {
+    pub fn content(&mut self) -> Vec<u8> {
+        self.flush();
         let include = &self.include.content.bytes;
         let builtin = &self.builtin.content.bytes;
-        let content = &self.content.borrow().bytes;
+        let content = &self.content.get_mut().bytes;
         let len = include.len() + builtin.len() + content.len() + 2;
         let mut out = String::with_capacity(len);
         out.push_str(include);
@@ -73,6 +80,12 @@ impl<'a> OutFile<'a> {
         }
         out.into_bytes()
     }
+
+    fn flush(&mut self) {
+        self.include.content.flush();
+        self.builtin.content.flush();
+        self.content.get_mut().flush();
+    }
 }
 
 impl<'a> Write for Content<'a> {
@@ -98,21 +111,11 @@ impl<'a> Content<'a> {
     }
 
     pub fn begin_block(&mut self, block: Block<'a>) {
-        self.blocks.push(block);
-        self.blocks_pending += 1;
+        self.push_block_boundary(BlockBoundary::Begin(block));
     }
 
     pub fn end_block(&mut self, block: Block<'a>) {
-        let begin_block = self.blocks.pop().unwrap();
-        let end_block = block;
-        assert_eq!(begin_block, end_block);
-
-        if self.blocks_pending > 0 {
-            self.blocks_pending -= 1;
-        } else {
-            Block::write_end(block, &mut self.bytes);
-            self.section_pending = true;
-        }
+        self.push_block_boundary(BlockBoundary::End(block));
     }
 
     pub fn write_fmt(&mut self, args: Arguments) {
@@ -122,14 +125,9 @@ impl<'a> Content<'a> {
     fn write(&mut self, b: &str) {
         if !b.is_empty() {
             if self.blocks_pending > 0 {
-                if !self.bytes.is_empty() {
-                    self.bytes.push('\n');
-                }
-                let pending = self.blocks.len() - self.blocks_pending..;
-                for block in &self.blocks[pending] {
-                    Block::write_begin(*block, &mut self.bytes);
-                }
-            } else if self.section_pending && !self.bytes.is_empty() {
+                self.flush_blocks();
+            }
+            if self.section_pending && !self.bytes.is_empty() {
                 self.bytes.push('\n');
             }
             self.bytes.push_str(b);
@@ -137,4 +135,59 @@ impl<'a> Content<'a> {
             self.blocks_pending = 0;
         }
     }
+
+    fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
+        if self.blocks_pending > 0 && boundary == self.blocks.last().unwrap().rev() {
+            self.blocks.pop();
+            self.blocks_pending -= 1;
+        } else {
+            self.blocks.push(boundary);
+            self.blocks_pending += 1;
+        }
+    }
+
+    fn flush(&mut self) {
+        if self.blocks_pending > 0 {
+            self.flush_blocks();
+        }
+    }
+
+    fn flush_blocks(&mut self) {
+        self.section_pending = !self.bytes.is_empty();
+        let mut read = self.blocks.len() - self.blocks_pending;
+        let mut write = read;
+
+        while read < self.blocks.len() {
+            match self.blocks[read] {
+                BlockBoundary::Begin(begin_block) => {
+                    if self.section_pending {
+                        self.bytes.push('\n');
+                        self.section_pending = false;
+                    }
+                    Block::write_begin(begin_block, &mut self.bytes);
+                    self.blocks[write] = BlockBoundary::Begin(begin_block);
+                    write += 1;
+                }
+                BlockBoundary::End(end_block) => {
+                    write = write.checked_sub(1).unwrap();
+                    let begin_block = self.blocks[write];
+                    assert_eq!(begin_block, BlockBoundary::Begin(end_block));
+                    Block::write_end(end_block, &mut self.bytes);
+                    self.section_pending = true;
+                }
+            }
+            read += 1;
+        }
+
+        self.blocks.truncate(write);
+    }
+}
+
+impl<'a> BlockBoundary<'a> {
+    fn rev(self) -> BlockBoundary<'a> {
+        match self {
+            BlockBoundary::Begin(block) => BlockBoundary::End(block),
+            BlockBoundary::End(block) => BlockBoundary::Begin(block),
+        }
+    }
 }

From 078c90fab6cdcecb981b7577a93d480883e2d7ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:09:25 +0000
Subject: [PATCH 1194/2232] Implement set_namespace helper for OutFile


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 95b49a6..5c21bc4 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -1,9 +1,11 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
+    pub namespace: Namespace,
     direct: Vec<&'a Api>,
     nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
@@ -45,7 +47,17 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
         .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
         .collect();
 
-    NamespaceEntries { direct, nested }
+    let namespace = apis
+        .first()
+        .copied()
+        .and_then(Api::namespace)
+        .map_or(Namespace::ROOT, |ns| ns.iter().take(depth).collect());
+
+    NamespaceEntries {
+        namespace,
+        direct,
+        nested,
+    }
 }
 
 #[cfg(test)]
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 2733c32..bf880cc 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -2,6 +2,7 @@ use crate::gen::block::Block;
 use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::gen::Opt;
+use crate::syntax::namespace::Namespace;
 use crate::syntax::Types;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
@@ -18,6 +19,7 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
+    namespace: &'a Namespace,
     blocks: Vec<BlockBoundary<'a>>,
     section_pending: bool,
     blocks_pending: usize,
@@ -54,6 +56,10 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().end_block(block);
     }
 
+    pub fn set_namespace(&mut self, namespace: &'a Namespace) {
+        self.content.get_mut().set_namespace(namespace);
+    }
+
     pub fn write_fmt(&self, args: Arguments) {
         let content = &mut *self.content.borrow_mut();
         Write::write_fmt(content, args).unwrap();
@@ -118,6 +124,16 @@ impl<'a> Content<'a> {
         self.push_block_boundary(BlockBoundary::End(block));
     }
 
+    pub fn set_namespace(&mut self, namespace: &'a Namespace) {
+        for name in self.namespace.iter().rev() {
+            self.end_block(Block::UserDefinedNamespace(name));
+        }
+        for name in namespace {
+            self.begin_block(Block::UserDefinedNamespace(name));
+        }
+        self.namespace = namespace;
+    }
+
     pub fn write_fmt(&mut self, args: Arguments) {
         Write::write_fmt(self, args).unwrap();
     }
@@ -147,6 +163,7 @@ impl<'a> Content<'a> {
     }
 
     fn flush(&mut self) {
+        self.set_namespace(Default::default());
         if self.blocks_pending > 0 {
             self.flush_blocks();
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0b6a5aa..352d643 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -57,7 +57,8 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     }
 }
 
-fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntries<'a>) {
+fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
+    out.set_namespace(&ns_entries.namespace);
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -127,11 +128,8 @@ fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntri
         }
     }
 
-    for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        let block = Block::UserDefinedNamespace(namespace);
-        out.begin_block(block);
+    for (_, nested_ns_entries) in ns_entries.nested_content() {
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(block);
     }
 }
 
@@ -974,6 +972,7 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
+    out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 834a1d5..7628b0a 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -2,6 +2,7 @@ use crate::syntax::qualified::QualifiedName;
 use crate::syntax::Api;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
+use std::iter::FromIterator;
 use std::slice::Iter;
 use syn::parse::{Parse, ParseStream, Result};
 use syn::{Ident, Token};
@@ -10,7 +11,7 @@ mod kw {
     syn::custom_keyword!(namespace);
 }
 
-#[derive(Clone)]
+#[derive(Clone, Default)]
 pub struct Namespace {
     segments: Vec<Ident>,
 }
@@ -37,6 +38,13 @@ impl Namespace {
     }
 }
 
+impl Default for &Namespace {
+    fn default() -> Self {
+        const ROOT: &Namespace = &Namespace::ROOT;
+        ROOT
+    }
+}
+
 impl Parse for Namespace {
     fn parse(input: ParseStream) -> Result<Self> {
         let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
@@ -67,6 +75,16 @@ impl<'a> IntoIterator for &'a Namespace {
     }
 }
 
+impl<'a> FromIterator<&'a Ident> for Namespace {
+    fn from_iter<I>(idents: I) -> Self
+    where
+        I: IntoIterator<Item = &'a Ident>,
+    {
+        let segments = idents.into_iter().cloned().collect();
+        Namespace { segments }
+    }
+}
+
 impl Api {
     pub fn namespace(&self) -> Option<&Namespace> {
         match self {

From 6b5d4dde00f645749ad699a7b8c36aa9e8644a17 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:16:29 +0000
Subject: [PATCH 1195/2232] Merge pull request #401 from dtolnay/block


Validate that block begins and ends are correctly paired
---

diff --git a/gen/src/block.rs b/gen/src/block.rs
index 19dc8b1..96a9a6e 100644
--- a/gen/src/block.rs
+++ b/gen/src/block.rs
@@ -1,6 +1,6 @@
 use proc_macro2::Ident;
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum Block<'a> {
     AnonymousNamespace,
     Namespace(&'static str),
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 7498c69..0f12e89 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -18,8 +18,9 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
+    blocks: Vec<Block<'a>>,
     section_pending: bool,
-    blocks_pending: Vec<Block<'a>>,
+    blocks_pending: usize,
 }
 
 impl<'a> OutFile<'a> {
@@ -97,11 +98,18 @@ impl<'a> Content<'a> {
     }
 
     pub fn begin_block(&mut self, block: Block<'a>) {
-        self.blocks_pending.push(block);
+        self.blocks.push(block);
+        self.blocks_pending += 1;
     }
 
     pub fn end_block(&mut self, block: Block<'a>) {
-        if self.blocks_pending.pop().is_none() {
+        let begin_block = self.blocks.pop().unwrap();
+        let end_block = block;
+        assert_eq!(begin_block, end_block);
+
+        if self.blocks_pending > 0 {
+            self.blocks_pending -= 1;
+        } else {
             Block::write_end(block, &mut self.bytes);
             self.section_pending = true;
         }
@@ -113,21 +121,20 @@ impl<'a> Content<'a> {
 
     fn write(&mut self, b: &str) {
         if !b.is_empty() {
-            if !self.blocks_pending.is_empty() {
+            if self.blocks_pending > 0 {
                 if !self.bytes.is_empty() {
                     self.bytes.push('\n');
                 }
-                for block in self.blocks_pending.drain(..) {
-                    Block::write_begin(block, &mut self.bytes);
-                }
-                self.section_pending = false;
-            } else if self.section_pending {
-                if !self.bytes.is_empty() {
-                    self.bytes.push('\n');
+                let pending = self.blocks.len() - self.blocks_pending..;
+                for block in &self.blocks[pending] {
+                    Block::write_begin(*block, &mut self.bytes);
                 }
-                self.section_pending = false;
+            } else if self.section_pending && !self.bytes.is_empty() {
+                self.bytes.push('\n');
             }
             self.bytes.push_str(b);
+            self.section_pending = false;
+            self.blocks_pending = 0;
         }
     }
 }

From 118a6a90388f9c947bff03cbd38b99e31f6d716d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:23:04 +0000
Subject: [PATCH 1196/2232] Merge pull request #402 from dtolnay/closeopen


Recognize identical block being closed and opened
---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index 0f12e89..2733c32 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -18,11 +18,17 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
-    blocks: Vec<Block<'a>>,
+    blocks: Vec<BlockBoundary<'a>>,
     section_pending: bool,
     blocks_pending: usize,
 }
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+enum BlockBoundary<'a> {
+    Begin(Block<'a>),
+    End(Block<'a>),
+}
+
 impl<'a> OutFile<'a> {
     pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
         OutFile {
@@ -53,10 +59,11 @@ impl<'a> OutFile<'a> {
         Write::write_fmt(content, args).unwrap();
     }
 
-    pub fn content(&self) -> Vec<u8> {
+    pub fn content(&mut self) -> Vec<u8> {
+        self.flush();
         let include = &self.include.content.bytes;
         let builtin = &self.builtin.content.bytes;
-        let content = &self.content.borrow().bytes;
+        let content = &self.content.get_mut().bytes;
         let len = include.len() + builtin.len() + content.len() + 2;
         let mut out = String::with_capacity(len);
         out.push_str(include);
@@ -73,6 +80,12 @@ impl<'a> OutFile<'a> {
         }
         out.into_bytes()
     }
+
+    fn flush(&mut self) {
+        self.include.content.flush();
+        self.builtin.content.flush();
+        self.content.get_mut().flush();
+    }
 }
 
 impl<'a> Write for Content<'a> {
@@ -98,21 +111,11 @@ impl<'a> Content<'a> {
     }
 
     pub fn begin_block(&mut self, block: Block<'a>) {
-        self.blocks.push(block);
-        self.blocks_pending += 1;
+        self.push_block_boundary(BlockBoundary::Begin(block));
     }
 
     pub fn end_block(&mut self, block: Block<'a>) {
-        let begin_block = self.blocks.pop().unwrap();
-        let end_block = block;
-        assert_eq!(begin_block, end_block);
-
-        if self.blocks_pending > 0 {
-            self.blocks_pending -= 1;
-        } else {
-            Block::write_end(block, &mut self.bytes);
-            self.section_pending = true;
-        }
+        self.push_block_boundary(BlockBoundary::End(block));
     }
 
     pub fn write_fmt(&mut self, args: Arguments) {
@@ -122,14 +125,9 @@ impl<'a> Content<'a> {
     fn write(&mut self, b: &str) {
         if !b.is_empty() {
             if self.blocks_pending > 0 {
-                if !self.bytes.is_empty() {
-                    self.bytes.push('\n');
-                }
-                let pending = self.blocks.len() - self.blocks_pending..;
-                for block in &self.blocks[pending] {
-                    Block::write_begin(*block, &mut self.bytes);
-                }
-            } else if self.section_pending && !self.bytes.is_empty() {
+                self.flush_blocks();
+            }
+            if self.section_pending && !self.bytes.is_empty() {
                 self.bytes.push('\n');
             }
             self.bytes.push_str(b);
@@ -137,4 +135,59 @@ impl<'a> Content<'a> {
             self.blocks_pending = 0;
         }
     }
+
+    fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
+        if self.blocks_pending > 0 && boundary == self.blocks.last().unwrap().rev() {
+            self.blocks.pop();
+            self.blocks_pending -= 1;
+        } else {
+            self.blocks.push(boundary);
+            self.blocks_pending += 1;
+        }
+    }
+
+    fn flush(&mut self) {
+        if self.blocks_pending > 0 {
+            self.flush_blocks();
+        }
+    }
+
+    fn flush_blocks(&mut self) {
+        self.section_pending = !self.bytes.is_empty();
+        let mut read = self.blocks.len() - self.blocks_pending;
+        let mut write = read;
+
+        while read < self.blocks.len() {
+            match self.blocks[read] {
+                BlockBoundary::Begin(begin_block) => {
+                    if self.section_pending {
+                        self.bytes.push('\n');
+                        self.section_pending = false;
+                    }
+                    Block::write_begin(begin_block, &mut self.bytes);
+                    self.blocks[write] = BlockBoundary::Begin(begin_block);
+                    write += 1;
+                }
+                BlockBoundary::End(end_block) => {
+                    write = write.checked_sub(1).unwrap();
+                    let begin_block = self.blocks[write];
+                    assert_eq!(begin_block, BlockBoundary::Begin(end_block));
+                    Block::write_end(end_block, &mut self.bytes);
+                    self.section_pending = true;
+                }
+            }
+            read += 1;
+        }
+
+        self.blocks.truncate(write);
+    }
+}
+
+impl<'a> BlockBoundary<'a> {
+    fn rev(self) -> BlockBoundary<'a> {
+        match self {
+            BlockBoundary::Begin(block) => BlockBoundary::End(block),
+            BlockBoundary::End(block) => BlockBoundary::Begin(block),
+        }
+    }
 }

From 5a21a9838602516c60b421191386fa5c14de7107 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 02:27:22 +0000
Subject: [PATCH 1197/2232] Merge pull request #403 from dtolnay/setnamespace


Implement set_namespace helper for OutFile
---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 95b49a6..5c21bc4 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -1,9 +1,11 @@
+use crate::syntax::namespace::Namespace;
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
+    pub namespace: Namespace,
     direct: Vec<&'a Api>,
     nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
@@ -45,7 +47,17 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
         .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
         .collect();
 
-    NamespaceEntries { direct, nested }
+    let namespace = apis
+        .first()
+        .copied()
+        .and_then(Api::namespace)
+        .map_or(Namespace::ROOT, |ns| ns.iter().take(depth).collect());
+
+    NamespaceEntries {
+        namespace,
+        direct,
+        nested,
+    }
 }
 
 #[cfg(test)]
diff --git a/gen/src/out.rs b/gen/src/out.rs
index 2733c32..bf880cc 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -2,6 +2,7 @@ use crate::gen::block::Block;
 use crate::gen::builtin::Builtins;
 use crate::gen::include::Includes;
 use crate::gen::Opt;
+use crate::syntax::namespace::Namespace;
 use crate::syntax::Types;
 use std::cell::RefCell;
 use std::fmt::{self, Arguments, Write};
@@ -18,6 +19,7 @@ pub(crate) struct OutFile<'a> {
 #[derive(Default)]
 pub struct Content<'a> {
     bytes: String,
+    namespace: &'a Namespace,
     blocks: Vec<BlockBoundary<'a>>,
     section_pending: bool,
     blocks_pending: usize,
@@ -54,6 +56,10 @@ impl<'a> OutFile<'a> {
         self.content.get_mut().end_block(block);
     }
 
+    pub fn set_namespace(&mut self, namespace: &'a Namespace) {
+        self.content.get_mut().set_namespace(namespace);
+    }
+
     pub fn write_fmt(&self, args: Arguments) {
         let content = &mut *self.content.borrow_mut();
         Write::write_fmt(content, args).unwrap();
@@ -118,6 +124,16 @@ impl<'a> Content<'a> {
         self.push_block_boundary(BlockBoundary::End(block));
     }
 
+    pub fn set_namespace(&mut self, namespace: &'a Namespace) {
+        for name in self.namespace.iter().rev() {
+            self.end_block(Block::UserDefinedNamespace(name));
+        }
+        for name in namespace {
+            self.begin_block(Block::UserDefinedNamespace(name));
+        }
+        self.namespace = namespace;
+    }
+
     pub fn write_fmt(&mut self, args: Arguments) {
         Write::write_fmt(self, args).unwrap();
     }
@@ -147,6 +163,7 @@ impl<'a> Content<'a> {
     }
 
     fn flush(&mut self) {
+        self.set_namespace(Default::default());
         if self.blocks_pending > 0 {
             self.flush_blocks();
         }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0b6a5aa..352d643 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -57,7 +57,8 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
     }
 }
 
-fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntries<'a>) {
+fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
+    out.set_namespace(&ns_entries.namespace);
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -127,11 +128,8 @@ fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &NamespaceEntri
         }
     }
 
-    for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        let block = Block::UserDefinedNamespace(namespace);
-        out.begin_block(block);
+    for (_, nested_ns_entries) in ns_entries.nested_content() {
         gen_namespace_contents(out, nested_ns_entries);
-        out.end_block(block);
     }
 }
 
@@ -974,6 +972,7 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
+    out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 834a1d5..7628b0a 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -2,6 +2,7 @@ use crate::syntax::qualified::QualifiedName;
 use crate::syntax::Api;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
+use std::iter::FromIterator;
 use std::slice::Iter;
 use syn::parse::{Parse, ParseStream, Result};
 use syn::{Ident, Token};
@@ -10,7 +11,7 @@ mod kw {
     syn::custom_keyword!(namespace);
 }
 
-#[derive(Clone)]
+#[derive(Clone, Default)]
 pub struct Namespace {
     segments: Vec<Ident>,
 }
@@ -37,6 +38,13 @@ impl Namespace {
     }
 }
 
+impl Default for &Namespace {
+    fn default() -> Self {
+        const ROOT: &Namespace = &Namespace::ROOT;
+        ROOT
+    }
+}
+
 impl Parse for Namespace {
     fn parse(input: ParseStream) -> Result<Self> {
         let segments = QualifiedName::parse_quoted_or_unquoted(input)?.segments;
@@ -67,6 +75,16 @@ impl<'a> IntoIterator for &'a Namespace {
     }
 }
 
+impl<'a> FromIterator<&'a Ident> for Namespace {
+    fn from_iter<I>(idents: I) -> Self
+    where
+        I: IntoIterator<Item = &'a Ident>,
+    {
+        let segments = idents.into_iter().cloned().collect();
+        Namespace { segments }
+    }
+}
+
 impl Api {
     pub fn namespace(&self) -> Option<&Namespace> {
         match self {

From e279735b790d95b78fd245f983dee26df713b1d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 03:08:37 +0000
Subject: [PATCH 1198/2232] Standardize on write_ prefix for functions that write to a &mut OutFile


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 352d643..a2d41a7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -23,8 +23,8 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     out.include.extend(&opt.include);
 
     let apis_by_namespace = NamespaceEntries::new(apis);
-    gen_namespace_forward_declarations(out, &apis_by_namespace);
-    gen_namespace_contents(out, &apis_by_namespace);
+    write_namespace_forward_declarations(out, &apis_by_namespace);
+    write_namespace_contents(out, &apis_by_namespace);
 
     if !header {
         out.next_section();
@@ -37,7 +37,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     out_file.content()
 }
 
-fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
+fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
     let apis = ns_entries.direct_content();
 
     for api in apis {
@@ -52,12 +52,12 @@ fn gen_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceE
 
     for (namespace, nested_ns_entries) in ns_entries.nested_content() {
         writeln!(out, "namespace {} {{", namespace);
-        gen_namespace_forward_declarations(out, nested_ns_entries);
+        write_namespace_forward_declarations(out, nested_ns_entries);
         writeln!(out, "}} // namespace {}", namespace);
     }
 }
 
-fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
+fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
     out.set_namespace(&ns_entries.namespace);
     let apis = ns_entries.direct_content();
 
@@ -129,7 +129,7 @@ fn gen_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEn
     }
 
     for (_, nested_ns_entries) in ns_entries.nested_content() {
-        gen_namespace_contents(out, nested_ns_entries);
+        write_namespace_contents(out, nested_ns_entries);
     }
 }
 

From 58711a9563e4abf71e0c0456246a5493cf640df8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 03:11:37 +0000
Subject: [PATCH 1199/2232] Move #pragma once to where header block is written


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index d88c12d..cf718da 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -47,9 +47,14 @@ impl<'a> Includes<'a> {
 }
 
 pub(super) fn write(out: &mut OutFile) {
+    let header = out.header;
     let include = &mut out.include;
     let out = &mut include.content;
 
+    if header {
+        writeln!(out, "#pragma once");
+    }
+
     for include in &include.custom {
         match include.kind {
             IncludeKind::Quoted => {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a2d41a7..08bb1fc 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -15,10 +15,6 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     let mut out_file = OutFile::new(header, opt, types);
     let out = &mut out_file;
 
-    if header {
-        writeln!(out.include, "#pragma once");
-    }
-
     pick_includes_and_builtins(out);
     out.include.extend(&opt.include);
 

From 11bd7ff8d64bbc6d72ffced7ebf7102fd2533ffe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 03:44:58 +0000
Subject: [PATCH 1200/2232] Perform exhaustive match in pick_includes_and_builtins


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 08bb1fc..2b4e552 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -179,7 +179,7 @@ fn pick_includes_and_builtins(out: &mut OutFile) {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
             }
-            _ => {}
+            Type::Ref(_) | Type::Void(_) => {}
         }
     }
 }

From 1f010c6ef07c270b9045f51d5901dc814ec0bfe0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:27:57 +0000
Subject: [PATCH 1201/2232] Move cxxbridge05$exception declaration to builtins


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 4b8dce5..36e32f8 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -22,6 +22,7 @@ pub struct Builtins<'a> {
     pub rust_str_repr: bool,
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
+    pub exception: bool,
     pub content: Content<'a>,
 }
 
@@ -195,4 +196,13 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     out.end_block(Block::Namespace("rust"));
+
+    if builtin.exception {
+        out.begin_block(Block::ExternC);
+        writeln!(
+            out,
+            "const char *cxxbridge05$exception(const char *, size_t);",
+        );
+        out.end_block(Block::ExternC);
+    }
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2b4e552..3498ef9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -106,7 +106,6 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
 
     if !out.header {
         out.begin_block(Block::ExternC);
-        write_exception_glue(out, apis);
         for api in apis {
             match api {
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
@@ -316,26 +315,6 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
     );
 }
 
-fn write_exception_glue(out: &mut OutFile, apis: &[&Api]) {
-    let mut has_cxx_throws = false;
-    for api in apis {
-        if let Api::CxxFunction(efn) = api {
-            if efn.throws {
-                has_cxx_throws = true;
-                break;
-            }
-        }
-    }
-
-    if has_cxx_throws {
-        out.next_section();
-        writeln!(
-            out,
-            "const char *cxxbridge05$exception(const char *, size_t);",
-        );
-    }
-}
-
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
     out.next_section();
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
@@ -500,13 +479,14 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
     writeln!(out, ";");
     if efn.throws {
         out.include.cstring = true;
+        out.builtin.exception = true;
         writeln!(out, "        throw$.ptr = nullptr;");
         writeln!(out, "      }},");
         writeln!(out, "      [&](const char *catch$) noexcept {{");
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = cxxbridge05$exception(catch$, throw$.len);",
+            "        throw$.ptr = ::cxxbridge05$exception(catch$, throw$.len);",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");

From ca563ee3359fa13cdf305a181d6a4c1c0d025880 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:29:35 +0000
Subject: [PATCH 1202/2232] Move Block::ExternC to the individual items


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 3498ef9..dfa0502 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -105,7 +105,6 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
     }
 
     if !out.header {
-        out.begin_block(Block::ExternC);
         for api in apis {
             match api {
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
@@ -113,7 +112,6 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
                 _ => {}
             }
         }
-        out.end_block(Block::ExternC);
     }
 
     for api in apis {
@@ -317,6 +315,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
 
 fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
     out.next_section();
+    out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
     }
@@ -498,6 +497,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
             write_function_pointer_trampoline(out, efn, var, f);
         }
     }
+    out.end_block(Block::ExternC);
 }
 
 fn write_function_pointer_trampoline(
@@ -516,9 +516,11 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn) {
+    out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
     write_rust_function_decl_impl(out, &link_name, efn, indirect_call);
+    out.end_block(Block::ExternC);
 }
 
 fn write_rust_function_decl_impl(

From 0b9b9f84b6ee591717ca073e5cbd38440465387d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:41:30 +0000
Subject: [PATCH 1203/2232] Specify lifetimes which are connected to OutFile


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index dfa0502..abc965a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -181,7 +181,7 @@ fn pick_includes_and_builtins(out: &mut OutFile) {
     }
 }
 
-fn write_struct(out: &mut OutFile, strct: &Struct) {
+fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -211,7 +211,11 @@ fn write_struct_using(out: &mut OutFile, ident: &CppName) {
     );
 }
 
-fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&ExternFn]) {
+fn write_struct_with_methods<'a>(
+    out: &mut OutFile<'a>,
+    ety: &'a ExternType,
+    methods: &[&ExternFn],
+) {
     let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -236,7 +240,7 @@ fn write_struct_with_methods(out: &mut OutFile, ety: &ExternType, methods: &[&Ex
     writeln!(out, "#endif // {}", guard);
 }
 
-fn write_enum(out: &mut OutFile, enm: &Enum) {
+fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -253,7 +257,7 @@ fn write_enum(out: &mut OutFile, enm: &Enum) {
     writeln!(out, "#endif // {}", guard);
 }
 
-fn check_enum(out: &mut OutFile, enm: &Enum) {
+fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     write!(
         out,
         "static_assert(sizeof({}) == sizeof(",
@@ -313,7 +317,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
     );
 }
 
-fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn) {
+fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
@@ -515,7 +519,7 @@ fn write_function_pointer_trampoline(
     write_rust_function_shim_impl(out, &c_trampoline, f, &r_trampoline, indirect_call);
 }
 
-fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn) {
+fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -573,7 +577,7 @@ fn write_rust_function_decl_impl(
     writeln!(out, ") noexcept;");
 }
 
-fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn) {
+fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }

From d7a3a18e573153203381253377fac68ba985f57b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:45:38 +0000
Subject: [PATCH 1204/2232] Prefer namespace over ns


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 5c21bc4..08ce4b4 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -29,8 +29,8 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
     let mut direct = Vec::new();
     let mut nested_namespaces = BTreeMap::new();
     for api in &apis {
-        if let Some(ns) = api.namespace() {
-            let first_ns_elem = ns.iter().nth(depth);
+        if let Some(namespace) = api.namespace() {
+            let first_ns_elem = namespace.iter().nth(depth);
             if let Some(first_ns_elem) = first_ns_elem {
                 nested_namespaces
                     .entry(first_ns_elem)
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 3796431..e55a08a 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -43,7 +43,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
     let _ = syntax::error::ERRORS;
 
     let namespace = match Namespace::parse_bridge_attr_namespace.parse(args) {
-        Ok(ns) => ns,
+        Ok(namespace) => namespace,
         Err(err) => return err.to_compile_error().into(),
     };
     let mut ffi = parse_macro_input!(input as Module);
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 354790a..03c4380 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -13,7 +13,7 @@ fn check(cx: &mut Check, ident: &Ident) {
 }
 
 fn check_ident(cx: &mut Check, ident: &CppName) {
-    for segment in &ident.ns {
+    for segment in &ident.namespace {
         check(cx, segment);
     }
     check(cx, &ident.ident);
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 9255feb..d1f3adc 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -15,13 +15,13 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
         Some(receiver) => {
             let receiver_ident = types.resolve(&receiver.ty);
             join!(
-                efn.ident.cxx.ns,
+                efn.ident.cxx.namespace,
                 CXXBRIDGE,
                 receiver_ident.ident,
                 efn.ident.rust
             )
         }
-        None => join!(efn.ident.cxx.ns, CXXBRIDGE, efn.ident.rust),
+        None => join!(efn.ident.cxx.namespace, CXXBRIDGE, efn.ident.rust),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 90af17f..b12d72b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -197,7 +197,7 @@ pub struct Pair {
 // to output it as a qualified name or as an unqualfied name.
 #[derive(Clone)]
 pub struct CppName {
-    pub ns: Namespace,
+    pub namespace: Namespace,
     pub ident: Ident,
 }
 
diff --git a/syntax/names.rs b/syntax/names.rs
index a61ffc3..ee010a9 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -5,19 +5,23 @@ use syn::Token;
 impl Pair {
     /// Use this constructor when the item can't have a different
     /// name in Rust and C++.
-    pub fn new(ns: Namespace, ident: Ident) -> Self {
+    pub fn new(namespace: Namespace, ident: Ident) -> Self {
         Self {
             rust: ident.clone(),
-            cxx: CppName::new(ns, ident),
+            cxx: CppName::new(namespace, ident),
         }
     }
 
     /// 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(ns: Namespace, cxx_ident: Ident, rust_ident: Ident) -> Self {
+    pub fn new_from_differing_names(
+        namespace: Namespace,
+        cxx_ident: Ident,
+        rust_ident: Ident,
+    ) -> Self {
         Self {
             rust: rust_ident,
-            cxx: CppName::new(ns, cxx_ident),
+            cxx: CppName::new(namespace, cxx_ident),
         }
     }
 }
@@ -47,12 +51,12 @@ impl ResolvableName {
 }
 
 impl CppName {
-    pub fn new(ns: Namespace, ident: Ident) -> Self {
-        Self { ns, ident }
+    pub fn new(namespace: Namespace, ident: Ident) -> Self {
+        Self { namespace, ident }
     }
 
     fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
-        self.ns.iter().chain(std::iter::once(&self.ident))
+        self.namespace.iter().chain(std::iter::once(&self.ident))
     }
 
     fn join(&self, sep: &str) -> String {
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 7628b0a..02e5dc2 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -32,9 +32,9 @@ impl Namespace {
 
         input.parse::<kw::namespace>()?;
         input.parse::<Token![=]>()?;
-        let ns = input.parse::<Namespace>()?;
+        let namespace = input.parse::<Namespace>()?;
         input.parse::<Option<Token![,]>>()?;
-        Ok(ns)
+        Ok(namespace)
     }
 }
 
@@ -88,10 +88,10 @@ impl<'a> FromIterator<&'a Ident> for Namespace {
 impl Api {
     pub fn namespace(&self) -> Option<&Namespace> {
         match self {
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.ns),
-            Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.ns),
-            Api::Enum(enm) => Some(&enm.ident.cxx.ns),
-            Api::Struct(strct) => Some(&strct.ident.cxx.ns),
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.namespace),
+            Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.namespace),
+            Api::Enum(enm) => Some(&enm.ident.cxx.namespace),
+            Api::Struct(strct) => Some(&strct.ident.cxx.namespace),
             Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
         }
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1927554..c170f79 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -21,22 +21,27 @@ pub mod kw {
     syn::custom_keyword!(Result);
 }
 
-pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool, ns: &Namespace) -> Vec<Api> {
+pub fn parse_items(
+    cx: &mut Errors,
+    items: Vec<Item>,
+    trusted: bool,
+    namespace: &Namespace,
+) -> Vec<Api> {
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(cx, item, ns.clone()) {
+            Item::Struct(item) => match parse_struct(cx, item, namespace.clone()) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item, ns.clone()) {
+            Item::Enum(item) => match parse_enum(cx, item, namespace.clone()) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
             Item::ForeignMod(foreign_mod) => {
-                parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, ns)
+                parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
             }
-            Item::Impl(item) => match parse_impl(item, ns) {
+            Item::Impl(item) => match parse_impl(item, namespace) {
                 Ok(imp) => apis.push(imp),
                 Err(err) => cx.push(err),
             },
@@ -47,7 +52,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool, ns: &Namesp
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -68,7 +73,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
-            namespace: Some(&mut ns),
+            namespace: Some(&mut namespace),
             ..Default::default()
         },
     );
@@ -85,7 +90,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<
         doc,
         derives,
         struct_token: item.struct_token,
-        ident: Pair::new(ns.clone(), item.ident),
+        ident: Pair::new(namespace.clone(), item.ident),
         brace_token: fields.brace_token,
         fields: fields
             .named
@@ -93,14 +98,14 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut ns: Namespace) -> Result<
             .map(|field| {
                 Ok(Var {
                     ident: field.ident.unwrap(),
-                    ty: parse_type(&field.ty, &ns)?,
+                    ty: parse_type(&field.ty, &namespace)?,
                 })
             })
             .collect::<Result<_>>()?,
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum, mut ns: Namespace) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -121,7 +126,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, mut ns: Namespace) -> Result<Api>
         attrs::Parser {
             doc: Some(&mut doc),
             repr: Some(&mut repr),
-            namespace: Some(&mut ns),
+            namespace: Some(&mut namespace),
             ..Default::default()
         },
     );
@@ -172,7 +177,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, mut ns: Namespace) -> Result<Api>
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
-        ident: Pair::new(ns, item.ident),
+        ident: Pair::new(namespace, item.ident),
         brace_token,
         variants,
         repr,
@@ -184,7 +189,7 @@ fn parse_foreign_mod(
     foreign_mod: ItemForeignMod,
     out: &mut Vec<Api>,
     trusted: bool,
-    ns: &Namespace,
+    namespace: &Namespace,
 ) {
     let lang = match parse_lang(&foreign_mod.abi) {
         Ok(lang) => lang,
@@ -209,12 +214,13 @@ fn parse_foreign_mod(
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, ns.clone()) {
+                match parse_extern_type(cx, foreign, lang, trusted, namespace.clone()) {
                     Ok(ety) => items.push(ety),
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, ns.clone()) {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, namespace.clone())
+            {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -225,7 +231,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, ns.clone()) {
+                match parse_extern_verbatim(cx, tokens, lang, namespace.clone()) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }
@@ -277,7 +283,7 @@ fn parse_extern_type(
     foreign_type: &ForeignItemType,
     lang: Lang,
     trusted: bool,
-    mut ns: Namespace,
+    mut namespace: Namespace,
 ) -> Result<Api> {
     let mut doc = Doc::new();
     attrs::parse(
@@ -285,7 +291,7 @@ fn parse_extern_type(
         &foreign_type.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
-            namespace: Some(&mut ns),
+            namespace: Some(&mut namespace),
             ..Default::default()
         },
     );
@@ -299,7 +305,7 @@ fn parse_extern_type(
     Ok(api_type(ExternType {
         doc,
         type_token,
-        ident: Pair::new(ns, ident),
+        ident: Pair::new(namespace, ident),
         semi_token,
         trusted,
     }))
@@ -309,7 +315,7 @@ fn parse_extern_fn(
     cx: &mut Errors,
     foreign_fn: &ForeignItemFn,
     lang: Lang,
-    mut ns: Namespace,
+    mut namespace: Namespace,
 ) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
@@ -335,7 +341,7 @@ fn parse_extern_fn(
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
-            namespace: Some(&mut ns),
+            namespace: Some(&mut namespace),
             ..Default::default()
         },
     );
@@ -367,7 +373,7 @@ fn parse_extern_fn(
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
-                let ty = parse_type(&arg.ty, &ns)?;
+                let ty = parse_type(&arg.ty, &namespace)?;
                 if ident != "self" {
                     args.push_value(Var { ident, ty });
                     if let Some(comma) = comma {
@@ -394,12 +400,12 @@ fn parse_extern_fn(
     }
 
     let mut throws_tokens = None;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &ns)?;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &namespace)?;
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let ident = Pair::new_from_differing_names(
-        ns,
+        namespace,
         cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
         rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
     );
@@ -432,7 +438,7 @@ fn parse_extern_verbatim(
     cx: &mut Errors,
     tokens: &TokenStream,
     lang: Lang,
-    mut ns: Namespace,
+    mut namespace: Namespace,
 ) -> Result<Api> {
     // type Alias = crate::path::to::Type;
     let parse = |input: ParseStream| -> Result<TypeAlias> {
@@ -454,7 +460,7 @@ fn parse_extern_verbatim(
             &attrs,
             attrs::Parser {
                 doc: Some(&mut doc),
-                namespace: Some(&mut ns),
+                namespace: Some(&mut namespace),
                 ..Default::default()
             },
         );
@@ -462,7 +468,7 @@ fn parse_extern_verbatim(
         Ok(TypeAlias {
             doc,
             type_token,
-            ident: Pair::new(ns, ident),
+            ident: Pair::new(namespace, ident),
             eq_token,
             ty,
             semi_token,
@@ -481,7 +487,7 @@ fn parse_extern_verbatim(
     }
 }
 
-fn parse_impl(imp: ItemImpl, ns: &Namespace) -> Result<Api> {
+fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -507,7 +513,7 @@ fn parse_impl(imp: ItemImpl, ns: &Namespace) -> Result<Api> {
 
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
-        ty: parse_type(&self_ty, ns)?,
+        ty: parse_type(&self_ty, namespace)?,
         brace_token: imp.brace_token,
     }))
 }
@@ -556,19 +562,19 @@ fn parse_include(input: ParseStream) -> Result<Include> {
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
 }
 
-fn parse_type(ty: &RustType, ns: &Namespace) -> Result<Type> {
+fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => parse_type_reference(ty, ns),
-        RustType::Path(ty) => parse_type_path(ty, ns),
-        RustType::Slice(ty) => parse_type_slice(ty, ns),
-        RustType::BareFn(ty) => parse_type_fn(ty, ns),
+        RustType::Reference(ty) => parse_type_reference(ty, namespace),
+        RustType::Path(ty) => parse_type_path(ty, namespace),
+        RustType::Slice(ty) => parse_type_slice(ty, namespace),
+        RustType::BareFn(ty) => parse_type_fn(ty, namespace),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_reference(ty: &TypeReference, ns: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, ns)?;
+fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, namespace)?;
     let which = match &inner {
         Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
@@ -591,7 +597,7 @@ fn parse_type_reference(ty: &TypeReference, ns: &Namespace) -> Result<Type> {
     })))
 }
 
-fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
+fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
@@ -602,7 +608,7 @@ fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, ns)?;
+                        let inner = parse_type(arg, namespace)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
                             name: maybe_resolved_ident,
                             langle: generic.lt_token,
@@ -612,7 +618,7 @@ fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, ns)?;
+                        let inner = parse_type(arg, namespace)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
                             name: maybe_resolved_ident,
                             langle: generic.lt_token,
@@ -622,7 +628,7 @@ fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, ns)?;
+                        let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
                             name: maybe_resolved_ident,
                             langle: generic.lt_token,
@@ -632,7 +638,7 @@ fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, ns)?;
+                        let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
                             name: maybe_resolved_ident,
                             langle: generic.lt_token,
@@ -648,15 +654,15 @@ fn parse_type_path(ty: &TypePath, ns: &Namespace) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice, ns: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, ns)?;
+fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, namespace)?;
     Ok(Type::Slice(Box::new(Slice {
         bracket: ty.bracket_token,
         inner,
     })))
 }
 
-fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
+fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
             ty,
@@ -674,7 +680,7 @@ fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
         .iter()
         .enumerate()
         .map(|(i, arg)| {
-            let ty = parse_type(&arg.ty, ns)?;
+            let ty = parse_type(&arg.ty, namespace)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("_{}", i),
@@ -683,7 +689,7 @@ fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
         })
         .collect::<Result<_>>()?;
     let mut throws_tokens = None;
-    let ret = parse_return_type(&ty.output, &mut throws_tokens, ns)?;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens, namespace)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
@@ -700,7 +706,7 @@ fn parse_type_fn(ty: &TypeBareFn, ns: &Namespace) -> Result<Type> {
 fn parse_return_type(
     ty: &ReturnType,
     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
-    ns: &Namespace,
+    namespace: &Namespace,
 ) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
@@ -722,7 +728,7 @@ fn parse_return_type(
             }
         }
     }
-    match parse_type(ret, ns)? {
+    match parse_type(ret, namespace)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),
     }
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 0b79d5f..c849a62 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -81,7 +81,7 @@ impl Segment for Namespace {
 
 impl Segment for CppName {
     fn write(&self, symbol: &mut Symbol) {
-        self.ns.write(symbol);
+        self.namespace.write(symbol);
         self.ident.write(symbol);
     }
 }

From b63ed5aa2c7a7b23a731f46c837ce9f49e8745f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:46:33 +0000
Subject: [PATCH 1205/2232] Move set_namespace to individual items


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index abc965a..0369ef5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -54,7 +54,6 @@ fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &Namespac
 }
 
 fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
-    out.set_namespace(&ns_entries.namespace);
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -182,6 +181,7 @@ fn pick_includes_and_builtins(out: &mut OutFile) {
 }
 
 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());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -216,6 +216,7 @@ fn write_struct_with_methods<'a>(
     ety: &'a ExternType,
     methods: &[&ExternFn],
 ) {
+    out.set_namespace(&ety.ident.cxx.namespace);
     let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -241,6 +242,7 @@ fn write_struct_with_methods<'a>(
 }
 
 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());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -258,6 +260,7 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
+    out.set_namespace(&enm.ident.cxx.namespace);
     write!(
         out,
         "static_assert(sizeof({}) == sizeof(",
@@ -319,6 +322,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
+    out.set_namespace(&efn.ident.cxx.namespace);
     out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
@@ -520,6 +524,7 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
+    out.set_namespace(&efn.ident.cxx.namespace);
     out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -578,6 +583,7 @@ fn write_rust_function_decl_impl(
 }
 
 fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
+    out.set_namespace(&efn.ident.cxx.namespace);
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }

From 3ff4fe48a57c9c44dd7070579093a132685ba22c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:46:49 +0000
Subject: [PATCH 1206/2232] Remove namespace from NamespaceEntries


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 08ce4b4..7309aa9 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -1,11 +1,9 @@
-use crate::syntax::namespace::Namespace;
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
-    pub namespace: Namespace,
     direct: Vec<&'a Api>,
     nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
@@ -47,17 +45,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
         .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
         .collect();
 
-    let namespace = apis
-        .first()
-        .copied()
-        .and_then(Api::namespace)
-        .map_or(Namespace::ROOT, |ns| ns.iter().take(depth).collect());
-
-    NamespaceEntries {
-        namespace,
-        direct,
-        nested,
-    }
+    NamespaceEntries { direct, nested }
 }
 
 #[cfg(test)]

From b8f3f5474cdd56daf0959658dddf0c2a1a31caad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:54:58 +0000
Subject: [PATCH 1207/2232] Merge pull request #404 from dtolnay/namespace


Move set_namespace to individual items
---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 08ce4b4..7309aa9 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -1,11 +1,9 @@
-use crate::syntax::namespace::Namespace;
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::BTreeMap;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
-    pub namespace: Namespace,
     direct: Vec<&'a Api>,
     nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
 }
@@ -47,17 +45,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
         .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
         .collect();
 
-    let namespace = apis
-        .first()
-        .copied()
-        .and_then(Api::namespace)
-        .map_or(Namespace::ROOT, |ns| ns.iter().take(depth).collect());
-
-    NamespaceEntries {
-        namespace,
-        direct,
-        nested,
-    }
+    NamespaceEntries { direct, nested }
 }
 
 #[cfg(test)]
diff --git a/gen/src/write.rs b/gen/src/write.rs
index abc965a..0369ef5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -54,7 +54,6 @@ fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &Namespac
 }
 
 fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
-    out.set_namespace(&ns_entries.namespace);
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -182,6 +181,7 @@ fn pick_includes_and_builtins(out: &mut OutFile) {
 }
 
 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());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -216,6 +216,7 @@ fn write_struct_with_methods<'a>(
     ety: &'a ExternType,
     methods: &[&ExternFn],
 ) {
+    out.set_namespace(&ety.ident.cxx.namespace);
     let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.cxx.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -241,6 +242,7 @@ fn write_struct_with_methods<'a>(
 }
 
 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());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
@@ -258,6 +260,7 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
+    out.set_namespace(&enm.ident.cxx.namespace);
     write!(
         out,
         "static_assert(sizeof({}) == sizeof(",
@@ -319,6 +322,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
+    out.set_namespace(&efn.ident.cxx.namespace);
     out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
@@ -520,6 +524,7 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
+    out.set_namespace(&efn.ident.cxx.namespace);
     out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -578,6 +583,7 @@ fn write_rust_function_decl_impl(
 }
 
 fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
+    out.set_namespace(&efn.ident.cxx.namespace);
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }

From 1b0339c16b00f4f874418bbf620ad425db45c60e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 04:55:07 +0000
Subject: [PATCH 1208/2232] Emit all data structures before all functions


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0369ef5..8a4133c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -20,7 +20,8 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 
     let apis_by_namespace = NamespaceEntries::new(apis);
     write_namespace_forward_declarations(out, &apis_by_namespace);
-    write_namespace_contents(out, &apis_by_namespace);
+    write_namespace_data_structures(out, &apis_by_namespace);
+    write_namespace_functions(out, &apis_by_namespace);
 
     if !header {
         out.next_section();
@@ -53,7 +54,10 @@ fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &Namespac
     }
 }
 
-fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
+fn write_namespace_data_structures<'a>(
+    out: &mut OutFile<'a>,
+    ns_entries: &'a NamespaceEntries<'a>,
+) {
     let apis = ns_entries.direct_content();
 
     let mut methods_for_type = HashMap::new();
@@ -103,6 +107,14 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
         }
     }
 
+    for (_, nested_ns_entries) in ns_entries.nested_content() {
+        write_namespace_data_structures(out, nested_ns_entries);
+    }
+}
+
+fn write_namespace_functions<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
+    let apis = ns_entries.direct_content();
+
     if !out.header {
         for api in apis {
             match api {
@@ -121,7 +133,7 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
     }
 
     for (_, nested_ns_entries) in ns_entries.nested_content() {
-        write_namespace_contents(out, nested_ns_entries);
+        write_namespace_functions(out, nested_ns_entries);
     }
 }
 

From e1109d93a1959151386b72d21c98af6b787525fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:01:20 +0000
Subject: [PATCH 1209/2232] Emit data structures and functions each in source order


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8a4133c..7753ebf 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -20,8 +20,8 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 
     let apis_by_namespace = NamespaceEntries::new(apis);
     write_namespace_forward_declarations(out, &apis_by_namespace);
-    write_namespace_data_structures(out, &apis_by_namespace);
-    write_namespace_functions(out, &apis_by_namespace);
+    write_data_structures(out, apis);
+    write_functions(out, apis);
 
     if !header {
         out.next_section();
@@ -54,12 +54,7 @@ fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &Namespac
     }
 }
 
-fn write_namespace_data_structures<'a>(
-    out: &mut OutFile<'a>,
-    ns_entries: &'a NamespaceEntries<'a>,
-) {
-    let apis = ns_entries.direct_content();
-
+fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     let mut methods_for_type = HashMap::new();
     for api in apis {
         if let Api::RustFunction(efn) = api {
@@ -106,15 +101,9 @@ fn write_namespace_data_structures<'a>(
             }
         }
     }
-
-    for (_, nested_ns_entries) in ns_entries.nested_content() {
-        write_namespace_data_structures(out, nested_ns_entries);
-    }
 }
 
-fn write_namespace_functions<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
-    let apis = ns_entries.direct_content();
-
+fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     if !out.header {
         for api in apis {
             match api {
@@ -131,10 +120,6 @@ fn write_namespace_functions<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespac
             write_rust_function_shim(out, efn);
         }
     }
-
-    for (_, nested_ns_entries) in ns_entries.nested_content() {
-        write_namespace_functions(out, nested_ns_entries);
-    }
 }
 
 fn pick_includes_and_builtins(out: &mut OutFile) {

From eed76fa82ac5e8f7c29b85cdcf2785f32aeed902 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:07:08 +0000
Subject: [PATCH 1210/2232] Merge pull request #405 from dtolnay/sort


Emit data structures and functions in source order
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0369ef5..7753ebf 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -20,7 +20,8 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 
     let apis_by_namespace = NamespaceEntries::new(apis);
     write_namespace_forward_declarations(out, &apis_by_namespace);
-    write_namespace_contents(out, &apis_by_namespace);
+    write_data_structures(out, apis);
+    write_functions(out, apis);
 
     if !header {
         out.next_section();
@@ -53,9 +54,7 @@ fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &Namespac
     }
 }
 
-fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a NamespaceEntries<'a>) {
-    let apis = ns_entries.direct_content();
-
+fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     let mut methods_for_type = HashMap::new();
     for api in apis {
         if let Api::RustFunction(efn) = api {
@@ -102,7 +101,9 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
             }
         }
     }
+}
 
+fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     if !out.header {
         for api in apis {
             match api {
@@ -119,10 +120,6 @@ fn write_namespace_contents<'a>(out: &mut OutFile<'a>, ns_entries: &'a Namespace
             write_rust_function_shim(out, efn);
         }
     }
-
-    for (_, nested_ns_entries) in ns_entries.nested_content() {
-        write_namespace_contents(out, nested_ns_entries);
-    }
 }
 
 fn pick_includes_and_builtins(out: &mut OutFile) {

From 169bb47773b665105b30573499f2ce6c4323820f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:07:17 +0000
Subject: [PATCH 1211/2232] Clean up control flow of write::gen


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7753ebf..f5ef807 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -22,11 +22,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     write_namespace_forward_declarations(out, &apis_by_namespace);
     write_data_structures(out, apis);
     write_functions(out, apis);
-
-    if !header {
-        out.next_section();
-        write_generic_instantiations(out);
-    }
+    write_generic_instantiations(out);
 
     builtin::write(out);
     include::write(out);
@@ -957,6 +953,11 @@ fn to_mangled(ty: &Type, types: &Types) -> Symbol {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
+    if out.header {
+        return;
+    }
+
+    out.next_section();
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {

From 0472c262bcdf0631460c23caefa97963667d8c23 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:30:30 +0000
Subject: [PATCH 1212/2232] Flatten a nested if-let


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 7309aa9..18f2896 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -27,15 +27,12 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
     let mut direct = Vec::new();
     let mut nested_namespaces = BTreeMap::new();
     for api in &apis {
-        if let Some(namespace) = api.namespace() {
-            let first_ns_elem = namespace.iter().nth(depth);
-            if let Some(first_ns_elem) = first_ns_elem {
-                nested_namespaces
-                    .entry(first_ns_elem)
-                    .or_insert_with(Vec::new)
-                    .push(*api);
-                continue;
-            }
+        if let Some(first_ns_elem) = api.namespace().and_then(|ns| ns.iter().nth(depth)) {
+            nested_namespaces
+                .entry(first_ns_elem)
+                .or_insert_with(Vec::new)
+                .push(*api);
+            continue;
         }
         direct.push(*api);
     }

From 8704e3ed14eada73216eb55ac226011e48479556 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:33:25 +0000
Subject: [PATCH 1213/2232] Preserve source order of namespaces for forward declaration


This enables us to avoid answering hard questions like whether 'foo10'
is less or greater than 'foo9'.

---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 18f2896..748ec3f 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -1,11 +1,11 @@
 use crate::syntax::Api;
 use proc_macro2::Ident;
-use std::collections::BTreeMap;
+use std::collections::HashMap as Map;
 use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
     direct: Vec<&'a Api>,
-    nested: BTreeMap<&'a Ident, NamespaceEntries<'a>>,
+    nested: Vec<(&'a Ident, NamespaceEntries<'a>)>,
 }
 
 impl<'a> NamespaceEntries<'a> {
@@ -25,13 +25,18 @@ impl<'a> NamespaceEntries<'a> {
 
 fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
     let mut direct = Vec::new();
-    let mut nested_namespaces = BTreeMap::new();
+    let mut nested_namespaces = Vec::new();
+    let mut index_of_namespace = Map::new();
+
     for api in &apis {
         if let Some(first_ns_elem) = api.namespace().and_then(|ns| ns.iter().nth(depth)) {
-            nested_namespaces
-                .entry(first_ns_elem)
-                .or_insert_with(Vec::new)
-                .push(*api);
+            match index_of_namespace.get(first_ns_elem) {
+                None => {
+                    index_of_namespace.insert(first_ns_elem, nested_namespaces.len());
+                    nested_namespaces.push((first_ns_elem, vec![*api]));
+                }
+                Some(&index) => nested_namespaces[index].1.push(*api),
+            }
             continue;
         }
         direct.push(*api);

From de4b55392752ae3688b06ce326f04bd541d1e4f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 05:37:25 +0000
Subject: [PATCH 1214/2232] Update test_ns_entries_sort to match source order sorting


---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
index 748ec3f..143f6ec 100644
--- a/gen/src/alphasort.rs
+++ b/gen/src/alphasort.rs
@@ -83,12 +83,21 @@ mod tests {
         assert_ident(root_direct[2], "B");
 
         let mut root_nested = root.nested_content();
-        let (id, d) = root_nested.next().unwrap();
-        assert_eq!(id, "D");
         let (id, g) = root_nested.next().unwrap();
         assert_eq!(id, "G");
+        let (id, d) = root_nested.next().unwrap();
+        assert_eq!(id, "D");
         assert!(root_nested.next().is_none());
 
+        // ::G
+        let g_direct = g.direct_content();
+        assert_eq!(g_direct.len(), 2);
+        assert_ident(g_direct[0], "E");
+        assert_ident(g_direct[1], "H");
+
+        let mut g_nested = g.nested_content();
+        assert!(g_nested.next().is_none());
+
         // ::D
         let d_direct = d.direct_content();
         assert_eq!(d_direct.len(), 3);
@@ -105,15 +114,6 @@ mod tests {
         assert_eq!(k_direct.len(), 2);
         assert_ident(k_direct[0], "L");
         assert_ident(k_direct[1], "M");
-
-        // ::G
-        let g_direct = g.direct_content();
-        assert_eq!(g_direct.len(), 2);
-        assert_ident(g_direct[0], "E");
-        assert_ident(g_direct[1], "H");
-
-        let mut g_nested = g.nested_content();
-        assert!(g_nested.next().is_none());
     }
 
     fn assert_ident(api: &Api, expected: &str) {

From f7b81fb845a0aaa4238653af9f9a5624b290bfcb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 06:39:22 +0000
Subject: [PATCH 1215/2232] Move NamespaceEntries to nested:: module


Since the way we sort nested namespaces is no longer based on alphabetic
order.

---

diff --git a/gen/src/alphasort.rs b/gen/src/alphasort.rs
deleted file mode 100644
index 143f6ec..0000000
--- a/gen/src/alphasort.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-use crate::syntax::Api;
-use proc_macro2::Ident;
-use std::collections::HashMap as Map;
-use std::iter::FromIterator;
-
-pub struct NamespaceEntries<'a> {
-    direct: Vec<&'a Api>,
-    nested: Vec<(&'a Ident, NamespaceEntries<'a>)>,
-}
-
-impl<'a> NamespaceEntries<'a> {
-    pub fn new(apis: &'a [Api]) -> Self {
-        let api_refs = Vec::from_iter(apis);
-        sort_by_inner_namespace(api_refs, 0)
-    }
-
-    pub fn direct_content(&self) -> &[&'a Api] {
-        &self.direct
-    }
-
-    pub fn nested_content(&self) -> impl Iterator<Item = (&'a Ident, &NamespaceEntries<'a>)> {
-        self.nested.iter().map(|(k, entries)| (*k, entries))
-    }
-}
-
-fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
-    let mut direct = Vec::new();
-    let mut nested_namespaces = Vec::new();
-    let mut index_of_namespace = Map::new();
-
-    for api in &apis {
-        if let Some(first_ns_elem) = api.namespace().and_then(|ns| ns.iter().nth(depth)) {
-            match index_of_namespace.get(first_ns_elem) {
-                None => {
-                    index_of_namespace.insert(first_ns_elem, nested_namespaces.len());
-                    nested_namespaces.push((first_ns_elem, vec![*api]));
-                }
-                Some(&index) => nested_namespaces[index].1.push(*api),
-            }
-            continue;
-        }
-        direct.push(*api);
-    }
-
-    let nested = nested_namespaces
-        .into_iter()
-        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
-        .collect();
-
-    NamespaceEntries { direct, nested }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::NamespaceEntries;
-    use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Pair};
-    use proc_macro2::{Ident, Span};
-    use syn::Token;
-
-    #[test]
-    fn test_ns_entries_sort() {
-        let apis = &[
-            make_api(None, "C"),
-            make_api(None, "A"),
-            make_api(Some("G"), "E"),
-            make_api(Some("D"), "F"),
-            make_api(Some("G"), "H"),
-            make_api(Some("D::K"), "L"),
-            make_api(Some("D::K"), "M"),
-            make_api(None, "B"),
-            make_api(Some("D"), "I"),
-            make_api(Some("D"), "J"),
-        ];
-
-        let root = NamespaceEntries::new(apis);
-
-        // ::
-        let root_direct = root.direct_content();
-        assert_eq!(root_direct.len(), 3);
-        assert_ident(root_direct[0], "C");
-        assert_ident(root_direct[1], "A");
-        assert_ident(root_direct[2], "B");
-
-        let mut root_nested = root.nested_content();
-        let (id, g) = root_nested.next().unwrap();
-        assert_eq!(id, "G");
-        let (id, d) = root_nested.next().unwrap();
-        assert_eq!(id, "D");
-        assert!(root_nested.next().is_none());
-
-        // ::G
-        let g_direct = g.direct_content();
-        assert_eq!(g_direct.len(), 2);
-        assert_ident(g_direct[0], "E");
-        assert_ident(g_direct[1], "H");
-
-        let mut g_nested = g.nested_content();
-        assert!(g_nested.next().is_none());
-
-        // ::D
-        let d_direct = d.direct_content();
-        assert_eq!(d_direct.len(), 3);
-        assert_ident(d_direct[0], "F");
-        assert_ident(d_direct[1], "I");
-        assert_ident(d_direct[2], "J");
-
-        let mut d_nested = d.nested_content();
-        let (id, k) = d_nested.next().unwrap();
-        assert_eq!(id, "K");
-
-        // ::D::K
-        let k_direct = k.direct_content();
-        assert_eq!(k_direct.len(), 2);
-        assert_ident(k_direct[0], "L");
-        assert_ident(k_direct[1], "M");
-    }
-
-    fn assert_ident(api: &Api, expected: &str) {
-        if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.ident.cxx.ident, expected);
-        } else {
-            unreachable!()
-        }
-    }
-
-    fn make_api(ns: Option<&str>, ident: &str) -> Api {
-        let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
-        Api::CxxType(ExternType {
-            doc: Doc::new(),
-            type_token: Token![type](Span::call_site()),
-            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
-            semi_token: Token![;](Span::call_site()),
-            trusted: false,
-        })
-    }
-}
diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 8626058..61a8bbe 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -1,7 +1,6 @@
 // Functionality that is shared between the cxx_build::bridge entry point and
 // the cxxbridge CLI command.
 
-mod alphasort;
 mod block;
 mod builtin;
 mod check;
@@ -10,6 +9,7 @@ mod file;
 pub(super) mod fs;
 mod ifndef;
 pub(super) mod include;
+mod nested;
 pub(super) mod out;
 mod write;
 
diff --git a/gen/src/nested.rs b/gen/src/nested.rs
new file mode 100644
index 0000000..143f6ec
--- /dev/null
+++ b/gen/src/nested.rs
@@ -0,0 +1,137 @@
+use crate::syntax::Api;
+use proc_macro2::Ident;
+use std::collections::HashMap as Map;
+use std::iter::FromIterator;
+
+pub struct NamespaceEntries<'a> {
+    direct: Vec<&'a Api>,
+    nested: Vec<(&'a Ident, NamespaceEntries<'a>)>,
+}
+
+impl<'a> NamespaceEntries<'a> {
+    pub fn new(apis: &'a [Api]) -> Self {
+        let api_refs = Vec::from_iter(apis);
+        sort_by_inner_namespace(api_refs, 0)
+    }
+
+    pub fn direct_content(&self) -> &[&'a Api] {
+        &self.direct
+    }
+
+    pub fn nested_content(&self) -> impl Iterator<Item = (&'a Ident, &NamespaceEntries<'a>)> {
+        self.nested.iter().map(|(k, entries)| (*k, entries))
+    }
+}
+
+fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
+    let mut direct = Vec::new();
+    let mut nested_namespaces = Vec::new();
+    let mut index_of_namespace = Map::new();
+
+    for api in &apis {
+        if let Some(first_ns_elem) = api.namespace().and_then(|ns| ns.iter().nth(depth)) {
+            match index_of_namespace.get(first_ns_elem) {
+                None => {
+                    index_of_namespace.insert(first_ns_elem, nested_namespaces.len());
+                    nested_namespaces.push((first_ns_elem, vec![*api]));
+                }
+                Some(&index) => nested_namespaces[index].1.push(*api),
+            }
+            continue;
+        }
+        direct.push(*api);
+    }
+
+    let nested = nested_namespaces
+        .into_iter()
+        .map(|(k, apis)| (k, sort_by_inner_namespace(apis, depth + 1)))
+        .collect();
+
+    NamespaceEntries { direct, nested }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::NamespaceEntries;
+    use crate::syntax::namespace::Namespace;
+    use crate::syntax::{Api, Doc, ExternType, Pair};
+    use proc_macro2::{Ident, Span};
+    use syn::Token;
+
+    #[test]
+    fn test_ns_entries_sort() {
+        let apis = &[
+            make_api(None, "C"),
+            make_api(None, "A"),
+            make_api(Some("G"), "E"),
+            make_api(Some("D"), "F"),
+            make_api(Some("G"), "H"),
+            make_api(Some("D::K"), "L"),
+            make_api(Some("D::K"), "M"),
+            make_api(None, "B"),
+            make_api(Some("D"), "I"),
+            make_api(Some("D"), "J"),
+        ];
+
+        let root = NamespaceEntries::new(apis);
+
+        // ::
+        let root_direct = root.direct_content();
+        assert_eq!(root_direct.len(), 3);
+        assert_ident(root_direct[0], "C");
+        assert_ident(root_direct[1], "A");
+        assert_ident(root_direct[2], "B");
+
+        let mut root_nested = root.nested_content();
+        let (id, g) = root_nested.next().unwrap();
+        assert_eq!(id, "G");
+        let (id, d) = root_nested.next().unwrap();
+        assert_eq!(id, "D");
+        assert!(root_nested.next().is_none());
+
+        // ::G
+        let g_direct = g.direct_content();
+        assert_eq!(g_direct.len(), 2);
+        assert_ident(g_direct[0], "E");
+        assert_ident(g_direct[1], "H");
+
+        let mut g_nested = g.nested_content();
+        assert!(g_nested.next().is_none());
+
+        // ::D
+        let d_direct = d.direct_content();
+        assert_eq!(d_direct.len(), 3);
+        assert_ident(d_direct[0], "F");
+        assert_ident(d_direct[1], "I");
+        assert_ident(d_direct[2], "J");
+
+        let mut d_nested = d.nested_content();
+        let (id, k) = d_nested.next().unwrap();
+        assert_eq!(id, "K");
+
+        // ::D::K
+        let k_direct = k.direct_content();
+        assert_eq!(k_direct.len(), 2);
+        assert_ident(k_direct[0], "L");
+        assert_ident(k_direct[1], "M");
+    }
+
+    fn assert_ident(api: &Api, expected: &str) {
+        if let Api::CxxType(cxx_type) = api {
+            assert_eq!(cxx_type.ident.cxx.ident, expected);
+        } else {
+            unreachable!()
+        }
+    }
+
+    fn make_api(ns: Option<&str>, ident: &str) -> Api {
+        let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
+        Api::CxxType(ExternType {
+            doc: Doc::new(),
+            type_token: Token![type](Span::call_site()),
+            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            semi_token: Token![;](Span::call_site()),
+            trusted: false,
+        })
+    }
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f5ef807..a42d03e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,5 +1,5 @@
-use crate::gen::alphasort::NamespaceEntries;
 use crate::gen::block::Block;
+use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};

From 6edeaab3cb21824c0e24c9c34e50824ca1cd45ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 06:48:37 +0000
Subject: [PATCH 1216/2232] Treat un-namespaced items the same as root namespace


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 143f6ec..8a1dd6d 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -29,7 +29,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
     let mut index_of_namespace = Map::new();
 
     for api in &apis {
-        if let Some(first_ns_elem) = api.namespace().and_then(|ns| ns.iter().nth(depth)) {
+        if let Some(first_ns_elem) = api.namespace().iter().nth(depth) {
             match index_of_namespace.get(first_ns_elem) {
                 None => {
                     index_of_namespace.insert(first_ns_elem, nested_namespaces.len());
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 02e5dc2..160650f 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -86,13 +86,13 @@ impl<'a> FromIterator<&'a Ident> for Namespace {
 }
 
 impl Api {
-    pub fn namespace(&self) -> Option<&Namespace> {
+    pub fn namespace(&self) -> &Namespace {
         match self {
-            Api::CxxFunction(efn) | Api::RustFunction(efn) => Some(&efn.ident.cxx.namespace),
-            Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident.cxx.namespace),
-            Api::Enum(enm) => Some(&enm.ident.cxx.namespace),
-            Api::Struct(strct) => Some(&strct.ident.cxx.namespace),
-            Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => None,
+            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::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => Default::default(),
         }
     }
 }

From 90b133b5532a29b99a887fcad2f9327956079bcd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 06:53:37 +0000
Subject: [PATCH 1217/2232] Move C++-specific namespace code unused by the proc macro


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 61a8bbe..3d12c71 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -9,6 +9,7 @@ mod file;
 pub(super) mod fs;
 mod ifndef;
 pub(super) mod include;
+mod namespace;
 mod nested;
 pub(super) mod out;
 mod write;
diff --git a/gen/src/namespace.rs b/gen/src/namespace.rs
new file mode 100644
index 0000000..a8b049f
--- /dev/null
+++ b/gen/src/namespace.rs
@@ -0,0 +1,14 @@
+use crate::syntax::namespace::Namespace;
+use crate::syntax::Api;
+
+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::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => Default::default(),
+        }
+    }
+}
diff --git a/syntax/namespace.rs b/syntax/namespace.rs
index 160650f..07185e1 100644
--- a/syntax/namespace.rs
+++ b/syntax/namespace.rs
@@ -1,5 +1,4 @@
 use crate::syntax::qualified::QualifiedName;
-use crate::syntax::Api;
 use quote::IdentFragment;
 use std::fmt::{self, Display};
 use std::iter::FromIterator;
@@ -84,15 +83,3 @@ impl<'a> FromIterator<&'a Ident> for Namespace {
         Namespace { segments }
     }
 }
-
-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::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => Default::default(),
-        }
-    }
-}

From 7b0e510029beca0b255267470c8f2123520db0d3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 07:51:41 +0000
Subject: [PATCH 1218/2232] Omit namespaces containing no forward declarations


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 8a1dd6d..0a8816c 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -1,7 +1,6 @@
 use crate::syntax::Api;
 use proc_macro2::Ident;
 use std::collections::HashMap as Map;
-use std::iter::FromIterator;
 
 pub struct NamespaceEntries<'a> {
     direct: Vec<&'a Api>,
@@ -9,9 +8,8 @@ pub struct NamespaceEntries<'a> {
 }
 
 impl<'a> NamespaceEntries<'a> {
-    pub fn new(apis: &'a [Api]) -> Self {
-        let api_refs = Vec::from_iter(apis);
-        sort_by_inner_namespace(api_refs, 0)
+    pub fn new(apis: Vec<&'a Api>) -> Self {
+        sort_by_inner_namespace(apis, 0)
     }
 
     pub fn direct_content(&self) -> &[&'a Api] {
@@ -56,6 +54,7 @@ mod tests {
     use crate::syntax::namespace::Namespace;
     use crate::syntax::{Api, Doc, ExternType, Pair};
     use proc_macro2::{Ident, Span};
+    use std::iter::FromIterator;
     use syn::Token;
 
     #[test]
@@ -73,7 +72,7 @@ mod tests {
             make_api(Some("D"), "J"),
         ];
 
-        let root = NamespaceEntries::new(apis);
+        let root = NamespaceEntries::new(Vec::from_iter(apis));
 
         // ::
         let root_direct = root.direct_content();
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a42d03e..b2046c5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -18,8 +18,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     pick_includes_and_builtins(out);
     out.include.extend(&opt.include);
 
-    let apis_by_namespace = NamespaceEntries::new(apis);
-    write_namespace_forward_declarations(out, &apis_by_namespace);
+    write_forward_declarations(out, apis);
     write_data_structures(out, apis);
     write_functions(out, apis);
     write_generic_instantiations(out);
@@ -30,23 +29,34 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     out_file.content()
 }
 
-fn write_namespace_forward_declarations(out: &mut OutFile, ns_entries: &NamespaceEntries) {
-    let apis = ns_entries.direct_content();
+fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
+    let needs_forward_declaration = |api: &&Api| match api {
+        Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
+        _ => false,
+    };
 
-    for api in apis {
-        match api {
-            Api::Include(include) => out.include.insert(include),
-            Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
-            Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
-            Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
-            _ => {}
+    let apis_by_namespace =
+        NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
+
+    write(out, &apis_by_namespace);
+
+    fn write(out: &mut OutFile, ns_entries: &NamespaceEntries) {
+        let apis = ns_entries.direct_content();
+
+        for api in apis {
+            match api {
+                Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
+                Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
+                Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx.ident),
+                _ => unreachable!(),
+            }
         }
-    }
 
-    for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-        writeln!(out, "namespace {} {{", namespace);
-        write_namespace_forward_declarations(out, nested_ns_entries);
-        writeln!(out, "}} // namespace {}", namespace);
+        for (namespace, nested_ns_entries) in ns_entries.nested_content() {
+            writeln!(out, "namespace {} {{", namespace);
+            write(out, nested_ns_entries);
+            writeln!(out, "}} // namespace {}", namespace);
+        }
     }
 }
 
@@ -65,6 +75,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     for api in apis {
         match api {
+            Api::Include(include) => out.include.insert(include),
             Api::Struct(strct) => {
                 out.next_section();
                 if !out.types.cxx.contains(&strct.ident.rust) {

From d920be59083e03020459fe39ae31bf435c9b5850 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 07:51:41 +0000
Subject: [PATCH 1219/2232] Indent forward declarations by namespace depth


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b2046c5..9d07173 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -38,12 +38,13 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
     let apis_by_namespace =
         NamespaceEntries::new(apis.iter().filter(needs_forward_declaration).collect());
 
-    write(out, &apis_by_namespace);
+    write(out, &apis_by_namespace, 0);
 
-    fn write(out: &mut OutFile, ns_entries: &NamespaceEntries) {
+    fn write(out: &mut OutFile, ns_entries: &NamespaceEntries, indent: usize) {
         let apis = ns_entries.direct_content();
 
         for api in apis {
+            write!(out, "{:1$}", "", indent);
             match api {
                 Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
                 Api::CxxType(ety) => write_struct_using(out, &ety.ident.cxx),
@@ -53,9 +54,9 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
         }
 
         for (namespace, nested_ns_entries) in ns_entries.nested_content() {
-            writeln!(out, "namespace {} {{", namespace);
-            write(out, nested_ns_entries);
-            writeln!(out, "}} // namespace {}", namespace);
+            writeln!(out, "{:2$}namespace {} {{", "", namespace, indent);
+            write(out, nested_ns_entries, indent + 2);
+            writeln!(out, "{:1$}}}", "", indent);
         }
     }
 }

From 0e3ee8e398ebd17e0b68768c7587ac5cfd56d126 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 07:51:41 +0000
Subject: [PATCH 1220/2232] Implement forward declaration for enums


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 9d07173..ebef728 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -31,7 +31,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 
 fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
     let needs_forward_declaration = |api: &&Api| match api {
-        Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
+        Api::Struct(_) | Api::Enum(_) | Api::CxxType(_) | Api::RustType(_) => true,
         _ => false,
     };
 
@@ -47,6 +47,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
             write!(out, "{:1$}", "", indent);
             match api {
                 Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx.ident),
+                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),
                 _ => unreachable!(),
@@ -207,6 +208,12 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "struct {};", ident);
 }
 
+fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
+    write!(out, "enum class {} : ", enm.ident.cxx.ident);
+    write_atom(out, enm.repr);
+    writeln!(out, ";");
+}
+
 fn write_struct_using(out: &mut OutFile, ident: &CppName) {
     writeln!(
         out,

From 4bfca11c1e2504364fe277b54bfc0c875ff9ef5d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 07:59:11 +0000
Subject: [PATCH 1221/2232] Fix duplicated forward declaration for extern enums


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ebef728..68b5468 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -31,7 +31,8 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 
 fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
     let needs_forward_declaration = |api: &&Api| match api {
-        Api::Struct(_) | Api::Enum(_) | Api::CxxType(_) | Api::RustType(_) => true,
+        Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
+        Api::Enum(enm) => !out.types.cxx.contains(&enm.ident.rust),
         _ => false,
     };
 

From dfb82d74d5e78af406b04c93eecd0499fcf765c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:10:15 +0000
Subject: [PATCH 1222/2232] Move Api::Include handling to pick_includes_and_builtins


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 68b5468..2967594 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -15,7 +15,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
     let mut out_file = OutFile::new(header, opt, types);
     let out = &mut out_file;
 
-    pick_includes_and_builtins(out);
+    pick_includes_and_builtins(out, apis);
     out.include.extend(&opt.include);
 
     write_forward_declarations(out, apis);
@@ -78,7 +78,6 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     for api in apis {
         match api {
-            Api::Include(include) => out.include.insert(include),
             Api::Struct(strct) => {
                 out.next_section();
                 if !out.types.cxx.contains(&strct.ident.rust) {
@@ -132,7 +131,13 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     }
 }
 
-fn pick_includes_and_builtins(out: &mut OutFile) {
+fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
+    for api in apis {
+        if let Api::Include(include) = api {
+            out.include.insert(include);
+        }
+    }
+
     for ty in out.types {
         match ty {
             Type::Ident(ident) => match Atom::from(&ident.rust) {

From 58cd0c75b48457408a245fed507363fe86a80edd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:10:37 +0000
Subject: [PATCH 1223/2232] Skeleton for topological sort


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index 3d12c71..d19dea0 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -12,6 +12,7 @@ pub(super) mod include;
 mod namespace;
 mod nested;
 pub(super) mod out;
+mod toposort;
 mod write;
 
 pub(super) use self::error::Error;
diff --git a/gen/src/toposort.rs b/gen/src/toposort.rs
new file mode 100644
index 0000000..97b10f9
--- /dev/null
+++ b/gen/src/toposort.rs
@@ -0,0 +1,8 @@
+use crate::syntax::{Api, Types};
+use std::iter::FromIterator;
+
+pub fn sort<'a>(apis: &'a [Api], types: &Types) -> Vec<&'a Api> {
+    // TODO https://github.com/dtolnay/cxx/issues/292
+    let _ = types;
+    Vec::from_iter(apis)
+}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2967594..1cd6d07 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,7 +1,7 @@
 use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{builtin, include, Opt};
+use crate::gen::{builtin, include, toposort, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -76,7 +76,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for api in apis {
+    for api in toposort::sort(apis, out.types) {
         match api {
             Api::Struct(strct) => {
                 out.next_section();

From 8faec77e12aa6e4da2eb120d39a18adae5d2989b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:31:34 +0000
Subject: [PATCH 1224/2232] 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 @@ use crate::syntax::Api;
 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::gen::{builtin, include, toposort, Opt};
 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 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
         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 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     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 pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 }
 
 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_struct_decl(out: &mut OutFile, ident: &Ident) {
 }
 
 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 @@ fn write_struct_with_methods<'a>(
     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_struct_with_methods<'a>(
 }
 
 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 write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 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 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
         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 check_trivial_extern_type(out: &mut OutFile, id: &CppName) {
 
 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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     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_function_pointer_trampoline(
 }
 
 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 @@ fn write_rust_function_decl_impl(
         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_decl_impl(
 }
 
 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 @@ fn write_generic_instantiations(out: &mut OutFile) {
     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 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
     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::file::Module;
 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(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 }
 
 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_struct(strct: &Struct) -> TokenStream {
 }
 
 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_enum(enm: &Enum) -> TokenStream {
 }
 
 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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     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(alias: &TypeAlias) -> TokenStream {
 
 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 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
     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(cx: &mut Check, ident: &Ident) {
     }
 }
 
-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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
         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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
                 }
             }
             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 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
         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 @@ pub enum Lang {
 // 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 @@ impl ResolvableName {
         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 Namespace {
     }
 }
 
-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::atom::Atom::{self, *};
 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 struct Types<'a> {
     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 @@ impl<'a> Types<'a> {
         }
 
         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 @@ impl<'a> Types<'a> {
         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")

From da71ef6aa5767defe09a2cbda218341fcb7f8f3c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:36:03 +0000
Subject: [PATCH 1225/2232] Remove ResolvableName from Ty1


This is not treated as resolvable for now. It only supports a hardcoded
set of generic types (UniquePtr, CxxVector, Box, Vec).

---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 6684b6a..782d617 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -160,7 +160,7 @@ pub enum Type {
 }
 
 pub struct Ty1 {
-    pub name: ResolvableName,
+    pub name: Ident,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c170f79..6b5d925 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -602,15 +602,14 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
         let ident = segment.ident.clone();
-        let maybe_resolved_ident = ResolvableName::new(ident.clone());
         match &segment.arguments {
-            PathArguments::None => return Ok(Type::Ident(maybe_resolved_ident)),
+            PathArguments::None => return Ok(Type::Ident(ResolvableName::new(ident))),
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
-                            name: maybe_resolved_ident,
+                            name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -620,7 +619,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
-                            name: maybe_resolved_ident,
+                            name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -630,7 +629,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
-                            name: maybe_resolved_ident,
+                            name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
@@ -640,7 +639,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
-                            name: maybe_resolved_ident,
+                            name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 57db8eb..2b32532 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -39,7 +39,7 @@ impl ToTokens for Var {
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
-        let name = self.name.rust.to_string();
+        let name = self.name.to_string();
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {

From 17a934c4040c30eaa6e3f81a937301d51d7378bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:53:59 +0000
Subject: [PATCH 1226/2232] Rename non-Ident fields previously named ident


It will be clearer to avoid using 'ident' to refer to anything but Ident.

---

diff --git a/gen/src/namespace.rs b/gen/src/namespace.rs
index 7343875..b79c38f 100644
--- a/gen/src/namespace.rs
+++ b/gen/src/namespace.rs
@@ -4,10 +4,10 @@ use crate::syntax::Api;
 impl Api {
     pub fn namespace(&self) -> &Namespace {
         match self {
-            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::CxxFunction(efn) | Api::RustFunction(efn) => &efn.name.namespace,
+            Api::CxxType(ety) | Api::RustType(ety) => &ety.name.namespace,
+            Api::Enum(enm) => &enm.name.namespace,
+            Api::Struct(strct) => &strct.name.namespace,
             Api::Impl(_) | Api::Include(_) | Api::TypeAlias(_) => Default::default(),
         }
     }
diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 0a8816c..22b0c9f 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -117,7 +117,7 @@ mod tests {
 
     fn assert_ident(api: &Api, expected: &str) {
         if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.ident.cxx.ident, expected);
+            assert_eq!(cxx_type.name.cxx, expected);
         } else {
             unreachable!()
         }
@@ -128,7 +128,7 @@ mod tests {
         Api::CxxType(ExternType {
             doc: Doc::new(),
             type_token: Token![type](Span::call_site()),
-            ident: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            name: Pair::new(ns, Ident::new(ident, Span::call_site())),
             semi_token: Token![;](Span::call_site()),
             trusted: false,
         })
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7c16e81..8688797 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -32,7 +32,7 @@ pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u
 fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
     let needs_forward_declaration = |api: &&Api| match api {
         Api::Struct(_) | Api::CxxType(_) | Api::RustType(_) => true,
-        Api::Enum(enm) => !out.types.cxx.contains(&enm.ident.rust),
+        Api::Enum(enm) => !out.types.cxx.contains(&enm.name.rust),
         _ => false,
     };
 
@@ -47,10 +47,10 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
         for api in apis {
             write!(out, "{:1$}", "", indent);
             match api {
-                Api::Struct(strct) => write_struct_decl(out, &strct.ident.cxx),
+                Api::Struct(strct) => write_struct_decl(out, &strct.name.cxx),
                 Api::Enum(enm) => write_enum_decl(out, enm),
-                Api::CxxType(ety) => write_struct_using(out, &ety.ident),
-                Api::RustType(ety) => write_struct_decl(out, &ety.ident.cxx),
+                Api::CxxType(ety) => write_struct_using(out, &ety.name),
+                Api::RustType(ety) => write_struct_decl(out, &ety.name.cxx),
                 _ => unreachable!(),
             }
         }
@@ -80,20 +80,20 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         match api {
             Api::Struct(strct) => {
                 out.next_section();
-                if !out.types.cxx.contains(&strct.ident.rust) {
+                if !out.types.cxx.contains(&strct.name.rust) {
                     write_struct(out, strct);
                 }
             }
             Api::Enum(enm) => {
                 out.next_section();
-                if out.types.cxx.contains(&enm.ident.rust) {
+                if out.types.cxx.contains(&enm.name.rust) {
                     check_enum(out, enm);
                 } else {
                     write_enum(out, enm);
                 }
             }
             Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.ident.rust) {
+                if let Some(methods) = methods_for_type.get(&ety.name.rust) {
                     out.next_section();
                     write_struct_with_methods(out, ety, methods);
                 }
@@ -105,8 +105,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     out.next_section();
     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)
+            if out.types.required_trivial.contains_key(&ety.name.rust) {
+                check_trivial_extern_type(out, &ety.name)
             }
         }
     }
@@ -193,14 +193,14 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 }
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
-    out.set_namespace(&strct.ident.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.ident.to_symbol());
+    out.set_namespace(&strct.name.namespace);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.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);
+    writeln!(out, "struct {} final {{", strct.name.cxx);
     for field in &strct.fields {
         write!(out, "  ");
         write_type_space(out, &field.ty);
@@ -215,7 +215,7 @@ fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
 }
 
 fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
-    write!(out, "enum class {} : ", enm.ident.cxx);
+    write!(out, "enum class {} : ", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, ";");
 }
@@ -229,24 +229,24 @@ fn write_struct_with_methods<'a>(
     ety: &'a ExternType,
     methods: &[&ExternFn],
 ) {
-    out.set_namespace(&ety.ident.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.ident.to_symbol());
+    out.set_namespace(&ety.name.namespace);
+    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.name.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);
-    writeln!(out, "  {}() = delete;", ety.ident.cxx);
+    writeln!(out, "struct {} final {{", ety.name.cxx);
+    writeln!(out, "  {}() = delete;", ety.name.cxx);
     writeln!(
         out,
         "  {}(const {} &) = delete;",
-        ety.ident.cxx, ety.ident.cxx,
+        ety.name.cxx, ety.name.cxx,
     );
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
-        let local_name = method.ident.cxx.to_string();
+        let local_name = method.name.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
@@ -255,14 +255,14 @@ fn write_struct_with_methods<'a>(
 }
 
 fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
-    out.set_namespace(&enm.ident.namespace);
-    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.ident.to_symbol());
+    out.set_namespace(&enm.name.namespace);
+    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.name.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);
+    write!(out, "enum class {} : ", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
@@ -273,8 +273,8 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
-    out.set_namespace(&enm.ident.namespace);
-    write!(out, "static_assert(sizeof({}) == sizeof(", enm.ident.cxx);
+    out.set_namespace(&enm.name.namespace);
+    write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");
     for variant in &enm.variants {
@@ -283,7 +283,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.ident.cxx, variant.ident, variant.discriminant,
+            enm.name.cxx, variant.ident, variant.discriminant,
         );
     }
 }
@@ -331,7 +331,7 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
-    out.set_namespace(&efn.ident.namespace);
+    out.set_namespace(&efn.name.namespace);
     out.begin_block(Block::ExternC);
     if let Some(annotation) = &out.opt.cxx_impl_annotations {
         write!(out, "{} ", annotation);
@@ -377,12 +377,12 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     write!(out, "  ");
     write_return_type(out, &efn.ret);
     match &efn.receiver {
-        None => write!(out, "(*{}$)(", efn.ident.rust),
+        None => write!(out, "(*{}$)(", efn.name.rust),
         Some(receiver) => write!(
             out,
             "({}::*{}$)(",
             out.types.resolve(&receiver.ty).to_fully_qualified(),
-            efn.ident.rust,
+            efn.name.rust,
         ),
     }
     for (i, arg) in efn.args.iter().enumerate() {
@@ -399,12 +399,12 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     write!(out, " = ");
     match &efn.receiver {
-        None => write!(out, "{}", efn.ident.to_fully_qualified()),
+        None => write!(out, "{}", efn.name.to_fully_qualified()),
         Some(receiver) => write!(
             out,
             "&{}::{}",
             out.types.resolve(&receiver.ty).to_fully_qualified(),
-            efn.ident.cxx,
+            efn.name.cxx,
         ),
     }
     writeln!(out, ";");
@@ -438,8 +438,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         _ => {}
     }
     match &efn.receiver {
-        None => write!(out, "{}$(", efn.ident.rust),
-        Some(_) => write!(out, "(self.*{}$)(", efn.ident.rust),
+        None => write!(out, "{}$(", efn.name.rust),
+        Some(_) => write!(out, "(self.*{}$)(", efn.name.rust),
     }
     for (i, arg) in efn.args.iter().enumerate() {
         if i > 0 {
@@ -533,7 +533,7 @@ fn write_function_pointer_trampoline(
 }
 
 fn write_rust_function_decl<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
-    out.set_namespace(&efn.ident.namespace);
+    out.set_namespace(&efn.name.namespace);
     out.begin_block(Block::ExternC);
     let link_name = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
@@ -592,13 +592,13 @@ fn write_rust_function_decl_impl(
 }
 
 fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
-    out.set_namespace(&efn.ident.namespace);
+    out.set_namespace(&efn.name.namespace);
     for line in efn.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
     let local_name = match &efn.sig.receiver {
-        None => efn.ident.cxx.to_string(),
-        Some(receiver) => format!("{}::{}", out.types.resolve(&receiver.ty).cxx, efn.ident.cxx),
+        None => efn.name.cxx.to_string(),
+        Some(receiver) => format!("{}::{}", out.types.resolve(&receiver.ty).cxx, efn.name.cxx),
     };
     let invoke = mangle::extern_fn(efn, out.types);
     let indirect_call = false;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 026ec43..029c54f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -43,10 +43,8 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
-                let ident = &ety.ident;
-                if !types.structs.contains_key(&ident.rust)
-                    && !types.enums.contains_key(&ident.rust)
-                {
+                let ident = &ety.name.rust;
+                if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
                     expanded.extend(expand_cxx_type(ety));
                 }
             }
@@ -125,10 +123,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 }
 
 fn expand_struct(strct: &Struct) -> TokenStream {
-    let ident = &strct.ident;
+    let ident = &strct.name.rust;
     let doc = &strct.doc;
     let derives = DeriveAttribute(&strct.derives);
-    let type_id = type_id(&strct.ident);
+    let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
@@ -152,10 +150,10 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 }
 
 fn expand_enum(enm: &Enum) -> TokenStream {
-    let ident = &enm.ident;
+    let ident = &enm.name.rust;
     let doc = &enm.doc;
     let repr = enm.repr;
-    let type_id = type_id(&enm.ident);
+    let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
         let variant_ident = &variant.ident;
         let discriminant = &variant.discriminant;
@@ -185,9 +183,9 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 }
 
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
-    let ident = &ety.ident;
+    let ident = &ety.name.rust;
     let doc = &ety.doc;
-    let type_id = type_id(&ety.ident);
+    let type_id = type_id(&ety.name);
 
     quote! {
         #doc
@@ -235,7 +233,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(efn, types);
-    let local_name = format_ident!("__{}", efn.ident.rust);
+    let local_name = format_ident!("__{}", efn.name.rust);
     quote! {
         #[link_name = #link_name]
         fn #local_name(#(#all_args,)* #outparam) #ret;
@@ -323,7 +321,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             }
         })
         .collect::<TokenStream>();
-    let local_name = format_ident!("__{}", efn.ident.rust);
+    let local_name = format_ident!("__{}", efn.name.rust);
     let call = if indirect_return {
         let ret = expand_extern_type(efn.ret.as_ref().unwrap());
         setup.extend(quote! {
@@ -420,7 +418,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
-    let ident = &efn.ident;
+    let ident = &efn.name.rust;
     let function_shim = quote! {
         #doc
         pub #unsafety fn #ident(#(#all_args,)*) #ret {
@@ -449,7 +447,7 @@ fn expand_function_pointer_trampoline(
     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.ident.rust, var);
+    let catch_unwind_label = format!("::{}::{}", efn.name.rust, var);
     let shim = expand_rust_function_shim_impl(
         sig,
         types,
@@ -475,7 +473,7 @@ fn expand_function_pointer_trampoline(
 }
 
 fn expand_rust_type(ety: &ExternType) -> TokenStream {
-    let ident = &ety.ident;
+    let ident = &ety.name.rust;
     quote! {
         use super::#ident;
     }
@@ -490,12 +488,12 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     //     |    doesn't have a size known at compile-time
     //     required by this bound in `ffi::_::__AssertSized`
 
-    let ident = &ety.ident;
+    let ident = &ety.name.rust;
     let begin_span = Token![::](ety.type_token.span);
     let sized = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Sized
     };
-    quote_spanned! {ident.rust.span()=>
+    quote_spanned! {ident.span()=>
         let _ = {
             fn __AssertSized<T: ?#sized + #sized>() {}
             __AssertSized::<#ident>
@@ -505,9 +503,9 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
-    let local_name = format_ident!("__{}", efn.ident.rust);
-    let catch_unwind_label = format!("::{}", efn.ident.rust);
-    let invoke = Some(&efn.ident.rust);
+    let local_name = format_ident!("__{}", efn.name.rust);
+    let catch_unwind_label = format!("::{}", efn.name.rust);
+    let invoke = Some(&efn.name.rust);
     expand_rust_function_shim_impl(
         efn,
         types,
@@ -675,7 +673,7 @@ fn expand_rust_function_shim_impl(
 
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
-    let ident = &alias.ident;
+    let ident = &alias.name.rust;
     let ty = &alias.ty;
     quote! {
         #doc
@@ -684,8 +682,8 @@ fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
 }
 
 fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
-    let ident = &alias.ident;
-    let type_id = type_id(ident);
+    let ident = &alias.name.rust;
+    let type_id = type_id(&alias.name);
     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::<);
@@ -695,7 +693,7 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
         const _: fn() = #begin #ident, #type_id #end;
     };
 
-    if types.required_trivial.contains_key(&alias.ident.rust) {
+    if types.required_trivial.contains_key(&alias.name.rust) {
         let begin = quote_spanned!(begin_span=> ::cxx::private::verify_extern_kind::<);
         verify.extend(quote! {
             const _: fn() = #begin #ident, ::cxx::kind::Trivial #end;
diff --git a/syntax/check.rs b/syntax/check.rs
index ba488e1..e8a6448 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -167,16 +167,16 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
-    let ident = &strct.ident;
-    check_reserved_name(cx, &ident.rust);
+    let name = &strct.name;
+    check_reserved_name(cx, &name.rust);
 
     if strct.fields.is_empty() {
         let span = span_for_struct_error(strct);
         cx.error(span, "structs without any fields are not supported");
     }
 
-    if cx.types.cxx.contains(&ident.rust) {
-        if let Some(ety) = cx.types.untrusted.get(&ident.rust) {
+    if cx.types.cxx.contains(&name.rust) {
+        if let Some(ety) = cx.types.untrusted.get(&name.rust) {
             let msg = "extern shared struct must be declared in an `unsafe extern` block";
             cx.error(ety, msg);
         }
@@ -198,7 +198,7 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 }
 
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
-    check_reserved_name(cx, &enm.ident.rust);
+    check_reserved_name(cx, &enm.name.rust);
 
     if enm.variants.is_empty() {
         let span = span_for_enum_error(enm);
@@ -207,13 +207,13 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 }
 
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
-    check_reserved_name(cx, &ety.ident.rust);
+    check_reserved_name(cx, &ety.name.rust);
 
-    if let Some(reason) = cx.types.required_trivial.get(&ety.ident.rust) {
+    if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
         let what = match reason {
-            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.ident.rust),
-            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.ident.rust),
-            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.ident.rust),
+            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
+            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
+            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
diff --git a/syntax/ident.rs b/syntax/ident.rs
index bb2fe46..aaf7832 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -24,28 +24,28 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
-                check_ident(cx, &strct.ident);
+                check_ident(cx, &strct.name);
                 for field in &strct.fields {
                     check(cx, &field.ident);
                 }
             }
             Api::Enum(enm) => {
-                check_ident(cx, &enm.ident);
+                check_ident(cx, &enm.name);
                 for variant in &enm.variants {
                     check(cx, &variant.ident);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                check_ident(cx, &ety.ident);
+                check_ident(cx, &ety.name);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                check(cx, &efn.ident.rust);
+                check(cx, &efn.name.rust);
                 for arg in &efn.args {
                     check(cx, &arg.ident);
                 }
             }
             Api::TypeAlias(alias) => {
-                check_ident(cx, &alias.ident);
+                check_ident(cx, &alias.name);
             }
         }
     }
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 55ffca5..cc5115a 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -15,13 +15,13 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
         Some(receiver) => {
             let receiver_ident = types.resolve(&receiver.ty);
             join!(
-                efn.ident.namespace,
+                efn.name.namespace,
                 CXXBRIDGE,
                 receiver_ident.cxx,
-                efn.ident.rust
+                efn.name.rust
             )
         }
-        None => join!(efn.ident.namespace, CXXBRIDGE, efn.ident.rust),
+        None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 782d617..ac6350a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -67,7 +67,7 @@ pub enum IncludeKind {
 pub struct ExternType {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Pair,
+    pub name: Pair,
     pub semi_token: Token![;],
     pub trusted: bool,
 }
@@ -76,7 +76,7 @@ pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub struct_token: Token![struct],
-    pub ident: Pair,
+    pub name: Pair,
     pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
@@ -84,7 +84,7 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub enum_token: Token![enum],
-    pub ident: Pair,
+    pub name: Pair,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
@@ -93,7 +93,7 @@ pub struct Enum {
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
-    pub ident: Pair,
+    pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
 }
@@ -101,7 +101,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub type_token: Token![type],
-    pub ident: Pair,
+    pub name: Pair,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 6b5d925..2136653 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -90,7 +90,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
         doc,
         derives,
         struct_token: item.struct_token,
-        ident: Pair::new(namespace.clone(), item.ident),
+        name: Pair::new(namespace.clone(), item.ident),
         brace_token: fields.brace_token,
         fields: fields
             .named
@@ -177,7 +177,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Resu
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
-        ident: Pair::new(namespace, item.ident),
+        name: Pair::new(namespace, item.ident),
         brace_token,
         variants,
         repr,
@@ -241,8 +241,8 @@ fn parse_foreign_mod(
     }
 
     let mut types = items.iter().filter_map(|item| match item {
-        Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.ident),
-        Api::TypeAlias(alias) => Some(&alias.ident),
+        Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
+        Api::TypeAlias(alias) => Some(&alias.name),
         _ => None,
     });
     if let (Some(single_type), None) = (types.next(), types.next()) {
@@ -305,7 +305,7 @@ fn parse_extern_type(
     Ok(api_type(ExternType {
         doc,
         type_token,
-        ident: Pair::new(namespace, ident),
+        name: Pair::new(namespace, ident),
         semi_token,
         trusted,
     }))
@@ -404,7 +404,7 @@ fn parse_extern_fn(
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let ident = Pair::new_from_differing_names(
+    let name = Pair::new_from_differing_names(
         namespace,
         cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
         rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
@@ -419,7 +419,7 @@ fn parse_extern_fn(
     Ok(api_function(ExternFn {
         lang,
         doc,
-        ident,
+        name,
         sig: Signature {
             unsafety,
             fn_token,
@@ -468,7 +468,7 @@ fn parse_extern_verbatim(
         Ok(TypeAlias {
             doc,
             type_token,
-            ident: Pair::new(namespace, ident),
+            name: Pair::new(namespace, ident),
             eq_token,
             ty,
             semi_token,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 2b32532..15c23dc 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -85,7 +85,7 @@ impl ToTokens for ExternType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
+        self.name.to_tokens(tokens);
     }
 }
 
@@ -93,7 +93,7 @@ impl ToTokens for TypeAlias {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
+        self.name.to_tokens(tokens);
     }
 }
 
@@ -101,7 +101,7 @@ impl ToTokens for Struct {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.struct_token.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
+        self.name.to_tokens(tokens);
     }
 }
 
@@ -109,7 +109,7 @@ impl ToTokens for Enum {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.enum_token.to_tokens(tokens);
-        self.ident.to_tokens(tokens);
+        self.name.to_tokens(tokens);
     }
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index d9d6361..67b041b 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -70,7 +70,7 @@ impl<'a> Types<'a> {
             match api {
                 Api::Include(_) => {}
                 Api::Struct(strct) => {
-                    let ident = &strct.ident.rust;
+                    let ident = &strct.name.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -81,14 +81,14 @@ impl<'a> Types<'a> {
                         // type, then error.
                         duplicate_name(cx, strct, ident);
                     }
-                    structs.insert(&strct.ident.rust, strct);
+                    structs.insert(&strct.name.rust, strct);
                     for field in &strct.fields {
                         visit(&mut all, &field.ty);
                     }
-                    add_resolution(&strct.ident);
+                    add_resolution(&strct.name);
                 }
                 Api::Enum(enm) => {
-                    let ident = &enm.ident.rust;
+                    let ident = &enm.name.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)
                             || structs.contains_key(ident)
@@ -100,10 +100,10 @@ impl<'a> Types<'a> {
                         duplicate_name(cx, enm, ident);
                     }
                     enums.insert(ident, enm);
-                    add_resolution(&enm.ident);
+                    add_resolution(&enm.name);
                 }
                 Api::CxxType(ety) => {
-                    let ident = &ety.ident.rust;
+                    let ident = &ety.name.rust;
                     if !type_names.insert(ident)
                         && (cxx.contains(ident)
                             || !structs.contains_key(ident) && !enums.contains_key(ident))
@@ -117,21 +117,21 @@ impl<'a> Types<'a> {
                     if !ety.trusted {
                         untrusted.insert(ident, ety);
                     }
-                    add_resolution(&ety.ident);
+                    add_resolution(&ety.name);
                 }
                 Api::RustType(ety) => {
-                    let ident = &ety.ident.rust;
+                    let ident = &ety.name.rust;
                     if !type_names.insert(ident) {
                         duplicate_name(cx, ety, ident);
                     }
                     rust.insert(ident);
-                    add_resolution(&ety.ident);
+                    add_resolution(&ety.name);
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     // Note: duplication of the C++ name is fine because C++ has
                     // function overloading.
-                    if !function_names.insert((&efn.receiver, &efn.ident.rust)) {
-                        duplicate_name(cx, efn, &efn.ident.rust);
+                    if !function_names.insert((&efn.receiver, &efn.name.rust)) {
+                        duplicate_name(cx, efn, &efn.name.rust);
                     }
                     for arg in &efn.args {
                         visit(&mut all, &arg.ty);
@@ -141,13 +141,13 @@ impl<'a> Types<'a> {
                     }
                 }
                 Api::TypeAlias(alias) => {
-                    let ident = &alias.ident;
-                    if !type_names.insert(&ident.rust) {
-                        duplicate_name(cx, alias, &ident.rust);
+                    let ident = &alias.name.rust;
+                    if !type_names.insert(ident) {
+                        duplicate_name(cx, alias, ident);
                     }
-                    cxx.insert(&ident.rust);
-                    aliases.insert(&ident.rust, alias);
-                    add_resolution(&alias.ident);
+                    cxx.insert(ident);
+                    aliases.insert(ident, alias);
+                    add_resolution(&alias.name);
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);

From 9bb232b12e73722c896ee05fe8e75452d0d5b89f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 08:55:51 +0000
Subject: [PATCH 1227/2232] Remove ToTokens for Pair


Clearer to be explicit at the call sites.

---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 15c23dc..500ea0b 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Impl, Pair, Receiver, Ref, ResolvableName, Signature,
+    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
     Slice, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -85,7 +85,7 @@ impl ToTokens for ExternType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
-        self.name.to_tokens(tokens);
+        self.name.rust.to_tokens(tokens);
     }
 }
 
@@ -93,7 +93,7 @@ impl ToTokens for TypeAlias {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
-        self.name.to_tokens(tokens);
+        self.name.rust.to_tokens(tokens);
     }
 }
 
@@ -101,7 +101,7 @@ impl ToTokens for Struct {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.struct_token.to_tokens(tokens);
-        self.name.to_tokens(tokens);
+        self.name.rust.to_tokens(tokens);
     }
 }
 
@@ -109,7 +109,7 @@ impl ToTokens for Enum {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
         self.enum_token.to_tokens(tokens);
-        self.name.to_tokens(tokens);
+        self.name.rust.to_tokens(tokens);
     }
 }
 
@@ -121,12 +121,6 @@ impl ToTokens for ExternFn {
     }
 }
 
-impl ToTokens for Pair {
-    fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.rust.to_tokens(tokens);
-    }
-}
-
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.impl_token.to_tokens(tokens);

From dcfa8e91c6ce09f8ddd78968518d88d2629d0529 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 17:57:45 +0000
Subject: [PATCH 1228/2232] Move include information of builtins to builtin.rs


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 36e32f8..ab2b465 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -41,6 +41,38 @@ pub(super) fn write(out: &mut OutFile) {
     let builtin = &mut out.builtin;
     let out = &mut builtin.content;
 
+    if builtin.rust_string {
+        include.array = true;
+        include.cstdint = true;
+        include.string = true;
+    }
+
+    if builtin.rust_str {
+        include.cstdint = true;
+        include.string = true;
+    }
+
+    if builtin.rust_box {
+        include.new = true;
+        include.type_traits = true;
+    }
+
+    if builtin.rust_vec {
+        include.array = true;
+        include.new = true;
+        include.type_traits = true;
+        builtin.panic = true;
+        builtin.unsafe_bitcopy = true;
+    }
+
+    if builtin.rust_error {
+        include.exception = true;
+    }
+
+    if builtin.rust_isize {
+        include.basetsd = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge05"));
     writeln!(out, "// #include \"rust/cxx.h\"");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8688797..2c3234c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -144,45 +144,18 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
                 | Some(I64) => out.include.cstdint = true,
                 Some(Usize) => out.include.cstddef = true,
-                Some(Isize) => {
-                    out.include.basetsd = true;
-                    out.builtin.rust_isize = true;
-                }
+                Some(Isize) => out.builtin.rust_isize = true,
                 Some(CxxString) => out.include.string = true,
-                Some(RustString) => {
-                    out.include.array = true;
-                    out.include.cstdint = true;
-                    out.include.string = true;
-                    out.builtin.rust_string = true;
-                }
+                Some(RustString) => out.builtin.rust_string = true,
                 Some(Bool) | Some(F32) | Some(F64) | None => {}
             },
-            Type::RustBox(_) => {
-                out.include.new = true;
-                out.include.type_traits = true;
-                out.builtin.rust_box = true;
-            }
-            Type::RustVec(_) => {
-                out.include.array = true;
-                out.include.new = true;
-                out.include.type_traits = true;
-                out.builtin.panic = true;
-                out.builtin.rust_vec = true;
-                out.builtin.unsafe_bitcopy = true;
-            }
+            Type::RustBox(_) => out.builtin.rust_box = true,
+            Type::RustVec(_) => out.builtin.rust_vec = true,
             Type::UniquePtr(_) => out.include.memory = true,
-            Type::Str(_) => {
-                out.include.cstdint = true;
-                out.include.string = true;
-                out.builtin.rust_str = true;
-            }
+            Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
-            Type::Fn(_) => {
-                out.builtin.rust_fn = true;
-            }
-            Type::Slice(_) => {
-                out.builtin.rust_slice = true;
-            }
+            Type::Fn(_) => out.builtin.rust_fn = true,
+            Type::Slice(_) => out.builtin.rust_slice = true,
             Type::SliceRefU8(_) => {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
@@ -750,7 +723,6 @@ fn write_rust_function_shim_impl(
     }
     writeln!(out, ";");
     if sig.throws {
-        out.include.exception = true;
         out.builtin.rust_error = true;
         writeln!(out, "  if (error$.ptr) {{");
         writeln!(out, "    throw ::rust::impl<::rust::Error>::error(error$);");

From 174bd951168e0c72d5b612487c70717e135bc20f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 18:23:52 +0000
Subject: [PATCH 1229/2232] Expose way to bypass trivial destr/move on extern types passed by value


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index ab2b465..7a4ddcd 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -23,6 +23,7 @@ pub struct Builtins<'a> {
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
     pub exception: bool,
+    pub relocatable: bool,
     pub content: Content<'a>,
 }
 
@@ -73,6 +74,10 @@ pub(super) fn write(out: &mut OutFile) {
         include.basetsd = true;
     }
 
+    if builtin.relocatable {
+        include.type_traits = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge05"));
     writeln!(out, "// #include \"rust/cxx.h\"");
@@ -100,6 +105,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE05_RELOCATABLE");
 
     if builtin.manually_drop {
         out.next_section();
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2c3234c..c806e55 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -262,7 +262,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
-    // NOTE: The following two static assertions are just nice-to-have and not
+    // NOTE: The following static assertion is 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:
     //
@@ -273,31 +273,35 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     //
     // Since the user went on the record with their unsafe impl to unsafely
     // claim they KNOW that the type is trivial, it's fine for that to be on
-    // them if that were wrong.
+    // them if that were wrong. However, in practice correctly reasoning about
+    // the relocatability of C++ types is challenging, particularly if the type
+    // definition were to change over time, so for now we add this check.
+    //
+    // There may be legitimate reasons to opt out of this assertion for support
+    // of types that the programmer knows are soundly Rust-movable despite not
+    // being recognized as such by the C++ type system due to a move constructor
+    // or destructor. To opt out of the relocatability check, they need to do
+    // one of the following things in any header used by `include!` in their
+    // bridge.
+    //
+    //      --- if they define the type:
+    //      struct MyType {
+    //        ...
+    //    +   using IsRelocatable = std::true_type;
+    //      };
+    //
+    //      --- otherwise:
+    //    + template <>
+    //    + struct rust::IsRelocatable<MyType> : std::true_type {};
     //
-    // There may be a legitimate reason we'll want to remove these assertions
-    // for support of types that the programmer knows are Rust-movable despite
-    // not being recognized as such by the C++ type system due to a move
-    // constructor or destructor.
 
-    let id = &id.to_fully_qualified();
-    out.include.type_traits = true;
-    writeln!(out, "static_assert(");
-    writeln!(
-        out,
-        "    ::std::is_trivially_move_constructible<{}>::value,",
-        id,
-    );
-    writeln!(
-        out,
-        "    \"type {} marked as Trivial in Rust is not trivially move constructible in C++\");",
-        id,
-    );
+    let id = id.to_fully_qualified();
+    out.builtin.relocatable = true;
     writeln!(out, "static_assert(");
-    writeln!(out, "    ::std::is_trivially_destructible<{}>::value,", id);
+    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
     writeln!(
         out,
-        "    \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",
+        "    \"type {} marked as Trivial in Rust is not trivially move constructible and trivially destructible in C++\");",
         id,
     );
 }
diff --git a/include/cxx.h b/include/cxx.h
index 45c3828..b048e27 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -267,6 +267,27 @@ using isize = ssize_t;
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
+// IsRelocatable<T> is used in assertions that a C++ type passed by value
+// between Rust and C++ is soundly relocatable by Rust.
+//
+// There may be legitimate reasons to opt out of the check for support of types
+// that the programmer knows are soundly Rust-movable despite not being
+// recognized as such by the C++ type system due to a move constructor or
+// destructor. To opt out of the relocatability check, do either of the
+// following things in any header used by `include!` in the bridge.
+//
+//      --- if you define the type:
+//      struct MyType {
+//        ...
+//    +   using IsRelocatable = std::true_type;
+//      };
+//
+//      --- otherwise:
+//    + template <>
+//    + struct rust::IsRelocatable<MyType> : std::true_type {};
+template <typename T>
+struct IsRelocatable;
+
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;
@@ -281,6 +302,8 @@ template <typename Signature, bool Throws = false>
 using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
+template <typename T>
+using is_relocatable = IsRelocatable<T>;
 
 
 
@@ -552,5 +575,42 @@ template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
 #endif // CXXBRIDGE05_RUST_VEC
 
+#ifndef CXXBRIDGE05_RELOCATABLE
+#define CXXBRIDGE05_RELOCATABLE
+namespace detail {
+template <typename... Ts>
+struct make_void {
+  using type = void;
+};
+
+template <typename... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template <typename Void, template <typename...> class, typename...>
+struct detect : std::false_type {};
+template <template <typename...> class T, typename... A>
+struct detect<void_t<T<A...>>, T, A...> : std::true_type {};
+
+template <template <typename...> class T, typename... A>
+using is_detected = detect<void, T, A...>;
+
+template <typename T>
+using detect_IsRelocatable = typename T::IsRelocatable;
+
+template <typename T>
+struct get_IsRelocatable
+    : std::is_same<typename T::IsRelocatable, std::true_type> {};
+} // namespace detail
+
+template <typename T>
+struct IsRelocatable
+    : std::conditional<
+          detail::is_detected<detail::detect_IsRelocatable, T>::value,
+          detail::get_IsRelocatable<T>,
+          std::integral_constant<
+              bool, std::is_trivially_move_constructible<T>::value &&
+                        std::is_trivially_destructible<T>::value>>::type {};
+#endif // CXXBRIDGE05_RELOCATABLE
+
 } // namespace cxxbridge05
 } // namespace rust

From 063e97d32896a7e7c5076fa6035621d294f38ac8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 02 2020 18:38:43 +0000
Subject: [PATCH 1230/2232] Merge pull request #406 from dtolnay/relocatable


Expose way to bypass trivial destr/move on extern types passed by value
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index ab2b465..7a4ddcd 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -23,6 +23,7 @@ pub struct Builtins<'a> {
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
     pub exception: bool,
+    pub relocatable: bool,
     pub content: Content<'a>,
 }
 
@@ -73,6 +74,10 @@ pub(super) fn write(out: &mut OutFile) {
         include.basetsd = true;
     }
 
+    if builtin.relocatable {
+        include.type_traits = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge05"));
     writeln!(out, "// #include \"rust/cxx.h\"");
@@ -100,6 +105,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE05_RELOCATABLE");
 
     if builtin.manually_drop {
         out.next_section();
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2c3234c..c806e55 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -262,7 +262,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 }
 
 fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
-    // NOTE: The following two static assertions are just nice-to-have and not
+    // NOTE: The following static assertion is 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:
     //
@@ -273,31 +273,35 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     //
     // Since the user went on the record with their unsafe impl to unsafely
     // claim they KNOW that the type is trivial, it's fine for that to be on
-    // them if that were wrong.
+    // them if that were wrong. However, in practice correctly reasoning about
+    // the relocatability of C++ types is challenging, particularly if the type
+    // definition were to change over time, so for now we add this check.
+    //
+    // There may be legitimate reasons to opt out of this assertion for support
+    // of types that the programmer knows are soundly Rust-movable despite not
+    // being recognized as such by the C++ type system due to a move constructor
+    // or destructor. To opt out of the relocatability check, they need to do
+    // one of the following things in any header used by `include!` in their
+    // bridge.
+    //
+    //      --- if they define the type:
+    //      struct MyType {
+    //        ...
+    //    +   using IsRelocatable = std::true_type;
+    //      };
+    //
+    //      --- otherwise:
+    //    + template <>
+    //    + struct rust::IsRelocatable<MyType> : std::true_type {};
     //
-    // There may be a legitimate reason we'll want to remove these assertions
-    // for support of types that the programmer knows are Rust-movable despite
-    // not being recognized as such by the C++ type system due to a move
-    // constructor or destructor.
 
-    let id = &id.to_fully_qualified();
-    out.include.type_traits = true;
-    writeln!(out, "static_assert(");
-    writeln!(
-        out,
-        "    ::std::is_trivially_move_constructible<{}>::value,",
-        id,
-    );
-    writeln!(
-        out,
-        "    \"type {} marked as Trivial in Rust is not trivially move constructible in C++\");",
-        id,
-    );
+    let id = id.to_fully_qualified();
+    out.builtin.relocatable = true;
     writeln!(out, "static_assert(");
-    writeln!(out, "    ::std::is_trivially_destructible<{}>::value,", id);
+    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
     writeln!(
         out,
-        "    \"type {} marked as Trivial in Rust is not trivially destructible in C++\");",
+        "    \"type {} marked as Trivial in Rust is not trivially move constructible and trivially destructible in C++\");",
         id,
     );
 }
diff --git a/include/cxx.h b/include/cxx.h
index 45c3828..b048e27 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -267,6 +267,27 @@ using isize = ssize_t;
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
+// IsRelocatable<T> is used in assertions that a C++ type passed by value
+// between Rust and C++ is soundly relocatable by Rust.
+//
+// There may be legitimate reasons to opt out of the check for support of types
+// that the programmer knows are soundly Rust-movable despite not being
+// recognized as such by the C++ type system due to a move constructor or
+// destructor. To opt out of the relocatability check, do either of the
+// following things in any header used by `include!` in the bridge.
+//
+//      --- if you define the type:
+//      struct MyType {
+//        ...
+//    +   using IsRelocatable = std::true_type;
+//      };
+//
+//      --- otherwise:
+//    + template <>
+//    + struct rust::IsRelocatable<MyType> : std::true_type {};
+template <typename T>
+struct IsRelocatable;
+
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;
@@ -281,6 +302,8 @@ template <typename Signature, bool Throws = false>
 using fn = Fn<Signature, Throws>;
 template <typename Signature>
 using try_fn = TryFn<Signature>;
+template <typename T>
+using is_relocatable = IsRelocatable<T>;
 
 
 
@@ -552,5 +575,42 @@ template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
 #endif // CXXBRIDGE05_RUST_VEC
 
+#ifndef CXXBRIDGE05_RELOCATABLE
+#define CXXBRIDGE05_RELOCATABLE
+namespace detail {
+template <typename... Ts>
+struct make_void {
+  using type = void;
+};
+
+template <typename... Ts>
+using void_t = typename make_void<Ts...>::type;
+
+template <typename Void, template <typename...> class, typename...>
+struct detect : std::false_type {};
+template <template <typename...> class T, typename... A>
+struct detect<void_t<T<A...>>, T, A...> : std::true_type {};
+
+template <template <typename...> class T, typename... A>
+using is_detected = detect<void, T, A...>;
+
+template <typename T>
+using detect_IsRelocatable = typename T::IsRelocatable;
+
+template <typename T>
+struct get_IsRelocatable
+    : std::is_same<typename T::IsRelocatable, std::true_type> {};
+} // namespace detail
+
+template <typename T>
+struct IsRelocatable
+    : std::conditional<
+          detail::is_detected<detail::detect_IsRelocatable, T>::value,
+          detail::get_IsRelocatable<T>,
+          std::integral_constant<
+              bool, std::is_trivially_move_constructible<T>::value &&
+                        std::is_trivially_destructible<T>::value>>::type {};
+#endif // CXXBRIDGE05_RELOCATABLE
+
 } // namespace cxxbridge05
 } // namespace rust

From a1f02e51cf3a87e2ebeb45b122e8802b2987d0e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 01:10:54 +0000
Subject: [PATCH 1231/2232] More separation of handling throws and non-throws C++ function shims


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 029c54f..23b31fa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -348,71 +348,76 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         }
     };
     let expr = if efn.throws {
-        efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident.rust == RustString => {
-                Some(quote!(#call.map(|r| r.into_string())))
-            }
-            Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(#call.map(|r| r.into_vec_string())))
-                } else {
-                    Some(quote!(#call.map(|r| r.into_vec())))
+        efn.ret
+            .as_ref()
+            .and_then(|ret| match ret {
+                Type::Ident(ident) if ident.rust == RustString => {
+                    Some(quote!(#call.map(|r| r.into_string())))
                 }
-            }
-            Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_string()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
-                },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_vec_string()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_vec()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
+                Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
+                Type::RustVec(vec) => {
+                    if vec.inner == RustString {
+                        Some(quote!(#call.map(|r| r.into_vec_string())))
+                    } else {
+                        Some(quote!(#call.map(|r| r.into_vec())))
+                    }
+                }
+                Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
+                Type::Ref(ty) => match &ty.inner {
+                    Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
+                        None => Some(quote!(#call.map(|r| r.as_string()))),
+                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
+                    },
+                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                        None => Some(quote!(#call.map(|r| r.as_vec_string()))),
+                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
+                    },
+                    Type::RustVec(_) => match ty.mutability {
+                        None => Some(quote!(#call.map(|r| r.as_vec()))),
+                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
+                    },
+                    _ => None,
                 },
+                Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
+                Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
                 _ => None,
-            },
-            Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
-            Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
-            _ => None,
-        })
+            })
+            .unwrap_or(call)
     } else {
-        efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
-            Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(#call.into_vec_string()))
-                } else {
-                    Some(quote!(#call.into_vec()))
+        efn.ret
+            .as_ref()
+            .and_then(|ret| match ret {
+                Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
+                Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
+                Type::RustVec(vec) => {
+                    if vec.inner == RustString {
+                        Some(quote!(#call.into_vec_string()))
+                    } else {
+                        Some(quote!(#call.into_vec()))
+                    }
                 }
-            }
-            Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                    None => Some(quote!(#call.as_string())),
-                    Some(_) => Some(quote!(#call.as_mut_string())),
-                },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(#call.as_vec_string())),
-                    Some(_) => Some(quote!(#call.as_mut_vec_string())),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(#call.as_vec())),
-                    Some(_) => Some(quote!(#call.as_mut_vec())),
+                Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
+                Type::Ref(ty) => match &ty.inner {
+                    Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
+                        None => Some(quote!(#call.as_string())),
+                        Some(_) => Some(quote!(#call.as_mut_string())),
+                    },
+                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                        None => Some(quote!(#call.as_vec_string())),
+                        Some(_) => Some(quote!(#call.as_mut_vec_string())),
+                    },
+                    Type::RustVec(_) => match ty.mutability {
+                        None => Some(quote!(#call.as_vec())),
+                        Some(_) => Some(quote!(#call.as_mut_vec())),
+                    },
+                    _ => None,
                 },
+                Type::Str(_) => Some(quote!(#call.as_str())),
+                Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
                 _ => None,
-            },
-            Type::Str(_) => Some(quote!(#call.as_str())),
-            Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
-            _ => None,
-        })
-    }
-    .unwrap_or(call);
+            })
+            .unwrap_or(call)
+    };
     let mut dispatch = quote!(#setup #expr);
     let unsafety = &efn.sig.unsafety;
     if unsafety.is_none() {

From 2debdb2751418fa92428aa787d5d08c48b066654 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 01:18:30 +0000
Subject: [PATCH 1232/2232] Remove needlessly Ok-wrapping indirect throws return values


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 23b31fa..0b90a4f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -331,7 +331,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             setup.extend(quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
             });
-            quote!(::std::result::Result::Ok(__return.assume_init()))
+            quote!(__return.assume_init())
         } else {
             setup.extend(quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr());
@@ -347,44 +347,12 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             #local_name(#(#vars),*)
         }
     };
-    let expr = if efn.throws {
-        efn.ret
-            .as_ref()
-            .and_then(|ret| match ret {
-                Type::Ident(ident) if ident.rust == RustString => {
-                    Some(quote!(#call.map(|r| r.into_string())))
-                }
-                Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
-                Type::RustVec(vec) => {
-                    if vec.inner == RustString {
-                        Some(quote!(#call.map(|r| r.into_vec_string())))
-                    } else {
-                        Some(quote!(#call.map(|r| r.into_vec())))
-                    }
-                }
-                Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
-                Type::Ref(ty) => match &ty.inner {
-                    Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                        None => Some(quote!(#call.map(|r| r.as_string()))),
-                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
-                    },
-                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                        None => Some(quote!(#call.map(|r| r.as_vec_string()))),
-                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
-                    },
-                    Type::RustVec(_) => match ty.mutability {
-                        None => Some(quote!(#call.map(|r| r.as_vec()))),
-                        Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
-                    },
-                    _ => None,
-                },
-                Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
-                Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
-                _ => None,
-            })
-            .unwrap_or(call)
+    let mut expr;
+    if efn.throws && efn.sig.ret.is_none() {
+        expr = call;
     } else {
-        efn.ret
+        expr = efn
+            .ret
             .as_ref()
             .and_then(|ret| match ret {
                 Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
@@ -416,7 +384,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
                 _ => None,
             })
-            .unwrap_or(call)
+            .unwrap_or(call);
+        if efn.throws {
+            expr = quote!(::std::result::Result::Ok(#expr));
+        }
     };
     let mut dispatch = quote!(#setup #expr);
     let unsafety = &efn.sig.unsafety;

From 0d5248543ebac4ad769ca274cca6c83fc94c2b63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 01:24:13 +0000
Subject: [PATCH 1233/2232] Simplify extern C++ function return lowering


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 0b90a4f..443f4c7 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -327,17 +327,16 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
         });
-        if efn.throws {
-            setup.extend(quote! {
+        setup.extend(if efn.throws {
+            quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
-            });
-            quote!(__return.assume_init())
+            }
         } else {
-            setup.extend(quote! {
+            quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr());
-            });
-            quote!(__return.assume_init())
-        }
+            }
+        });
+        quote!(__return.assume_init())
     } else if efn.throws {
         quote! {
             #local_name(#(#vars),*).exception()
@@ -351,40 +350,39 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     if efn.throws && efn.sig.ret.is_none() {
         expr = call;
     } else {
-        expr = efn
-            .ret
-            .as_ref()
-            .and_then(|ret| match ret {
-                Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
-                Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
+        expr = match &efn.ret {
+            None => call,
+            Some(ret) => match ret {
+                Type::Ident(ident) if ident.rust == RustString => quote!(#call.into_string()),
+                Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#call)),
                 Type::RustVec(vec) => {
                     if vec.inner == RustString {
-                        Some(quote!(#call.into_vec_string()))
+                        quote!(#call.into_vec_string())
                     } else {
-                        Some(quote!(#call.into_vec()))
+                        quote!(#call.into_vec())
                     }
                 }
-                Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
+                Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#call)),
                 Type::Ref(ty) => match &ty.inner {
                     Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                        None => Some(quote!(#call.as_string())),
-                        Some(_) => Some(quote!(#call.as_mut_string())),
+                        None => quote!(#call.as_string()),
+                        Some(_) => quote!(#call.as_mut_string()),
                     },
                     Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                        None => Some(quote!(#call.as_vec_string())),
-                        Some(_) => Some(quote!(#call.as_mut_vec_string())),
+                        None => quote!(#call.as_vec_string()),
+                        Some(_) => quote!(#call.as_mut_vec_string()),
                     },
                     Type::RustVec(_) => match ty.mutability {
-                        None => Some(quote!(#call.as_vec())),
-                        Some(_) => Some(quote!(#call.as_mut_vec())),
+                        None => quote!(#call.as_vec()),
+                        Some(_) => quote!(#call.as_mut_vec()),
                     },
-                    _ => None,
+                    _ => call,
                 },
-                Type::Str(_) => Some(quote!(#call.as_str())),
-                Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
-                _ => None,
-            })
-            .unwrap_or(call);
+                Type::Str(_) => quote!(#call.as_str()),
+                Type::SliceRefU8(_) => quote!(#call.as_slice()),
+                _ => call,
+            },
+        };
         if efn.throws {
             expr = quote!(::std::result::Result::Ok(#expr));
         }

From babf65ca0011c7f19877b1fda22722bcb2e6176a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 01:41:54 +0000
Subject: [PATCH 1234/2232] Merge pull request #407 from dtolnay/throws


Simplify lowering of fallible extern C++ return values
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 029c54f..443f4c7 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -327,17 +327,16 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
         });
-        if efn.throws {
-            setup.extend(quote! {
+        setup.extend(if efn.throws {
+            quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr()).exception()?;
-            });
-            quote!(::std::result::Result::Ok(__return.assume_init()))
+            }
         } else {
-            setup.extend(quote! {
+            quote! {
                 #local_name(#(#vars,)* __return.as_mut_ptr());
-            });
-            quote!(__return.assume_init())
-        }
+            }
+        });
+        quote!(__return.assume_init())
     } else if efn.throws {
         quote! {
             #local_name(#(#vars),*).exception()
@@ -347,72 +346,47 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             #local_name(#(#vars),*)
         }
     };
-    let expr = if efn.throws {
-        efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident.rust == RustString => {
-                Some(quote!(#call.map(|r| r.into_string())))
-            }
-            Type::RustBox(_) => Some(quote!(#call.map(|r| ::std::boxed::Box::from_raw(r)))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(#call.map(|r| r.into_vec_string())))
-                } else {
-                    Some(quote!(#call.map(|r| r.into_vec())))
-                }
-            }
-            Type::UniquePtr(_) => Some(quote!(#call.map(|r| ::cxx::UniquePtr::from_raw(r)))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_string()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_string()))),
-                },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_vec_string()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec_string()))),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(#call.map(|r| r.as_vec()))),
-                    Some(_) => Some(quote!(#call.map(|r| r.as_mut_vec()))),
-                },
-                _ => None,
-            },
-            Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))),
-            Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))),
-            _ => None,
-        })
+    let mut expr;
+    if efn.throws && efn.sig.ret.is_none() {
+        expr = call;
     } else {
-        efn.ret.as_ref().and_then(|ret| match ret {
-            Type::Ident(ident) if ident.rust == RustString => Some(quote!(#call.into_string())),
-            Type::RustBox(_) => Some(quote!(::std::boxed::Box::from_raw(#call))),
-            Type::RustVec(vec) => {
-                if vec.inner == RustString {
-                    Some(quote!(#call.into_vec_string()))
-                } else {
-                    Some(quote!(#call.into_vec()))
+        expr = match &efn.ret {
+            None => call,
+            Some(ret) => match ret {
+                Type::Ident(ident) if ident.rust == RustString => quote!(#call.into_string()),
+                Type::RustBox(_) => quote!(::std::boxed::Box::from_raw(#call)),
+                Type::RustVec(vec) => {
+                    if vec.inner == RustString {
+                        quote!(#call.into_vec_string())
+                    } else {
+                        quote!(#call.into_vec())
+                    }
                 }
-            }
-            Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::from_raw(#call))),
-            Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                    None => Some(quote!(#call.as_string())),
-                    Some(_) => Some(quote!(#call.as_mut_string())),
+                Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#call)),
+                Type::Ref(ty) => match &ty.inner {
+                    Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
+                        None => quote!(#call.as_string()),
+                        Some(_) => quote!(#call.as_mut_string()),
+                    },
+                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
+                        None => quote!(#call.as_vec_string()),
+                        Some(_) => quote!(#call.as_mut_vec_string()),
+                    },
+                    Type::RustVec(_) => match ty.mutability {
+                        None => quote!(#call.as_vec()),
+                        Some(_) => quote!(#call.as_mut_vec()),
+                    },
+                    _ => call,
                 },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => Some(quote!(#call.as_vec_string())),
-                    Some(_) => Some(quote!(#call.as_mut_vec_string())),
-                },
-                Type::RustVec(_) => match ty.mutability {
-                    None => Some(quote!(#call.as_vec())),
-                    Some(_) => Some(quote!(#call.as_mut_vec())),
-                },
-                _ => None,
+                Type::Str(_) => quote!(#call.as_str()),
+                Type::SliceRefU8(_) => quote!(#call.as_slice()),
+                _ => call,
             },
-            Type::Str(_) => Some(quote!(#call.as_str())),
-            Type::SliceRefU8(_) => Some(quote!(#call.as_slice())),
-            _ => None,
-        })
-    }
-    .unwrap_or(call);
+        };
+        if efn.throws {
+            expr = quote!(::std::result::Result::Ok(#expr));
+        }
+    };
     let mut dispatch = quote!(#setup #expr);
     let unsafety = &efn.sig.unsafety;
     if unsafety.is_none() {

From 5e88a0d840f953a98c361cc7f25be53315a87a55 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 01:42:41 +0000
Subject: [PATCH 1235/2232] Make Types available in expand_extern_type


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 443f4c7..c86dc91 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -208,7 +208,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty);
+        let ty = expand_extern_type(&arg.ty, types);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
         } else if let Type::RustVec(_) = arg.ty {
@@ -229,7 +229,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     };
     let mut outparam = None;
     if indirect_return(efn, types) {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap());
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(efn, types);
@@ -323,7 +323,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .collect::<TokenStream>();
     let local_name = format_ident!("__{}", efn.name.rust);
     let call = if indirect_return {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap());
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
         });
@@ -508,7 +508,7 @@ fn expand_rust_function_shim_impl(
     });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty);
+        let ty = expand_extern_type(&arg.ty, types);
         if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
@@ -609,7 +609,7 @@ fn expand_rust_function_shim_impl(
     let mut outparam = None;
     let indirect_return = indirect_return(sig, types);
     if indirect_return {
-        let ret = expand_extern_type(sig.ret.as_ref().unwrap());
+        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types);
         outparam = Some(quote!(__return: *mut #ret,));
     }
     if sig.throws {
@@ -939,15 +939,15 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn expand_extern_type(ty: &Type) -> TokenStream {
+fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
     match ty {
         Type::Ident(ident) if ident.rust == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            let inner = expand_extern_type(&ty.inner);
+            let inner = expand_extern_type(&ty.inner, types);
             quote!(*mut #inner)
         }
         Type::RustVec(ty) => {
-            let elem = expand_extern_type(&ty.inner);
+            let elem = expand_extern_type(&ty.inner, types);
             quote!(::cxx::private::RustVec<#elem>)
         }
         Type::Ref(ty) => {
@@ -957,7 +957,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream {
                     quote!(&#mutability ::cxx::private::RustString)
                 }
                 Type::RustVec(ty) => {
-                    let inner = expand_extern_type(&ty.inner);
+                    let inner = expand_extern_type(&ty.inner, types);
                     quote!(&#mutability ::cxx::private::RustVec<#inner>)
                 }
                 _ => quote!(#ty),
@@ -974,6 +974,6 @@ fn expand_extern_return_type(ret: &Option<Type>, types: &Types) -> TokenStream {
         Some(ret) if !types.needs_indirect_abi(ret) => ret,
         _ => return TokenStream::new(),
     };
-    let ty = expand_extern_type(ret);
+    let ty = expand_extern_type(ret, types);
     quote!(-> #ty)
 }

From 701c6884762bdf01fce1cd97c8e7ff591e9990fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:20:08 +0000
Subject: [PATCH 1236/2232] Add repro of shared string by reference error


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index f40ec6c..af8a9f5 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -69,6 +69,10 @@ pub mod ffi {
         z: usize,
     }
 
+    struct SharedString {
+        msg: String,
+    }
+
     enum Enum {
         AVal,
         BVal = 2020,
@@ -169,6 +173,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
+        fn c_take_ref_shared_string(s: &SharedString) -> &SharedString;
         fn c_take_callback(callback: fn(String) -> usize);
         fn c_take_enum(e: Enum);
         fn c_take_ns_enum(e: AEnum);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a03ec2b..747788f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -385,6 +385,13 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
+const SharedString &c_take_ref_shared_string(const SharedString &s) {
+  if (std::string(s.msg) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+  return s;
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index e551048..7fc5633 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -36,6 +36,7 @@ namespace tests {
 
 struct R;
 struct Shared;
+struct SharedString;
 enum class Enum : uint16_t;
 
 class C {
@@ -134,6 +135,7 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
+const SharedString &c_take_ref_shared_string(const SharedString &s);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
diff --git a/tests/test.rs b/tests/test.rs
index a90b8fc..2c6f062 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -137,6 +137,9 @@ fn test_c_take() {
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    check!(ffi::c_take_ref_shared_string(&ffi::SharedString {
+        msg: "2020".to_owned()
+    }));
     let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }];
     check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec));
     let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }];

From fa1f15b2d700af64980747a0824725965056123b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:20:08 +0000
Subject: [PATCH 1237/2232] Add logic for predicting improper_ctypes lint


---

diff --git a/syntax/types.rs b/syntax/types.rs
index 67b041b..007d976 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -227,6 +227,45 @@ impl<'a> Types<'a> {
         false
     }
 
+    // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
+    // they may be otherwise unproblematic to mention in an extern signature.
+    // For example in a signature like `extern "C" fn(*const String)`, rustc
+    // refuses to believe that C could know how to supply us with a pointer to a
+    // Rust String, even though C could easily have obtained that pointer
+    // legitimately from a Rust call.
+    pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool {
+        match ty {
+            Type::Ident(ident) => {
+                let ident = &ident.rust;
+                if let Some(atom) = Atom::from(ident) {
+                    atom == RustString
+                } else if self.rust.contains(ident) {
+                    true
+                } else if self.cxx.contains(ident) || self.enums.contains_key(ident) {
+                    false
+                } else if let Some(strct) = self.structs.get(ident) {
+                    for var in &strct.fields {
+                        if self.is_considered_improper_ctype(&var.ty) {
+                            return true;
+                        }
+                    }
+                    false
+                } else {
+                    false
+                }
+            }
+            Type::RustBox(_)
+            | Type::RustVec(_)
+            | Type::Str(_)
+            | Type::Fn(_)
+            | Type::Void(_)
+            | Type::Slice(_)
+            | Type::SliceRefU8(_) => true,
+            Type::UniquePtr(_) | Type::CxxVector(_) => false,
+            Type::Ref(ty) => self.is_considered_improper_ctype(&ty.inner),
+        }
+    }
+
     pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
         self.resolutions
             .get(&ident.rust)

From 7953a11d0c9466103344c15a56569a0aa7f45c9d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:20:08 +0000
Subject: [PATCH 1238/2232] Implement improper ctypes check without infinite loop on cyclic structs


---

diff --git a/syntax/improper.rs b/syntax/improper.rs
new file mode 100644
index 0000000..6fd3162
--- /dev/null
+++ b/syntax/improper.rs
@@ -0,0 +1,36 @@
+use self::ImproperCtype::*;
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{Type, Types};
+use proc_macro2::Ident;
+
+pub enum ImproperCtype<'a> {
+    Definite(bool),
+    Depends(&'a Ident),
+}
+
+impl<'a> Types<'a> {
+    // yes, no, maybe
+    pub fn determine_improper_ctype(&self, ty: &Type) -> ImproperCtype<'a> {
+        match ty {
+            Type::Ident(ident) => {
+                let ident = &ident.rust;
+                if let Some(atom) = Atom::from(ident) {
+                    Definite(atom == RustString)
+                } else if let Some(strct) = self.structs.get(ident) {
+                    Depends(&strct.name.rust) // iterate to fixed-point
+                } else {
+                    Definite(self.rust.contains(ident))
+                }
+            }
+            Type::RustBox(_)
+            | Type::RustVec(_)
+            | Type::Str(_)
+            | Type::Fn(_)
+            | Type::Void(_)
+            | Type::Slice(_)
+            | Type::SliceRefU8(_) => Definite(true),
+            Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index ac6350a..b742e37 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -10,6 +10,7 @@ pub mod error;
 pub mod file;
 pub mod ident;
 mod impls;
+mod improper;
 pub mod mangle;
 mod names;
 pub mod namespace;
diff --git a/syntax/types.rs b/syntax/types.rs
index 007d976..5d6d582 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,4 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
@@ -19,6 +20,7 @@ pub struct Types<'a> {
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
+    pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -32,6 +34,7 @@ impl<'a> Types<'a> {
         let mut untrusted = Map::new();
         let mut explicit_impls = Set::new();
         let mut resolutions = Map::new();
+        let struct_improper_ctypes = UnorderedSet::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -190,7 +193,7 @@ impl<'a> Types<'a> {
             }
         }
 
-        Types {
+        let mut types = Types {
             all,
             structs,
             enums,
@@ -201,7 +204,34 @@ impl<'a> Types<'a> {
             required_trivial,
             explicit_impls,
             resolutions,
+            struct_improper_ctypes,
+        };
+
+        let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
+        let mut new_information = true;
+        while new_information {
+            new_information = false;
+            unresolved_structs.retain(|ident| {
+                let mut retain = false;
+                for var in &types.structs[ident].fields {
+                    if match types.determine_improper_ctype(&var.ty) {
+                        ImproperCtype::Depends(inner) => {
+                            retain = true;
+                            types.struct_improper_ctypes.contains(inner)
+                        }
+                        ImproperCtype::Definite(improper) => improper,
+                    } {
+                        types.struct_improper_ctypes.insert(ident);
+                        new_information = true;
+                        return false;
+                    }
+                }
+                // If all fields definite false, remove from unresolved_structs.
+                retain
+            });
         }
+
+        types
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
@@ -234,35 +264,9 @@ impl<'a> Types<'a> {
     // Rust String, even though C could easily have obtained that pointer
     // legitimately from a Rust call.
     pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool {
-        match ty {
-            Type::Ident(ident) => {
-                let ident = &ident.rust;
-                if let Some(atom) = Atom::from(ident) {
-                    atom == RustString
-                } else if self.rust.contains(ident) {
-                    true
-                } else if self.cxx.contains(ident) || self.enums.contains_key(ident) {
-                    false
-                } else if let Some(strct) = self.structs.get(ident) {
-                    for var in &strct.fields {
-                        if self.is_considered_improper_ctype(&var.ty) {
-                            return true;
-                        }
-                    }
-                    false
-                } else {
-                    false
-                }
-            }
-            Type::RustBox(_)
-            | Type::RustVec(_)
-            | Type::Str(_)
-            | Type::Fn(_)
-            | Type::Void(_)
-            | Type::Slice(_)
-            | Type::SliceRefU8(_) => true,
-            Type::UniquePtr(_) | Type::CxxVector(_) => false,
-            Type::Ref(ty) => self.is_considered_improper_ctype(&ty.inner),
+        match self.determine_improper_ctype(ty) {
+            ImproperCtype::Definite(improper) => improper,
+            ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
         }
     }
 

From 4cb9767a1de0fc5c9f98a6d387c21b9c5ff64440 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:20:08 +0000
Subject: [PATCH 1239/2232] Pass improper ctype references by void pointer


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c86dc91..c0e71e1 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -287,6 +287,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     None => quote!(::cxx::private::RustVec::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
                 },
+                inner if types.is_considered_improper_ctype(inner) => match ty.mutability {
+                    None => quote!(#var as *const #inner as *const ::std::ffi::c_void),
+                    Some(_) => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
+                },
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -376,6 +380,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                         None => quote!(#call.as_vec()),
                         Some(_) => quote!(#call.as_mut_vec()),
                     },
+                    inner if types.is_considered_improper_ctype(inner) => {
+                        let mutability = ty.mutability;
+                        quote!(&#mutability *#call.cast())
+                    }
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
@@ -545,6 +553,10 @@ fn expand_rust_function_shim_impl(
                     None => quote!(#ident.as_vec()),
                     Some(_) => quote!(#ident.as_mut_vec()),
                 },
+                inner if types.is_considered_improper_ctype(inner) => {
+                    let mutability = ty.mutability;
+                    quote!(&#mutability *#ident.cast())
+                }
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -593,6 +605,10 @@ fn expand_rust_function_shim_impl(
                 None => Some(quote!(::cxx::private::RustVec::from_ref)),
                 Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
             },
+            inner if types.is_considered_improper_ctype(inner) => match ty.mutability {
+                None => Some(quote!((|v| v as *const #inner as *const ::std::ffi::c_void))),
+                Some(_) => Some(quote!((|v| v as *mut #inner as *mut ::std::ffi::c_void))),
+            },
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
@@ -960,6 +976,10 @@ fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
                     let inner = expand_extern_type(&ty.inner, types);
                     quote!(&#mutability ::cxx::private::RustVec<#inner>)
                 }
+                inner if types.is_considered_improper_ctype(inner) => match mutability {
+                    None => quote!(*const ::std::ffi::c_void),
+                    Some(_) => quote!(*#mutability ::std::ffi::c_void),
+                },
                 _ => quote!(#ty),
             }
         }

From 2f09042ef01a4e0c1ab18dc4f6066765560c1564 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:28:13 +0000
Subject: [PATCH 1240/2232] Restrict improper ctype special case to only contexts that require it


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c0e71e1..b5d3067 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -208,7 +208,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty, types);
+        let ty = expand_extern_type(&arg.ty, types, true);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
         } else if let Type::RustVec(_) = arg.ty {
@@ -225,11 +225,11 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let ret = if efn.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&efn.ret, types)
+        expand_extern_return_type(&efn.ret, types, true)
     };
     let mut outparam = None;
     if indirect_return(efn, types) {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(efn, types);
@@ -327,7 +327,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .collect::<TokenStream>();
     let local_name = format_ident!("__{}", efn.name.rust);
     let call = if indirect_return {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
         });
@@ -516,7 +516,7 @@ fn expand_rust_function_shim_impl(
     });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty, types);
+        let ty = expand_extern_type(&arg.ty, types, false);
         if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
@@ -553,10 +553,6 @@ fn expand_rust_function_shim_impl(
                     None => quote!(#ident.as_vec()),
                     Some(_) => quote!(#ident.as_mut_vec()),
                 },
-                inner if types.is_considered_improper_ctype(inner) => {
-                    let mutability = ty.mutability;
-                    quote!(&#mutability *#ident.cast())
-                }
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
@@ -605,10 +601,6 @@ fn expand_rust_function_shim_impl(
                 None => Some(quote!(::cxx::private::RustVec::from_ref)),
                 Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
             },
-            inner if types.is_considered_improper_ctype(inner) => match ty.mutability {
-                None => Some(quote!((|v| v as *const #inner as *const ::std::ffi::c_void))),
-                Some(_) => Some(quote!((|v| v as *mut #inner as *mut ::std::ffi::c_void))),
-            },
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
@@ -625,7 +617,7 @@ fn expand_rust_function_shim_impl(
     let mut outparam = None;
     let indirect_return = indirect_return(sig, types);
     if indirect_return {
-        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
         outparam = Some(quote!(__return: *mut #ret,));
     }
     if sig.throws {
@@ -643,7 +635,7 @@ fn expand_rust_function_shim_impl(
     let ret = if sig.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&sig.ret, types)
+        expand_extern_return_type(&sig.ret, types, false)
     };
 
     let pointer = match invoke {
@@ -955,15 +947,15 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
+fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
     match ty {
         Type::Ident(ident) if ident.rust == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            let inner = expand_extern_type(&ty.inner, types);
+            let inner = expand_extern_type(&ty.inner, types, proper);
             quote!(*mut #inner)
         }
         Type::RustVec(ty) => {
-            let elem = expand_extern_type(&ty.inner, types);
+            let elem = expand_extern_type(&ty.inner, types, proper);
             quote!(::cxx::private::RustVec<#elem>)
         }
         Type::Ref(ty) => {
@@ -973,10 +965,10 @@ fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
                     quote!(&#mutability ::cxx::private::RustString)
                 }
                 Type::RustVec(ty) => {
-                    let inner = expand_extern_type(&ty.inner, types);
+                    let inner = expand_extern_type(&ty.inner, types, proper);
                     quote!(&#mutability ::cxx::private::RustVec<#inner>)
                 }
-                inner if types.is_considered_improper_ctype(inner) => match mutability {
+                inner if proper && types.is_considered_improper_ctype(inner) => match mutability {
                     None => quote!(*const ::std::ffi::c_void),
                     Some(_) => quote!(*#mutability ::std::ffi::c_void),
                 },
@@ -989,11 +981,11 @@ fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_extern_return_type(ret: &Option<Type>, types: &Types) -> TokenStream {
+fn expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream {
     let ret = match ret {
         Some(ret) if !types.needs_indirect_abi(ret) => ret,
         _ => return TokenStream::new(),
     };
-    let ty = expand_extern_type(ret, types);
+    let ty = expand_extern_type(ret, types, proper);
     quote!(-> #ty)
 }

From 2faf8726a6ee3b3bd413f6fd960dcb41506a9966 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:40:05 +0000
Subject: [PATCH 1241/2232] Merge pull request #408 from dtolnay/ctype


Pass improper ctype references by void pointer
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c86dc91..b5d3067 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -208,7 +208,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     });
     let args = efn.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty, types);
+        let ty = expand_extern_type(&arg.ty, types, true);
         if arg.ty == RustString {
             quote!(#ident: *const #ty)
         } else if let Type::RustVec(_) = arg.ty {
@@ -225,11 +225,11 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let ret = if efn.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&efn.ret, types)
+        expand_extern_return_type(&efn.ret, types, true)
     };
     let mut outparam = None;
     if indirect_return(efn, types) {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
         outparam = Some(quote!(__return: *mut #ret));
     }
     let link_name = mangle::extern_fn(efn, types);
@@ -287,6 +287,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     None => quote!(::cxx::private::RustVec::from_ref(#var)),
                     Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
                 },
+                inner if types.is_considered_improper_ctype(inner) => match ty.mutability {
+                    None => quote!(#var as *const #inner as *const ::std::ffi::c_void),
+                    Some(_) => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
+                },
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
@@ -323,7 +327,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .collect::<TokenStream>();
     let local_name = format_ident!("__{}", efn.name.rust);
     let call = if indirect_return {
-        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(efn.ret.as_ref().unwrap(), types, true);
         setup.extend(quote! {
             let mut __return = ::std::mem::MaybeUninit::<#ret>::uninit();
         });
@@ -376,6 +380,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                         None => quote!(#call.as_vec()),
                         Some(_) => quote!(#call.as_mut_vec()),
                     },
+                    inner if types.is_considered_improper_ctype(inner) => {
+                        let mutability = ty.mutability;
+                        quote!(&#mutability *#call.cast())
+                    }
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
@@ -508,7 +516,7 @@ fn expand_rust_function_shim_impl(
     });
     let args = sig.args.iter().map(|arg| {
         let ident = &arg.ident;
-        let ty = expand_extern_type(&arg.ty, types);
+        let ty = expand_extern_type(&arg.ty, types, false);
         if types.needs_indirect_abi(&arg.ty) {
             quote!(#ident: *mut #ty)
         } else {
@@ -609,7 +617,7 @@ fn expand_rust_function_shim_impl(
     let mut outparam = None;
     let indirect_return = indirect_return(sig, types);
     if indirect_return {
-        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types);
+        let ret = expand_extern_type(sig.ret.as_ref().unwrap(), types, false);
         outparam = Some(quote!(__return: *mut #ret,));
     }
     if sig.throws {
@@ -627,7 +635,7 @@ fn expand_rust_function_shim_impl(
     let ret = if sig.throws {
         quote!(-> ::cxx::private::Result)
     } else {
-        expand_extern_return_type(&sig.ret, types)
+        expand_extern_return_type(&sig.ret, types, false)
     };
 
     let pointer = match invoke {
@@ -939,15 +947,15 @@ fn indirect_return(sig: &Signature, types: &Types) -> bool {
         .map_or(false, |ret| sig.throws || types.needs_indirect_abi(ret))
 }
 
-fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
+fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
     match ty {
         Type::Ident(ident) if ident.rust == RustString => quote!(::cxx::private::RustString),
         Type::RustBox(ty) | Type::UniquePtr(ty) => {
-            let inner = expand_extern_type(&ty.inner, types);
+            let inner = expand_extern_type(&ty.inner, types, proper);
             quote!(*mut #inner)
         }
         Type::RustVec(ty) => {
-            let elem = expand_extern_type(&ty.inner, types);
+            let elem = expand_extern_type(&ty.inner, types, proper);
             quote!(::cxx::private::RustVec<#elem>)
         }
         Type::Ref(ty) => {
@@ -957,9 +965,13 @@ fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
                     quote!(&#mutability ::cxx::private::RustString)
                 }
                 Type::RustVec(ty) => {
-                    let inner = expand_extern_type(&ty.inner, types);
+                    let inner = expand_extern_type(&ty.inner, types, proper);
                     quote!(&#mutability ::cxx::private::RustVec<#inner>)
                 }
+                inner if proper && types.is_considered_improper_ctype(inner) => match mutability {
+                    None => quote!(*const ::std::ffi::c_void),
+                    Some(_) => quote!(*#mutability ::std::ffi::c_void),
+                },
                 _ => quote!(#ty),
             }
         }
@@ -969,11 +981,11 @@ fn expand_extern_type(ty: &Type, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_extern_return_type(ret: &Option<Type>, types: &Types) -> TokenStream {
+fn expand_extern_return_type(ret: &Option<Type>, types: &Types, proper: bool) -> TokenStream {
     let ret = match ret {
         Some(ret) if !types.needs_indirect_abi(ret) => ret,
         _ => return TokenStream::new(),
     };
-    let ty = expand_extern_type(ret, types);
+    let ty = expand_extern_type(ret, types, proper);
     quote!(-> #ty)
 }
diff --git a/syntax/improper.rs b/syntax/improper.rs
new file mode 100644
index 0000000..6fd3162
--- /dev/null
+++ b/syntax/improper.rs
@@ -0,0 +1,36 @@
+use self::ImproperCtype::*;
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{Type, Types};
+use proc_macro2::Ident;
+
+pub enum ImproperCtype<'a> {
+    Definite(bool),
+    Depends(&'a Ident),
+}
+
+impl<'a> Types<'a> {
+    // yes, no, maybe
+    pub fn determine_improper_ctype(&self, ty: &Type) -> ImproperCtype<'a> {
+        match ty {
+            Type::Ident(ident) => {
+                let ident = &ident.rust;
+                if let Some(atom) = Atom::from(ident) {
+                    Definite(atom == RustString)
+                } else if let Some(strct) = self.structs.get(ident) {
+                    Depends(&strct.name.rust) // iterate to fixed-point
+                } else {
+                    Definite(self.rust.contains(ident))
+                }
+            }
+            Type::RustBox(_)
+            | Type::RustVec(_)
+            | Type::Str(_)
+            | Type::Fn(_)
+            | Type::Void(_)
+            | Type::Slice(_)
+            | Type::SliceRefU8(_) => Definite(true),
+            Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index ac6350a..b742e37 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -10,6 +10,7 @@ pub mod error;
 pub mod file;
 pub mod ident;
 mod impls;
+mod improper;
 pub mod mangle;
 mod names;
 pub mod namespace;
diff --git a/syntax/types.rs b/syntax/types.rs
index 67b041b..5d6d582 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,4 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
@@ -19,6 +20,7 @@ pub struct Types<'a> {
     pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
+    pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
 }
 
 impl<'a> Types<'a> {
@@ -32,6 +34,7 @@ impl<'a> Types<'a> {
         let mut untrusted = Map::new();
         let mut explicit_impls = Set::new();
         let mut resolutions = Map::new();
+        let struct_improper_ctypes = UnorderedSet::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -190,7 +193,7 @@ impl<'a> Types<'a> {
             }
         }
 
-        Types {
+        let mut types = Types {
             all,
             structs,
             enums,
@@ -201,7 +204,34 @@ impl<'a> Types<'a> {
             required_trivial,
             explicit_impls,
             resolutions,
+            struct_improper_ctypes,
+        };
+
+        let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
+        let mut new_information = true;
+        while new_information {
+            new_information = false;
+            unresolved_structs.retain(|ident| {
+                let mut retain = false;
+                for var in &types.structs[ident].fields {
+                    if match types.determine_improper_ctype(&var.ty) {
+                        ImproperCtype::Depends(inner) => {
+                            retain = true;
+                            types.struct_improper_ctypes.contains(inner)
+                        }
+                        ImproperCtype::Definite(improper) => improper,
+                    } {
+                        types.struct_improper_ctypes.insert(ident);
+                        new_information = true;
+                        return false;
+                    }
+                }
+                // If all fields definite false, remove from unresolved_structs.
+                retain
+            });
         }
+
+        types
     }
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
@@ -227,6 +257,19 @@ impl<'a> Types<'a> {
         false
     }
 
+    // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
+    // they may be otherwise unproblematic to mention in an extern signature.
+    // For example in a signature like `extern "C" fn(*const String)`, rustc
+    // refuses to believe that C could know how to supply us with a pointer to a
+    // Rust String, even though C could easily have obtained that pointer
+    // legitimately from a Rust call.
+    pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool {
+        match self.determine_improper_ctype(ty) {
+            ImproperCtype::Definite(improper) => improper,
+            ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
+        }
+    }
+
     pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
         self.resolutions
             .get(&ident.rust)
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index f40ec6c..af8a9f5 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -69,6 +69,10 @@ pub mod ffi {
         z: usize,
     }
 
+    struct SharedString {
+        msg: String,
+    }
+
     enum Enum {
         AVal,
         BVal = 2020,
@@ -169,6 +173,7 @@ pub mod ffi {
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
         fn c_take_ref_rust_vec_copy(v: &Vec<u8>);
+        fn c_take_ref_shared_string(s: &SharedString) -> &SharedString;
         fn c_take_callback(callback: fn(String) -> usize);
         fn c_take_enum(e: Enum);
         fn c_take_ns_enum(e: AEnum);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index a03ec2b..747788f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -385,6 +385,13 @@ void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v) {
   }
 }
 
+const SharedString &c_take_ref_shared_string(const SharedString &s) {
+  if (std::string(s.msg) == "2020") {
+    cxx_test_suite_set_correct();
+  }
+  return s;
+}
+
 void c_take_callback(rust::Fn<size_t(rust::String)> callback) {
   callback("2020");
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index e551048..7fc5633 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -36,6 +36,7 @@ namespace tests {
 
 struct R;
 struct Shared;
+struct SharedString;
 enum class Enum : uint16_t;
 
 class C {
@@ -134,6 +135,7 @@ void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_copy(const rust::Vec<uint8_t> &v);
+const SharedString &c_take_ref_shared_string(const SharedString &s);
 void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
diff --git a/tests/test.rs b/tests/test.rs
index a90b8fc..2c6f062 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -137,6 +137,9 @@ fn test_c_take() {
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
+    check!(ffi::c_take_ref_shared_string(&ffi::SharedString {
+        msg: "2020".to_owned()
+    }));
     let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }];
     check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec));
     let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }];

From 17184cf98d7c3b9f60d2fef717223da374f6eb2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 02:57:04 +0000
Subject: [PATCH 1242/2232] Fix filename in diagnostics when taking input from stdin


---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index b269286..2335d43 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -4,6 +4,7 @@ use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
 use codespan_reporting::term::{self, Config};
+use std::borrow::Cow;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
 use std::io::{self, Write};
@@ -134,8 +135,13 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err
         .map(char::len_utf8)
         .sum::<usize>();
 
+    let mut path = path.to_string_lossy();
+    if path == "-" {
+        path = Cow::Borrowed(if cfg!(unix) { "/dev/stdin" } else { "stdin" });
+    }
+
     let mut files = SimpleFiles::new();
-    let file = files.add(path.to_string_lossy(), source);
+    let file = files.add(path, source);
 
     let diagnostic = diagnose(file, start_offset..end_offset, error);
 

From dd9e987fd6f7627d8582c960ef13c11aa8888264 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 03 2020 03:09:52 +0000
Subject: [PATCH 1243/2232] Merge pull request #409 from dtolnay/stdin


Fix filename in diagnostics when taking input from stdin
---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index b269286..2335d43 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -4,6 +4,7 @@ use codespan_reporting::diagnostic::{Diagnostic, Label};
 use codespan_reporting::files::SimpleFiles;
 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor};
 use codespan_reporting::term::{self, Config};
+use std::borrow::Cow;
 use std::error::Error as StdError;
 use std::fmt::{self, Display};
 use std::io::{self, Write};
@@ -134,8 +135,13 @@ fn display_syn_error(stderr: &mut dyn WriteColor, path: &Path, source: &str, err
         .map(char::len_utf8)
         .sum::<usize>();
 
+    let mut path = path.to_string_lossy();
+    if path == "-" {
+        path = Cow::Borrowed(if cfg!(unix) { "/dev/stdin" } else { "stdin" });
+    }
+
     let mut files = SimpleFiles::new();
-    let file = files.add(path.to_string_lossy(), source);
+    let file = files.add(path, source);
 
     let diagnostic = diagnose(file, start_offset..end_offset, error);
 

From 392fbc6669013a5c3748a35564ac6acdf4f180a6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:14:17 +0000
Subject: [PATCH 1244/2232] Add test of unsorted nested structs


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index af8a9f5..9ea3450 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -277,6 +277,27 @@ pub mod ffi {
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
     }
+
+    struct Dag0 {
+        i: i32,
+    }
+
+    struct Dag1 {
+        dag2: Dag2,
+        vec: Vec<Dag3>,
+    }
+
+    struct Dag2 {
+        dag4: Dag4,
+    }
+
+    struct Dag3 {
+        dag1: Dag1,
+    }
+
+    struct Dag4 {
+        dag0: Dag0,
+    }
 }
 
 pub type R = usize;

From 9622b464108a5cb4ca9364cd61fb8d062814eca7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:16:02 +0000
Subject: [PATCH 1245/2232] Implement struct toposort


---

diff --git a/gen/src/toposort.rs b/gen/src/toposort.rs
index 97b10f9..62a1148 100644
--- a/gen/src/toposort.rs
+++ b/gen/src/toposort.rs
@@ -1,8 +1,44 @@
-use crate::syntax::{Api, Types};
-use std::iter::FromIterator;
+use crate::syntax::{Api, Struct, Type, Types};
+use std::collections::btree_map::{BTreeMap as Map, Entry};
 
-pub fn sort<'a>(apis: &'a [Api], types: &Types) -> Vec<&'a Api> {
-    // TODO https://github.com/dtolnay/cxx/issues/292
-    let _ = types;
-    Vec::from_iter(apis)
+enum Mark {
+    Visiting,
+    Visited,
+}
+
+pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+    let mut sorted = Vec::new();
+    let ref mut marks = Map::new();
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            visit(strct, &mut sorted, marks, types);
+        }
+    }
+    sorted
+}
+
+fn visit<'a>(
+    strct: &'a Struct,
+    sorted: &mut Vec<&'a Struct>,
+    marks: &mut Map<*const Struct, Mark>,
+    types: &Types<'a>,
+) {
+    match marks.entry(strct) {
+        Entry::Occupied(entry) => match entry.get() {
+            Mark::Visiting => panic!("not a DAG"), // FIXME
+            Mark::Visited => return,
+        },
+        Entry::Vacant(entry) => {
+            entry.insert(Mark::Visiting);
+        }
+    }
+    for field in &strct.fields {
+        if let Type::Ident(ident) = &field.ty {
+            if let Some(inner) = types.structs.get(&ident.rust) {
+                visit(inner, sorted, marks, types);
+            }
+        }
+    }
+    marks.insert(strct, Mark::Visited);
+    sorted.push(strct);
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c806e55..414ea46 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -76,14 +76,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for api in toposort::sort(apis, out.types) {
+    for api in apis {
         match api {
-            Api::Struct(strct) => {
-                out.next_section();
-                if !out.types.cxx.contains(&strct.name.rust) {
-                    write_struct(out, strct);
-                }
-            }
             Api::Enum(enm) => {
                 out.next_section();
                 if out.types.cxx.contains(&enm.name.rust) {
@@ -102,6 +96,13 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    for strct in toposort::sort(apis, out.types) {
+        out.next_section();
+        if !out.types.cxx.contains(&strct.name.rust) {
+            write_struct(out, strct);
+        }
+    }
+
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {

From b0901e2cec4f6ee68cbd67808ba21e41145e1d6f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:22:34 +0000
Subject: [PATCH 1246/2232] Merge pull request #411 from dtolnay/sort


Implement struct toposort
---

diff --git a/gen/src/toposort.rs b/gen/src/toposort.rs
index 97b10f9..62a1148 100644
--- a/gen/src/toposort.rs
+++ b/gen/src/toposort.rs
@@ -1,8 +1,44 @@
-use crate::syntax::{Api, Types};
-use std::iter::FromIterator;
+use crate::syntax::{Api, Struct, Type, Types};
+use std::collections::btree_map::{BTreeMap as Map, Entry};
 
-pub fn sort<'a>(apis: &'a [Api], types: &Types) -> Vec<&'a Api> {
-    // TODO https://github.com/dtolnay/cxx/issues/292
-    let _ = types;
-    Vec::from_iter(apis)
+enum Mark {
+    Visiting,
+    Visited,
+}
+
+pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+    let mut sorted = Vec::new();
+    let ref mut marks = Map::new();
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            visit(strct, &mut sorted, marks, types);
+        }
+    }
+    sorted
+}
+
+fn visit<'a>(
+    strct: &'a Struct,
+    sorted: &mut Vec<&'a Struct>,
+    marks: &mut Map<*const Struct, Mark>,
+    types: &Types<'a>,
+) {
+    match marks.entry(strct) {
+        Entry::Occupied(entry) => match entry.get() {
+            Mark::Visiting => panic!("not a DAG"), // FIXME
+            Mark::Visited => return,
+        },
+        Entry::Vacant(entry) => {
+            entry.insert(Mark::Visiting);
+        }
+    }
+    for field in &strct.fields {
+        if let Type::Ident(ident) = &field.ty {
+            if let Some(inner) = types.structs.get(&ident.rust) {
+                visit(inner, sorted, marks, types);
+            }
+        }
+    }
+    marks.insert(strct, Mark::Visited);
+    sorted.push(strct);
 }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c806e55..414ea46 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -76,14 +76,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for api in toposort::sort(apis, out.types) {
+    for api in apis {
         match api {
-            Api::Struct(strct) => {
-                out.next_section();
-                if !out.types.cxx.contains(&strct.name.rust) {
-                    write_struct(out, strct);
-                }
-            }
             Api::Enum(enm) => {
                 out.next_section();
                 if out.types.cxx.contains(&enm.name.rust) {
@@ -102,6 +96,13 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    for strct in toposort::sort(apis, out.types) {
+        out.next_section();
+        if !out.types.cxx.contains(&strct.name.rust) {
+            write_struct(out, strct);
+        }
+    }
+
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index af8a9f5..9ea3450 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -277,6 +277,27 @@ pub mod ffi {
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
     }
+
+    struct Dag0 {
+        i: i32,
+    }
+
+    struct Dag1 {
+        dag2: Dag2,
+        vec: Vec<Dag3>,
+    }
+
+    struct Dag2 {
+        dag4: Dag4,
+    }
+
+    struct Dag3 {
+        dag1: Dag1,
+    }
+
+    struct Dag4 {
+        dag0: Dag0,
+    }
 }
 
 pub type R = usize;

From 942cffde239f07622ae7c275bf75d3fff09d1252 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:27:29 +0000
Subject: [PATCH 1247/2232] Perform topological sort of structs earlier during type checking


---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index d19dea0..3d12c71 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -12,7 +12,6 @@ pub(super) mod include;
 mod namespace;
 mod nested;
 pub(super) mod out;
-mod toposort;
 mod write;
 
 pub(super) use self::error::Error;
diff --git a/gen/src/toposort.rs b/gen/src/toposort.rs
deleted file mode 100644
index 62a1148..0000000
--- a/gen/src/toposort.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::syntax::{Api, Struct, Type, Types};
-use std::collections::btree_map::{BTreeMap as Map, Entry};
-
-enum Mark {
-    Visiting,
-    Visited,
-}
-
-pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
-    let mut sorted = Vec::new();
-    let ref mut marks = Map::new();
-    for api in apis {
-        if let Api::Struct(strct) = api {
-            visit(strct, &mut sorted, marks, types);
-        }
-    }
-    sorted
-}
-
-fn visit<'a>(
-    strct: &'a Struct,
-    sorted: &mut Vec<&'a Struct>,
-    marks: &mut Map<*const Struct, Mark>,
-    types: &Types<'a>,
-) {
-    match marks.entry(strct) {
-        Entry::Occupied(entry) => match entry.get() {
-            Mark::Visiting => panic!("not a DAG"), // FIXME
-            Mark::Visited => return,
-        },
-        Entry::Vacant(entry) => {
-            entry.insert(Mark::Visiting);
-        }
-    }
-    for field in &strct.fields {
-        if let Type::Ident(ident) = &field.ty {
-            if let Some(inner) = types.structs.get(&ident.rust) {
-                visit(inner, sorted, marks, types);
-            }
-        }
-    }
-    marks.insert(strct, Mark::Visited);
-    sorted.push(strct);
-}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 414ea46..fd2a815 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,7 +1,7 @@
 use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{builtin, include, toposort, Opt};
+use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -96,7 +96,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for strct in toposort::sort(apis, out.types) {
+    for strct in &out.types.toposorted_structs {
         out.next_section();
         if !out.types.cxx.contains(&strct.name.rust) {
             write_struct(out, strct);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b742e37..33ed31c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@ pub mod report;
 pub mod set;
 pub mod symbol;
 mod tokens;
+mod toposort;
 pub mod types;
 
 use self::discriminant::Discriminant;
diff --git a/syntax/toposort.rs b/syntax/toposort.rs
new file mode 100644
index 0000000..62a1148
--- /dev/null
+++ b/syntax/toposort.rs
@@ -0,0 +1,44 @@
+use crate::syntax::{Api, Struct, Type, Types};
+use std::collections::btree_map::{BTreeMap as Map, Entry};
+
+enum Mark {
+    Visiting,
+    Visited,
+}
+
+pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+    let mut sorted = Vec::new();
+    let ref mut marks = Map::new();
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            visit(strct, &mut sorted, marks, types);
+        }
+    }
+    sorted
+}
+
+fn visit<'a>(
+    strct: &'a Struct,
+    sorted: &mut Vec<&'a Struct>,
+    marks: &mut Map<*const Struct, Mark>,
+    types: &Types<'a>,
+) {
+    match marks.entry(strct) {
+        Entry::Occupied(entry) => match entry.get() {
+            Mark::Visiting => panic!("not a DAG"), // FIXME
+            Mark::Visited => return,
+        },
+        Entry::Vacant(entry) => {
+            entry.insert(Mark::Visiting);
+        }
+    }
+    for field in &strct.fields {
+        if let Type::Ident(ident) = &field.ty {
+            if let Some(inner) = types.structs.get(&ident.rust) {
+                visit(inner, sorted, marks, types);
+            }
+        }
+    }
+    marks.insert(strct, Mark::Visited);
+    sorted.push(strct);
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 5d6d582..ef2e5e6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,8 @@ use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
-    Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type, TypeAlias,
+    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -21,6 +22,7 @@ pub struct Types<'a> {
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
+    pub toposorted_structs: Vec<&'a Struct>,
 }
 
 impl<'a> Types<'a> {
@@ -35,6 +37,7 @@ impl<'a> Types<'a> {
         let mut explicit_impls = Set::new();
         let mut resolutions = Map::new();
         let struct_improper_ctypes = UnorderedSet::new();
+        let toposorted_structs = Vec::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -205,8 +208,11 @@ impl<'a> Types<'a> {
             explicit_impls,
             resolutions,
             struct_improper_ctypes,
+            toposorted_structs,
         };
 
+        types.toposorted_structs = toposort::sort(apis, &types);
+
         let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
         let mut new_information = true;
         while new_information {

From 0acfc126c7bc30d9390848849e902d784931eb3f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:41:40 +0000
Subject: [PATCH 1248/2232] Merge pull request #412 from dtolnay/sort


Perform topological sort of structs earlier during type checking
---

diff --git a/gen/src/mod.rs b/gen/src/mod.rs
index d19dea0..3d12c71 100644
--- a/gen/src/mod.rs
+++ b/gen/src/mod.rs
@@ -12,7 +12,6 @@ pub(super) mod include;
 mod namespace;
 mod nested;
 pub(super) mod out;
-mod toposort;
 mod write;
 
 pub(super) use self::error::Error;
diff --git a/gen/src/toposort.rs b/gen/src/toposort.rs
deleted file mode 100644
index 62a1148..0000000
--- a/gen/src/toposort.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::syntax::{Api, Struct, Type, Types};
-use std::collections::btree_map::{BTreeMap as Map, Entry};
-
-enum Mark {
-    Visiting,
-    Visited,
-}
-
-pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
-    let mut sorted = Vec::new();
-    let ref mut marks = Map::new();
-    for api in apis {
-        if let Api::Struct(strct) = api {
-            visit(strct, &mut sorted, marks, types);
-        }
-    }
-    sorted
-}
-
-fn visit<'a>(
-    strct: &'a Struct,
-    sorted: &mut Vec<&'a Struct>,
-    marks: &mut Map<*const Struct, Mark>,
-    types: &Types<'a>,
-) {
-    match marks.entry(strct) {
-        Entry::Occupied(entry) => match entry.get() {
-            Mark::Visiting => panic!("not a DAG"), // FIXME
-            Mark::Visited => return,
-        },
-        Entry::Vacant(entry) => {
-            entry.insert(Mark::Visiting);
-        }
-    }
-    for field in &strct.fields {
-        if let Type::Ident(ident) = &field.ty {
-            if let Some(inner) = types.structs.get(&ident.rust) {
-                visit(inner, sorted, marks, types);
-            }
-        }
-    }
-    marks.insert(strct, Mark::Visited);
-    sorted.push(strct);
-}
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 414ea46..fd2a815 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,7 +1,7 @@
 use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
-use crate::gen::{builtin, include, toposort, Opt};
+use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -96,7 +96,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for strct in toposort::sort(apis, out.types) {
+    for strct in &out.types.toposorted_structs {
         out.next_section();
         if !out.types.cxx.contains(&strct.name.rust) {
             write_struct(out, strct);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index b742e37..33ed31c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@ pub mod report;
 pub mod set;
 pub mod symbol;
 mod tokens;
+mod toposort;
 pub mod types;
 
 use self::discriminant::Discriminant;
diff --git a/syntax/toposort.rs b/syntax/toposort.rs
new file mode 100644
index 0000000..62a1148
--- /dev/null
+++ b/syntax/toposort.rs
@@ -0,0 +1,44 @@
+use crate::syntax::{Api, Struct, Type, Types};
+use std::collections::btree_map::{BTreeMap as Map, Entry};
+
+enum Mark {
+    Visiting,
+    Visited,
+}
+
+pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+    let mut sorted = Vec::new();
+    let ref mut marks = Map::new();
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            visit(strct, &mut sorted, marks, types);
+        }
+    }
+    sorted
+}
+
+fn visit<'a>(
+    strct: &'a Struct,
+    sorted: &mut Vec<&'a Struct>,
+    marks: &mut Map<*const Struct, Mark>,
+    types: &Types<'a>,
+) {
+    match marks.entry(strct) {
+        Entry::Occupied(entry) => match entry.get() {
+            Mark::Visiting => panic!("not a DAG"), // FIXME
+            Mark::Visited => return,
+        },
+        Entry::Vacant(entry) => {
+            entry.insert(Mark::Visiting);
+        }
+    }
+    for field in &strct.fields {
+        if let Type::Ident(ident) = &field.ty {
+            if let Some(inner) = types.structs.get(&ident.rust) {
+                visit(inner, sorted, marks, types);
+            }
+        }
+    }
+    marks.insert(strct, Mark::Visited);
+    sorted.push(strct);
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 5d6d582..ef2e5e6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,8 @@ use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::OrderedSet as Set;
 use crate::syntax::{
-    Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type, TypeAlias,
+    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -21,6 +22,7 @@ pub struct Types<'a> {
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
+    pub toposorted_structs: Vec<&'a Struct>,
 }
 
 impl<'a> Types<'a> {
@@ -35,6 +37,7 @@ impl<'a> Types<'a> {
         let mut explicit_impls = Set::new();
         let mut resolutions = Map::new();
         let struct_improper_ctypes = UnorderedSet::new();
+        let toposorted_structs = Vec::new();
 
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
@@ -205,8 +208,11 @@ impl<'a> Types<'a> {
             explicit_impls,
             resolutions,
             struct_improper_ctypes,
+            toposorted_structs,
         };
 
+        types.toposorted_structs = toposort::sort(apis, &types);
+
         let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
         let mut new_information = true;
         while new_information {

From 8b483096e627c36e8fcde025664fde09072dd6ec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:41:47 +0000
Subject: [PATCH 1249/2232] Pass error reporting context to topological sort


---

diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 62a1148..918d939 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::{Api, Struct, Type, Types};
 use std::collections::btree_map::{BTreeMap as Map, Entry};
 
@@ -6,18 +7,19 @@ enum Mark {
     Visited,
 }
 
-pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
     let mut sorted = Vec::new();
     let ref mut marks = Map::new();
     for api in apis {
         if let Api::Struct(strct) = api {
-            visit(strct, &mut sorted, marks, types);
+            visit(cx, strct, &mut sorted, marks, types);
         }
     }
     sorted
 }
 
 fn visit<'a>(
+    cx: &mut Errors,
     strct: &'a Struct,
     sorted: &mut Vec<&'a Struct>,
     marks: &mut Map<*const Struct, Mark>,
@@ -35,7 +37,7 @@ fn visit<'a>(
     for field in &strct.fields {
         if let Type::Ident(ident) = &field.ty {
             if let Some(inner) = types.structs.get(&ident.rust) {
-                visit(inner, sorted, marks, types);
+                visit(cx, inner, sorted, marks, types);
             }
         }
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index ef2e5e6..50325d6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -211,7 +211,7 @@ impl<'a> Types<'a> {
             toposorted_structs,
         };
 
-        types.toposorted_structs = toposort::sort(apis, &types);
+        types.toposorted_structs = toposort::sort(cx, apis, &types);
 
         let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
         let mut new_information = true;

From acae7a6aaedf5af8fd49095a8def69a9f538cbd4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:41:47 +0000
Subject: [PATCH 1250/2232] Emit diagnostic on cyclic structs


---

diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 918d939..7c210f2 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -12,7 +12,7 @@ pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a 
     let ref mut marks = Map::new();
     for api in apis {
         if let Api::Struct(strct) = api {
-            visit(cx, strct, &mut sorted, marks, types);
+            let _ = visit(cx, strct, &mut sorted, marks, types);
         }
     }
     sorted
@@ -24,11 +24,11 @@ fn visit<'a>(
     sorted: &mut Vec<&'a Struct>,
     marks: &mut Map<*const Struct, Mark>,
     types: &Types<'a>,
-) {
+) -> Result<(), ()> {
     match marks.entry(strct) {
         Entry::Occupied(entry) => match entry.get() {
-            Mark::Visiting => panic!("not a DAG"), // FIXME
-            Mark::Visited => return,
+            Mark::Visiting => return Err(()), // not a DAG
+            Mark::Visited => return Ok(()),
         },
         Entry::Vacant(entry) => {
             entry.insert(Mark::Visiting);
@@ -37,10 +37,13 @@ fn visit<'a>(
     for field in &strct.fields {
         if let Type::Ident(ident) = &field.ty {
             if let Some(inner) = types.structs.get(&ident.rust) {
-                visit(cx, inner, sorted, marks, types);
+                if visit(cx, inner, sorted, marks, types).is_err() {
+                    cx.error(field, "unsupported cyclic data structure");
+                }
             }
         }
     }
     marks.insert(strct, Mark::Visited);
     sorted.push(strct);
+    Ok(())
 }

From 07b7c13bc8d8c9073269bcba8631063c15ea602e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:41:48 +0000
Subject: [PATCH 1251/2232] Add ui test of struct cycle


---

diff --git a/tests/ui/struct_cycle.rs b/tests/ui/struct_cycle.rs
new file mode 100644
index 0000000..be5f553
--- /dev/null
+++ b/tests/ui/struct_cycle.rs
@@ -0,0 +1,30 @@
+#[cxx::bridge]
+mod ffi {
+    struct Node0 {
+        i: i32,
+    }
+
+    struct Node1 {
+        node2: Node2,
+        vec: Vec<Node3>,
+    }
+
+    struct Node2 {
+        node4: Node4,
+    }
+
+    struct Node3 {
+        node1: Node1,
+    }
+
+    struct Node4 {
+        node0: Node0,
+        node5: Node5,
+    }
+
+    struct Node5 {
+        node2: Node2,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/struct_cycle.stderr b/tests/ui/struct_cycle.stderr
new file mode 100644
index 0000000..7a64e29
--- /dev/null
+++ b/tests/ui/struct_cycle.stderr
@@ -0,0 +1,5 @@
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:26:9
+   |
+26 |         node2: Node2,
+   |         ^^^^^^^^^^^^

From 36b0ae8f3fe5630e63ff09822c2f7bdb18064919 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:49:51 +0000
Subject: [PATCH 1252/2232] Merge pull request #413 from dtolnay/sort


Emit diagnostic on cyclic structs
---

diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 62a1148..7c210f2 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -1,3 +1,4 @@
+use crate::syntax::report::Errors;
 use crate::syntax::{Api, Struct, Type, Types};
 use std::collections::btree_map::{BTreeMap as Map, Entry};
 
@@ -6,27 +7,28 @@ enum Mark {
     Visited,
 }
 
-pub fn sort<'a>(apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
+pub fn sort<'a>(cx: &mut Errors, apis: &'a [Api], types: &Types<'a>) -> Vec<&'a Struct> {
     let mut sorted = Vec::new();
     let ref mut marks = Map::new();
     for api in apis {
         if let Api::Struct(strct) = api {
-            visit(strct, &mut sorted, marks, types);
+            let _ = visit(cx, strct, &mut sorted, marks, types);
         }
     }
     sorted
 }
 
 fn visit<'a>(
+    cx: &mut Errors,
     strct: &'a Struct,
     sorted: &mut Vec<&'a Struct>,
     marks: &mut Map<*const Struct, Mark>,
     types: &Types<'a>,
-) {
+) -> Result<(), ()> {
     match marks.entry(strct) {
         Entry::Occupied(entry) => match entry.get() {
-            Mark::Visiting => panic!("not a DAG"), // FIXME
-            Mark::Visited => return,
+            Mark::Visiting => return Err(()), // not a DAG
+            Mark::Visited => return Ok(()),
         },
         Entry::Vacant(entry) => {
             entry.insert(Mark::Visiting);
@@ -35,10 +37,13 @@ fn visit<'a>(
     for field in &strct.fields {
         if let Type::Ident(ident) = &field.ty {
             if let Some(inner) = types.structs.get(&ident.rust) {
-                visit(inner, sorted, marks, types);
+                if visit(cx, inner, sorted, marks, types).is_err() {
+                    cx.error(field, "unsupported cyclic data structure");
+                }
             }
         }
     }
     marks.insert(strct, Mark::Visited);
     sorted.push(strct);
+    Ok(())
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index ef2e5e6..50325d6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -211,7 +211,7 @@ impl<'a> Types<'a> {
             toposorted_structs,
         };
 
-        types.toposorted_structs = toposort::sort(apis, &types);
+        types.toposorted_structs = toposort::sort(cx, apis, &types);
 
         let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
         let mut new_information = true;
diff --git a/tests/ui/struct_cycle.rs b/tests/ui/struct_cycle.rs
new file mode 100644
index 0000000..be5f553
--- /dev/null
+++ b/tests/ui/struct_cycle.rs
@@ -0,0 +1,30 @@
+#[cxx::bridge]
+mod ffi {
+    struct Node0 {
+        i: i32,
+    }
+
+    struct Node1 {
+        node2: Node2,
+        vec: Vec<Node3>,
+    }
+
+    struct Node2 {
+        node4: Node4,
+    }
+
+    struct Node3 {
+        node1: Node1,
+    }
+
+    struct Node4 {
+        node0: Node0,
+        node5: Node5,
+    }
+
+    struct Node5 {
+        node2: Node2,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/struct_cycle.stderr b/tests/ui/struct_cycle.stderr
new file mode 100644
index 0000000..7a64e29
--- /dev/null
+++ b/tests/ui/struct_cycle.stderr
@@ -0,0 +1,5 @@
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:26:9
+   |
+26 |         node2: Node2,
+   |         ^^^^^^^^^^^^

From 35b662dfc3d7a17792ed08f0a75e267ef248fe13 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 02:51:41 +0000
Subject: [PATCH 1253/2232] Point out every field involved in the cycle


---

diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 7c210f2..876f9ad 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -34,16 +34,18 @@ fn visit<'a>(
             entry.insert(Mark::Visiting);
         }
     }
+    let mut result = Ok(());
     for field in &strct.fields {
         if let Type::Ident(ident) = &field.ty {
             if let Some(inner) = types.structs.get(&ident.rust) {
                 if visit(cx, inner, sorted, marks, types).is_err() {
                     cx.error(field, "unsupported cyclic data structure");
+                    result = Err(());
                 }
             }
         }
     }
     marks.insert(strct, Mark::Visited);
     sorted.push(strct);
-    Ok(())
+    result
 }
diff --git a/tests/ui/struct_cycle.rs b/tests/ui/struct_cycle.rs
index be5f553..e74c2b1 100644
--- a/tests/ui/struct_cycle.rs
+++ b/tests/ui/struct_cycle.rs
@@ -25,6 +25,10 @@ mod ffi {
     struct Node5 {
         node2: Node2,
     }
+
+    struct Node6 {
+        node2: Node2,
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/struct_cycle.stderr b/tests/ui/struct_cycle.stderr
index 7a64e29..49bcb5f 100644
--- a/tests/ui/struct_cycle.stderr
+++ b/tests/ui/struct_cycle.stderr
@@ -3,3 +3,21 @@ error: unsupported cyclic data structure
    |
 26 |         node2: Node2,
    |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:22:9
+   |
+22 |         node5: Node5,
+   |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:13:9
+   |
+13 |         node4: Node4,
+   |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+ --> $DIR/struct_cycle.rs:8:9
+  |
+8 |         node2: Node2,
+  |         ^^^^^^^^^^^^

From 818004ff663e718071d056087ee30cbab31c173f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 03:01:33 +0000
Subject: [PATCH 1254/2232] Merge pull request #414 from dtolnay/sort


Point out every field involved in the cycle
---

diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 7c210f2..876f9ad 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -34,16 +34,18 @@ fn visit<'a>(
             entry.insert(Mark::Visiting);
         }
     }
+    let mut result = Ok(());
     for field in &strct.fields {
         if let Type::Ident(ident) = &field.ty {
             if let Some(inner) = types.structs.get(&ident.rust) {
                 if visit(cx, inner, sorted, marks, types).is_err() {
                     cx.error(field, "unsupported cyclic data structure");
+                    result = Err(());
                 }
             }
         }
     }
     marks.insert(strct, Mark::Visited);
     sorted.push(strct);
-    Ok(())
+    result
 }
diff --git a/tests/ui/struct_cycle.rs b/tests/ui/struct_cycle.rs
index be5f553..e74c2b1 100644
--- a/tests/ui/struct_cycle.rs
+++ b/tests/ui/struct_cycle.rs
@@ -25,6 +25,10 @@ mod ffi {
     struct Node5 {
         node2: Node2,
     }
+
+    struct Node6 {
+        node2: Node2,
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/struct_cycle.stderr b/tests/ui/struct_cycle.stderr
index 7a64e29..49bcb5f 100644
--- a/tests/ui/struct_cycle.stderr
+++ b/tests/ui/struct_cycle.stderr
@@ -3,3 +3,21 @@ error: unsupported cyclic data structure
    |
 26 |         node2: Node2,
    |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:22:9
+   |
+22 |         node5: Node5,
+   |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+  --> $DIR/struct_cycle.rs:13:9
+   |
+13 |         node4: Node4,
+   |         ^^^^^^^^^^^^
+
+error: unsupported cyclic data structure
+ --> $DIR/struct_cycle.rs:8:9
+  |
+8 |         node2: Node2,
+  |         ^^^^^^^^^^^^

From 5439fa195bbece443d261d40bf08d77012d44e58 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 03:21:30 +0000
Subject: [PATCH 1255/2232] Preserve relative order of structs and enums


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index fd2a815..b8d1dd4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -9,7 +9,7 @@ use crate::syntax::{
     Var,
 };
 use proc_macro2::Ident;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 
 pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
     let mut out_file = OutFile::new(header, opt, types);
@@ -76,8 +76,22 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    let mut structs_written = HashSet::new();
+    let mut toposorted_structs = out.types.toposorted_structs.iter();
     for api in apis {
         match api {
+            Api::Struct(strct) if !structs_written.contains(&strct.name.rust) => {
+                for next in &mut toposorted_structs {
+                    if !out.types.cxx.contains(&strct.name.rust) {
+                        out.next_section();
+                        write_struct(out, next);
+                    }
+                    structs_written.insert(&next.name.rust);
+                    if next.name.rust == strct.name.rust {
+                        break;
+                    }
+                }
+            }
             Api::Enum(enm) => {
                 out.next_section();
                 if out.types.cxx.contains(&enm.name.rust) {
@@ -96,13 +110,6 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    for strct in &out.types.toposorted_structs {
-        out.next_section();
-        if !out.types.cxx.contains(&strct.name.rust) {
-            write_struct(out, strct);
-        }
-    }
-
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {

From ecdd2d2cc8c764cb39e20dfe1d1ae6441c04dda2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 03:36:24 +0000
Subject: [PATCH 1256/2232] Introduce a visibility boundary inside of set module


In preparation for adding an UnorderedSet.

---

diff --git a/syntax/set.rs b/syntax/set.rs
index 73e3909..ee490e9 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -1,55 +1,61 @@
-use std::borrow::Borrow;
-use std::collections::HashSet;
 use std::fmt::{self, Debug};
-use std::hash::Hash;
 use std::slice;
 
-pub struct OrderedSet<T> {
-    set: HashSet<T>,
-    vec: Vec<T>,
-}
+pub use self::ordered::OrderedSet;
 
-impl<'a, T> OrderedSet<&'a T>
-where
-    T: Hash + Eq,
-{
-    pub fn new() -> Self {
-        OrderedSet {
-            set: HashSet::new(),
-            vec: Vec::new(),
-        }
-    }
+mod ordered {
+    use super::Iter;
+    use std::borrow::Borrow;
+    use std::collections::HashSet;
+    use std::hash::Hash;
 
-    pub fn insert(&mut self, value: &'a T) -> bool {
-        let new = self.set.insert(value);
-        if new {
-            self.vec.push(value);
-        }
-        new
+    pub struct OrderedSet<T> {
+        set: HashSet<T>,
+        vec: Vec<T>,
     }
 
-    pub fn contains<Q>(&self, value: &Q) -> bool
+    impl<'a, T> OrderedSet<&'a T>
     where
-        &'a T: Borrow<Q>,
-        Q: ?Sized + Hash + Eq,
+        T: Hash + Eq,
     {
-        self.set.contains(value)
-    }
+        pub fn new() -> Self {
+            OrderedSet {
+                set: HashSet::new(),
+                vec: Vec::new(),
+            }
+        }
 
-    pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
-    where
-        &'a T: Borrow<Q>,
-        Q: ?Sized + Hash + Eq,
-    {
-        self.set.get(value).copied()
+        pub fn insert(&mut self, value: &'a T) -> bool {
+            let new = self.set.insert(value);
+            if new {
+                self.vec.push(value);
+            }
+            new
+        }
+
+        pub fn contains<Q>(&self, value: &Q) -> bool
+        where
+            &'a T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.set.contains(value)
+        }
+
+        pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
+        where
+            &'a T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.set.get(value).copied()
+        }
     }
-}
 
-impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
-    type Item = &'a T;
-    type IntoIter = Iter<'s, 'a, T>;
-    fn into_iter(self) -> Self::IntoIter {
-        Iter(self.vec.iter())
+    impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
+        type Item = &'a T;
+        type IntoIter = Iter<'s, 'a, T>;
+        fn into_iter(self) -> Self::IntoIter {
+            Iter(self.vec.iter())
+        }
     }
 }
 

From c42de6906fd8bfde75bc27e34a99adc0e26af410 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 03:40:24 +0000
Subject: [PATCH 1257/2232] Introduce UnorderedSet newtype


---

diff --git a/syntax/set.rs b/syntax/set.rs
index ee490e9..6508f55 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -2,15 +2,15 @@ use std::fmt::{self, Debug};
 use std::slice;
 
 pub use self::ordered::OrderedSet;
+pub use self::unordered::UnorderedSet;
 
 mod ordered {
-    use super::Iter;
+    use super::{Iter, UnorderedSet};
     use std::borrow::Borrow;
-    use std::collections::HashSet;
     use std::hash::Hash;
 
     pub struct OrderedSet<T> {
-        set: HashSet<T>,
+        set: UnorderedSet<T>,
         vec: Vec<T>,
     }
 
@@ -20,7 +20,7 @@ mod ordered {
     {
         pub fn new() -> Self {
             OrderedSet {
-                set: HashSet::new(),
+                set: UnorderedSet::new(),
                 vec: Vec::new(),
             }
         }
@@ -59,6 +59,45 @@ mod ordered {
     }
 }
 
+mod unordered {
+    use std::borrow::Borrow;
+    use std::collections::HashSet;
+    use std::hash::Hash;
+
+    // Wrapper prohibits accidentally introducing iteration over the set, which
+    // could lead to nondeterministic generated code.
+    pub struct UnorderedSet<T>(HashSet<T>);
+
+    impl<T> UnorderedSet<T>
+    where
+        T: Hash + Eq,
+    {
+        pub fn new() -> Self {
+            UnorderedSet(HashSet::new())
+        }
+
+        pub fn insert(&mut self, value: T) -> bool {
+            self.0.insert(value)
+        }
+
+        pub fn contains<Q>(&self, value: &Q) -> bool
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.contains(value)
+        }
+
+        pub fn get<Q>(&self, value: &Q) -> Option<&T>
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.get(value)
+        }
+    }
+}
+
 pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
 
 impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
diff --git a/syntax/types.rs b/syntax/types.rs
index 50325d6..90a8221 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,14 +1,14 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
-use crate::syntax::set::OrderedSet as Set;
+use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
     toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
     TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
+use std::collections::BTreeMap as Map;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,

From bc21c75400dc1332c479490a6967c7323be24a5a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 04:50:34 +0000
Subject: [PATCH 1258/2232] Merge pull request #415 from dtolnay/set


Introduce UnorderedSet newtype
---

diff --git a/syntax/set.rs b/syntax/set.rs
index ee490e9..6508f55 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -2,15 +2,15 @@ use std::fmt::{self, Debug};
 use std::slice;
 
 pub use self::ordered::OrderedSet;
+pub use self::unordered::UnorderedSet;
 
 mod ordered {
-    use super::Iter;
+    use super::{Iter, UnorderedSet};
     use std::borrow::Borrow;
-    use std::collections::HashSet;
     use std::hash::Hash;
 
     pub struct OrderedSet<T> {
-        set: HashSet<T>,
+        set: UnorderedSet<T>,
         vec: Vec<T>,
     }
 
@@ -20,7 +20,7 @@ mod ordered {
     {
         pub fn new() -> Self {
             OrderedSet {
-                set: HashSet::new(),
+                set: UnorderedSet::new(),
                 vec: Vec::new(),
             }
         }
@@ -59,6 +59,45 @@ mod ordered {
     }
 }
 
+mod unordered {
+    use std::borrow::Borrow;
+    use std::collections::HashSet;
+    use std::hash::Hash;
+
+    // Wrapper prohibits accidentally introducing iteration over the set, which
+    // could lead to nondeterministic generated code.
+    pub struct UnorderedSet<T>(HashSet<T>);
+
+    impl<T> UnorderedSet<T>
+    where
+        T: Hash + Eq,
+    {
+        pub fn new() -> Self {
+            UnorderedSet(HashSet::new())
+        }
+
+        pub fn insert(&mut self, value: T) -> bool {
+            self.0.insert(value)
+        }
+
+        pub fn contains<Q>(&self, value: &Q) -> bool
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.contains(value)
+        }
+
+        pub fn get<Q>(&self, value: &Q) -> Option<&T>
+        where
+            T: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.get(value)
+        }
+    }
+}
+
 pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
 
 impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
diff --git a/syntax/types.rs b/syntax/types.rs
index 50325d6..90a8221 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,14 +1,14 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
-use crate::syntax::set::OrderedSet as Set;
+use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
     toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
     TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::{BTreeMap as Map, HashSet as UnorderedSet};
+use std::collections::BTreeMap as Map;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,

From b3060c66c834bb46a2d95a2dc5a5d8cde9fcbdb0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 04 2020 18:52:01 +0000
Subject: [PATCH 1259/2232] Release 0.5.3


---

diff --git a/Cargo.toml b/Cargo.toml
index 4e01e1a..a221708 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.2" # remember to update html_root_url
+version = "0.5.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,16 +20,16 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.2", path = "macro" }
+cxxbridge-macro = { version = "=0.5.3", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.2", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.3", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.2", path = "gen/build" }
-cxx-gen = { version = "0.5", path = "gen/lib" }
+cxx-build = { version = "=0.5.3", path = "gen/build" }
+cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 2f4c512..b8ac4a9 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b1954b4..e566bb4 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -20,7 +20,7 @@ scratch = "1.0"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
-cxx-gen = { version = "0.5", path = "../lib" }
+cxx-gen = { version = "0.6", path = "../lib" }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index f1c977c..8b7ed8b 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index ee62e14..d3c9ffb 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.5.2"
+version = "0.6.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 3d12d20..bc626ff 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.2"
+version = "0.5.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 9cd3adf..4cc283d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.3")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f9c5f60..703852c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.2"
+version = "0.5.3"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.2"
+version = "0.5.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -88,7 +88,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.5.2"
+version = "0.6.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.2"
+version = "0.5.3"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -119,11 +119,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.2"
+version = "0.5.3"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.2"
+version = "0.5.3"
 dependencies = [
  "cxx",
  "proc-macro2",

From 22664ae52fde550d9ca786284823a4159f53b988 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 00:30:45 +0000
Subject: [PATCH 1260/2232] Fix missing declaration of impl<T> template


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 7a4ddcd..f3240d0 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -24,6 +24,7 @@ pub struct Builtins<'a> {
     pub rust_slice_repr: bool,
     pub exception: bool,
     pub relocatable: bool,
+    pub friend_impl: bool,
     pub content: Content<'a>,
 }
 
@@ -51,6 +52,11 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_str {
         include.cstdint = true;
         include.string = true;
+        builtin.friend_impl = true;
+    }
+
+    if builtin.rust_slice {
+        builtin.friend_impl = true;
     }
 
     if builtin.rust_box {
@@ -68,6 +74,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     if builtin.rust_error {
         include.exception = true;
+        builtin.friend_impl = true;
     }
 
     if builtin.rust_isize {
@@ -89,7 +96,7 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "struct unsafe_bitcopy_t;");
     }
 
-    if builtin.rust_error {
+    if builtin.friend_impl {
         out.begin_block(Block::AnonymousNamespace);
         writeln!(out, "template <typename T>");
         writeln!(out, "class impl;");

From ce5b068efa60c993baca086007b09fa27423ffce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 00:32:04 +0000
Subject: [PATCH 1261/2232] Release 0.5.4


---

diff --git a/Cargo.toml b/Cargo.toml
index a221708..803f01e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.3" # remember to update html_root_url
+version = "0.5.4" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.3", path = "macro" }
+cxxbridge-macro = { version = "=0.5.4", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.3", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.4", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.3", path = "gen/build" }
+cxx-build = { version = "=0.5.4", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index b8ac4a9..17d89d6 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.3"
+version = "0.5.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index e566bb4..15949b5 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.3"
+version = "0.5.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 8b7ed8b..1289c34 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.3"
+version = "0.5.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index d3c9ffb..b4a10f1 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.0"
+version = "0.6.1"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index bc626ff..647710c 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.3"
+version = "0.5.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 4cc283d..5134268 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.3")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 703852c..bdfcc38 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.3"
+version = "0.5.4"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.3"
+version = "0.5.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -88,7 +88,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.0"
+version = "0.6.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -108,7 +108,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.3"
+version = "0.5.4"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -119,11 +119,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.3"
+version = "0.5.4"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.3"
+version = "0.5.4"
 dependencies = [
  "cxx",
  "proc-macro2",

From ae004d6b98fa6a30e2cbf9f9224fbde7d0e40439 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 00:36:42 +0000
Subject: [PATCH 1262/2232] Add string intern set


---

diff --git a/gen/build/src/intern.rs b/gen/build/src/intern.rs
new file mode 100644
index 0000000..800b8a3
--- /dev/null
+++ b/gen/build/src/intern.rs
@@ -0,0 +1,28 @@
+use lazy_static::lazy_static;
+use std::collections::HashSet;
+use std::sync::{Mutex, PoisonError};
+
+#[derive(Copy, Clone)]
+pub struct InternedString(&'static str);
+
+impl InternedString {
+    pub fn str(self) -> &'static str {
+        self.0
+    }
+}
+
+pub fn intern(s: &str) -> InternedString {
+    lazy_static! {
+        static ref INTERN: Mutex<HashSet<&'static str>> = Mutex::new(HashSet::new());
+    }
+
+    let mut set = INTERN.lock().unwrap_or_else(PoisonError::into_inner);
+    InternedString(match set.get(s) {
+        Some(interned) => *interned,
+        None => {
+            let interned = Box::leak(Box::from(s));
+            set.insert(interned);
+            interned
+        }
+    })
+}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 3e37143..b4a455a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -57,6 +57,7 @@
 mod cfg;
 mod error;
 mod gen;
+mod intern;
 mod out;
 mod paths;
 mod syntax;

From 676196b1fe2da5ca43a2bb41732cb0fb6fca6c10 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 00:36:42 +0000
Subject: [PATCH 1263/2232] Use interned strings in cfg implementation


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index e0186a3..d18a2c0 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -79,6 +79,7 @@ pub use self::r#impl::Cfg::CFG;
 
 #[cfg(not(doc))]
 mod r#impl {
+    use crate::intern::{intern, InternedString};
     use lazy_static::lazy_static;
     use std::cell::RefCell;
     use std::collections::HashMap;
@@ -88,12 +89,11 @@ mod r#impl {
     use std::sync::{PoisonError, RwLock};
 
     lazy_static! {
-        static ref PACKAGE_NAME: Box<str> = {
+        static ref INCLUDE_PREFIX: RwLock<InternedString> = RwLock::new({
             crate::env_os("CARGO_PKG_NAME")
-                .map(|pkg| pkg.to_string_lossy().into_owned().into_boxed_str())
+                .map(|pkg| intern(&pkg.to_string_lossy()))
                 .unwrap_or_default()
-        };
-        static ref INCLUDE_PREFIX: RwLock<Vec<&'static str>> = RwLock::new(vec![&PACKAGE_NAME]);
+        });
     }
 
     thread_local! {
@@ -117,11 +117,10 @@ mod r#impl {
 
     impl<'a> Cfg<'a> {
         fn current() -> super::Cfg<'a> {
-            let include_prefix = *INCLUDE_PREFIX
+            let include_prefix = INCLUDE_PREFIX
                 .read()
                 .unwrap_or_else(PoisonError::into_inner)
-                .last()
-                .unwrap();
+                .str();
             super::Cfg {
                 include_prefix,
                 marker: PhantomData,
@@ -184,10 +183,9 @@ mod r#impl {
     impl<'a> Drop for Cfg<'a> {
         fn drop(&mut self) {
             if let Cfg::Mut(cfg) = self {
-                INCLUDE_PREFIX
+                *INCLUDE_PREFIX
                     .write()
-                    .unwrap_or_else(PoisonError::into_inner)
-                    .push(Box::leak(Box::from(cfg.include_prefix)));
+                    .unwrap_or_else(PoisonError::into_inner) = intern(cfg.include_prefix);
             } else {
                 CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
             }
diff --git a/gen/build/src/intern.rs b/gen/build/src/intern.rs
index 800b8a3..51bc07c 100644
--- a/gen/build/src/intern.rs
+++ b/gen/build/src/intern.rs
@@ -2,7 +2,7 @@ use lazy_static::lazy_static;
 use std::collections::HashSet;
 use std::sync::{Mutex, PoisonError};
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default)]
 pub struct InternedString(&'static str);
 
 impl InternedString {

From bd54b6fd54234c1f4a7ba33ecf7902ef459c2c22 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 06:49:41 +0000
Subject: [PATCH 1264/2232] Add CFG exported header fields


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index d18a2c0..954481b 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -1,9 +1,17 @@
 use std::fmt::{self, Debug};
 use std::marker::PhantomData;
+use std::path::Path;
 
 /// Build configuration. See [CFG].
 pub struct Cfg<'a> {
     pub include_prefix: &'a str,
+    // Not implemented yet. https://github.com/dtolnay/cxx/issues/417
+    #[doc(hidden)]
+    pub exported_header_dirs: Vec<&'a Path>,
+    #[doc(hidden)]
+    pub exported_header_prefixes: Vec<&'a str>,
+    #[doc(hidden)]
+    pub exported_header_links: Vec<&'a str>,
     marker: PhantomData<*const ()>, // !Send + !Sync
 }
 
@@ -62,6 +70,9 @@ pub struct Cfg<'a> {
 #[cfg(doc)]
 pub static mut CFG: Cfg = Cfg {
     include_prefix: "",
+    exported_header_dirs: Vec::new(),
+    exported_header_prefixes: Vec::new(),
+    exported_header_links: Vec::new(),
     marker: PhantomData,
 };
 
@@ -123,6 +134,9 @@ mod r#impl {
                 .str();
             super::Cfg {
                 include_prefix,
+                exported_header_dirs: Vec::new(),
+                exported_header_prefixes: Vec::new(),
+                exported_header_links: Vec::new(),
                 marker: PhantomData,
             }
         }

From 306f126917782c79c19b83f41acc1c98a8f913e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 06:58:41 +0000
Subject: [PATCH 1265/2232] Wire up exported headers storage


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 954481b..b11756b 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -97,6 +97,7 @@ mod r#impl {
     use std::fmt::{self, Debug};
     use std::marker::PhantomData;
     use std::ops::{Deref, DerefMut};
+    use std::path::Path;
     use std::sync::{PoisonError, RwLock};
 
     lazy_static! {
@@ -105,6 +106,9 @@ mod r#impl {
                 .map(|pkg| intern(&pkg.to_string_lossy()))
                 .unwrap_or_default()
         });
+        static ref EXPORTED_HEADER_DIRS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
+        static ref EXPORTED_HEADER_PREFIXES: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
+        static ref EXPORTED_HEADER_LINKS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
     }
 
     thread_local! {
@@ -132,11 +136,33 @@ mod r#impl {
                 .read()
                 .unwrap_or_else(PoisonError::into_inner)
                 .str();
+            let exported_header_dirs = EXPORTED_HEADER_DIRS
+                .read()
+                .unwrap_or_else(PoisonError::into_inner)
+                .iter()
+                .copied()
+                .map(InternedString::str)
+                .map(Path::new)
+                .collect();
+            let exported_header_prefixes = EXPORTED_HEADER_PREFIXES
+                .read()
+                .unwrap_or_else(PoisonError::into_inner)
+                .iter()
+                .copied()
+                .map(InternedString::str)
+                .collect();
+            let exported_header_links = EXPORTED_HEADER_LINKS
+                .read()
+                .unwrap_or_else(PoisonError::into_inner)
+                .iter()
+                .copied()
+                .map(InternedString::str)
+                .collect();
             super::Cfg {
                 include_prefix,
-                exported_header_dirs: Vec::new(),
-                exported_header_prefixes: Vec::new(),
-                exported_header_links: Vec::new(),
+                exported_header_dirs,
+                exported_header_prefixes,
+                exported_header_links,
                 marker: PhantomData,
             }
         }
@@ -200,6 +226,30 @@ mod r#impl {
                 *INCLUDE_PREFIX
                     .write()
                     .unwrap_or_else(PoisonError::into_inner) = intern(cfg.include_prefix);
+                *EXPORTED_HEADER_DIRS
+                    .write()
+                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                    .exported_header_dirs
+                    .iter()
+                    .copied()
+                    .map(|path| intern(&path.to_string_lossy()))
+                    .collect();
+                *EXPORTED_HEADER_PREFIXES
+                    .write()
+                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                    .exported_header_prefixes
+                    .iter()
+                    .copied()
+                    .map(intern)
+                    .collect();
+                *EXPORTED_HEADER_LINKS
+                    .write()
+                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                    .exported_header_links
+                    .iter()
+                    .copied()
+                    .map(intern)
+                    .collect();
             } else {
                 CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
             }

From 39e9f91883f754716a13759dabcda345accac115 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 07:03:38 +0000
Subject: [PATCH 1266/2232] Combine current cfg into one rwlock


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index b11756b..880224a 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -100,15 +100,32 @@ mod r#impl {
     use std::path::Path;
     use std::sync::{PoisonError, RwLock};
 
-    lazy_static! {
-        static ref INCLUDE_PREFIX: RwLock<InternedString> = RwLock::new({
-            crate::env_os("CARGO_PKG_NAME")
+    struct CurrentCfg {
+        include_prefix: InternedString,
+        exported_header_dirs: Vec<InternedString>,
+        exported_header_prefixes: Vec<InternedString>,
+        exported_header_links: Vec<InternedString>,
+    }
+
+    impl CurrentCfg {
+        fn default() -> Self {
+            let include_prefix = crate::env_os("CARGO_PKG_NAME")
                 .map(|pkg| intern(&pkg.to_string_lossy()))
-                .unwrap_or_default()
-        });
-        static ref EXPORTED_HEADER_DIRS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
-        static ref EXPORTED_HEADER_PREFIXES: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
-        static ref EXPORTED_HEADER_LINKS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
+                .unwrap_or_default();
+            let exported_header_dirs = Vec::new();
+            let exported_header_prefixes = Vec::new();
+            let exported_header_links = Vec::new();
+            CurrentCfg {
+                include_prefix,
+                exported_header_dirs,
+                exported_header_prefixes,
+                exported_header_links,
+            }
+        }
+    }
+
+    lazy_static! {
+        static ref CURRENT: RwLock<CurrentCfg> = RwLock::new(CurrentCfg::default());
     }
 
     thread_local! {
@@ -132,28 +149,23 @@ mod r#impl {
 
     impl<'a> Cfg<'a> {
         fn current() -> super::Cfg<'a> {
-            let include_prefix = INCLUDE_PREFIX
-                .read()
-                .unwrap_or_else(PoisonError::into_inner)
-                .str();
-            let exported_header_dirs = EXPORTED_HEADER_DIRS
-                .read()
-                .unwrap_or_else(PoisonError::into_inner)
+            let current = CURRENT.read().unwrap_or_else(PoisonError::into_inner);
+            let include_prefix = current.include_prefix.str();
+            let exported_header_dirs = current
+                .exported_header_dirs
                 .iter()
                 .copied()
                 .map(InternedString::str)
                 .map(Path::new)
                 .collect();
-            let exported_header_prefixes = EXPORTED_HEADER_PREFIXES
-                .read()
-                .unwrap_or_else(PoisonError::into_inner)
+            let exported_header_prefixes = current
+                .exported_header_prefixes
                 .iter()
                 .copied()
                 .map(InternedString::str)
                 .collect();
-            let exported_header_links = EXPORTED_HEADER_LINKS
-                .read()
-                .unwrap_or_else(PoisonError::into_inner)
+            let exported_header_links = current
+                .exported_header_links
                 .iter()
                 .copied()
                 .map(InternedString::str)
@@ -223,28 +235,21 @@ mod r#impl {
     impl<'a> Drop for Cfg<'a> {
         fn drop(&mut self) {
             if let Cfg::Mut(cfg) = self {
-                *INCLUDE_PREFIX
-                    .write()
-                    .unwrap_or_else(PoisonError::into_inner) = intern(cfg.include_prefix);
-                *EXPORTED_HEADER_DIRS
-                    .write()
-                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                let mut current = CURRENT.write().unwrap_or_else(PoisonError::into_inner);
+                current.include_prefix = intern(cfg.include_prefix);
+                current.exported_header_dirs = cfg
                     .exported_header_dirs
                     .iter()
                     .copied()
                     .map(|path| intern(&path.to_string_lossy()))
                     .collect();
-                *EXPORTED_HEADER_PREFIXES
-                    .write()
-                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                current.exported_header_prefixes = cfg
                     .exported_header_prefixes
                     .iter()
                     .copied()
                     .map(intern)
                     .collect();
-                *EXPORTED_HEADER_LINKS
-                    .write()
-                    .unwrap_or_else(PoisonError::into_inner) = cfg
+                current.exported_header_links = cfg
                     .exported_header_links
                     .iter()
                     .copied()

From 95208218cac6a319d82f6c711e640cc8b3022080 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 07:15:31 +0000
Subject: [PATCH 1267/2232] Add interned vec helpers


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 880224a..00f9535 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -91,13 +91,13 @@ pub use self::r#impl::Cfg::CFG;
 #[cfg(not(doc))]
 mod r#impl {
     use crate::intern::{intern, InternedString};
+    use crate::vec::{self, InternedVec as _};
     use lazy_static::lazy_static;
     use std::cell::RefCell;
     use std::collections::HashMap;
     use std::fmt::{self, Debug};
     use std::marker::PhantomData;
     use std::ops::{Deref, DerefMut};
-    use std::path::Path;
     use std::sync::{PoisonError, RwLock};
 
     struct CurrentCfg {
@@ -151,25 +151,9 @@ mod r#impl {
         fn current() -> super::Cfg<'a> {
             let current = CURRENT.read().unwrap_or_else(PoisonError::into_inner);
             let include_prefix = current.include_prefix.str();
-            let exported_header_dirs = current
-                .exported_header_dirs
-                .iter()
-                .copied()
-                .map(InternedString::str)
-                .map(Path::new)
-                .collect();
-            let exported_header_prefixes = current
-                .exported_header_prefixes
-                .iter()
-                .copied()
-                .map(InternedString::str)
-                .collect();
-            let exported_header_links = current
-                .exported_header_links
-                .iter()
-                .copied()
-                .map(InternedString::str)
-                .collect();
+            let exported_header_dirs = current.exported_header_dirs.vec();
+            let exported_header_prefixes = current.exported_header_prefixes.vec();
+            let exported_header_links = current.exported_header_links.vec();
             super::Cfg {
                 include_prefix,
                 exported_header_dirs,
@@ -237,24 +221,9 @@ mod r#impl {
             if let Cfg::Mut(cfg) = self {
                 let mut current = CURRENT.write().unwrap_or_else(PoisonError::into_inner);
                 current.include_prefix = intern(cfg.include_prefix);
-                current.exported_header_dirs = cfg
-                    .exported_header_dirs
-                    .iter()
-                    .copied()
-                    .map(|path| intern(&path.to_string_lossy()))
-                    .collect();
-                current.exported_header_prefixes = cfg
-                    .exported_header_prefixes
-                    .iter()
-                    .copied()
-                    .map(intern)
-                    .collect();
-                current.exported_header_links = cfg
-                    .exported_header_links
-                    .iter()
-                    .copied()
-                    .map(intern)
-                    .collect();
+                current.exported_header_dirs = vec::intern(&cfg.exported_header_dirs);
+                current.exported_header_prefixes = vec::intern(&cfg.exported_header_prefixes);
+                current.exported_header_links = vec::intern(&cfg.exported_header_links);
             } else {
                 CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
             }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b4a455a..ef34d43 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -62,6 +62,7 @@ mod out;
 mod paths;
 mod syntax;
 mod target;
+mod vec;
 
 use crate::error::{Error, Result};
 use crate::gen::error::report;
diff --git a/gen/build/src/vec.rs b/gen/build/src/vec.rs
new file mode 100644
index 0000000..ac9235e
--- /dev/null
+++ b/gen/build/src/vec.rs
@@ -0,0 +1,50 @@
+use crate::intern::{self, InternedString};
+use std::path::Path;
+
+pub trait InternedVec<T>
+where
+    T: ?Sized,
+{
+    fn vec(&self) -> Vec<&'static T>;
+}
+
+impl<T> InternedVec<T> for Vec<InternedString>
+where
+    T: ?Sized + Element,
+{
+    fn vec(&self) -> Vec<&'static T> {
+        self.iter().copied().map(Element::unintern).collect()
+    }
+}
+
+pub fn intern<T>(elements: &[&T]) -> Vec<InternedString>
+where
+    T: ?Sized + Element,
+{
+    elements.iter().copied().map(Element::intern).collect()
+}
+
+pub trait Element {
+    fn intern(&self) -> InternedString;
+    fn unintern(_: InternedString) -> &'static Self;
+}
+
+impl Element for str {
+    fn intern(&self) -> InternedString {
+        intern::intern(self)
+    }
+
+    fn unintern(interned: InternedString) -> &'static Self {
+        interned.str()
+    }
+}
+
+impl Element for Path {
+    fn intern(&self) -> InternedString {
+        intern::intern(&self.to_string_lossy())
+    }
+
+    fn unintern(interned: InternedString) -> &'static Self {
+        Path::new(interned.str())
+    }
+}

From 62ff78f20ed91a77e2ab2446e292776053562cd3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 07:26:54 +0000
Subject: [PATCH 1268/2232] Move dependency-collecting logic to module


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
new file mode 100644
index 0000000..05a15d3
--- /dev/null
+++ b/gen/build/src/deps.rs
@@ -0,0 +1,38 @@
+use std::collections::BTreeMap;
+use std::env;
+use std::path::PathBuf;
+
+pub fn include_dirs() -> impl Iterator<Item = PathBuf> {
+    let mut env_include_dirs = BTreeMap::new();
+    for (k, v) in env::vars_os() {
+        let mut k = k.to_string_lossy().into_owned();
+        // Only variables set from a build script of direct dependencies are
+        // observable. That's exactly what we want! Your crate needs to declare
+        // a direct dependency on the other crate in order to be able to
+        // #include its headers.
+        //
+        // Also, they're only observable if the dependency's manifest contains a
+        // `links` key. This is important because Cargo imposes no ordering on
+        // the execution of build scripts without a `links` key. When exposing a
+        // generated header for the current crate to #include, we need to be
+        // sure the dependency's build script has already executed and emitted
+        // that generated header.
+        //
+        // References:
+        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
+        if k.starts_with("DEP_") {
+            if k.ends_with("_CXXBRIDGE_INCLUDE") {
+                // Tweak to ensure sorted before the other one, for the same
+                // reason as the comment on ordering of include_dir vs crate_dir
+                // above.
+                k.replace_range(k.len() - "INCLUDE".len().., "0");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_CRATE") {
+                k.replace_range(k.len() - "CRATE".len().., "1");
+                env_include_dirs.insert(k, PathBuf::from(v));
+            }
+        }
+    }
+    env_include_dirs.into_iter().map(|entry| entry.1)
+}
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ef34d43..6908f3c 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -55,6 +55,7 @@
 )]
 
 mod cfg;
+mod deps;
 mod error;
 mod gen;
 mod intern;
@@ -70,7 +71,6 @@ use crate::gen::Opt;
 use crate::paths::PathExt;
 use crate::target::TargetDir;
 use cc::Build;
-use std::collections::BTreeMap;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -199,48 +199,13 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         build.include(crate_dir);
         eprintln!("  {}", crate_dir.display());
     }
-    for dep in env_include_dirs() {
+    for dep in deps::include_dirs() {
         build.include(&dep);
         eprintln!("  {}", dep.display());
     }
     Ok(build)
 }
 
-fn env_include_dirs() -> impl Iterator<Item = PathBuf> {
-    let mut env_include_dirs = BTreeMap::new();
-    for (k, v) in env::vars_os() {
-        let mut k = k.to_string_lossy().into_owned();
-        // Only variables set from a build script of direct dependencies are
-        // observable. That's exactly what we want! Your crate needs to declare
-        // a direct dependency on the other crate in order to be able to
-        // #include its headers.
-        //
-        // Also, they're only observable if the dependency's manifest contains a
-        // `links` key. This is important because Cargo imposes no ordering on
-        // the execution of build scripts without a `links` key. When exposing a
-        // generated header for the current crate to #include, we need to be
-        // sure the dependency's build script has already executed and emitted
-        // that generated header.
-        //
-        // References:
-        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
-        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
-        if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_INCLUDE") {
-                // Tweak to ensure sorted before the other one, for the same
-                // reason as the comment on ordering of include_dir vs crate_dir
-                // above.
-                k.replace_range(k.len() - "INCLUDE".len().., "0");
-                env_include_dirs.insert(k, PathBuf::from(v));
-            } else if k.ends_with("_CXXBRIDGE_CRATE") {
-                k.replace_range(k.len() - "CRATE".len().., "1");
-                env_include_dirs.insert(k, PathBuf::from(v));
-            }
-        }
-    }
-    env_include_dirs.into_iter().map(|entry| entry.1)
-}
-
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
     if prj.include_prefix.as_os_str().is_empty() {
         let crate_dir = prj.manifest_dir.clone();

From f20c9b786a54d3364fd88f20f6aab027d41059e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 18:22:01 +0000
Subject: [PATCH 1269/2232] Start building structured dependency information


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 05a15d3..57e96c9 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -2,8 +2,15 @@ use std::collections::BTreeMap;
 use std::env;
 use std::path::PathBuf;
 
-pub fn include_dirs() -> impl Iterator<Item = PathBuf> {
-    let mut env_include_dirs = BTreeMap::new();
+#[derive(Default)]
+pub struct Crate {
+    pub crate_dir: Option<PathBuf>,
+    pub include_dir: Option<PathBuf>,
+}
+
+pub fn direct_dependencies() -> Vec<Crate> {
+    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
+
     for (k, v) in env::vars_os() {
         let mut k = k.to_string_lossy().into_owned();
         // Only variables set from a build script of direct dependencies are
@@ -22,17 +29,15 @@ pub fn include_dirs() -> impl Iterator<Item = PathBuf> {
         //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
         //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
         if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_INCLUDE") {
-                // Tweak to ensure sorted before the other one, for the same
-                // reason as the comment on ordering of include_dir vs crate_dir
-                // above.
-                k.replace_range(k.len() - "INCLUDE".len().., "0");
-                env_include_dirs.insert(k, PathBuf::from(v));
-            } else if k.ends_with("_CXXBRIDGE_CRATE") {
-                k.replace_range(k.len() - "CRATE".len().., "1");
-                env_include_dirs.insert(k, PathBuf::from(v));
+            if k.ends_with("_CXXBRIDGE_CRATE") {
+                k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
+                crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
+                k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
+                crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
             }
         }
     }
-    env_include_dirs.into_iter().map(|entry| entry.1)
+
+    crates.into_iter().map(|entry| entry.1).collect()
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 6908f3c..b684a25 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -65,6 +65,7 @@ mod syntax;
 mod target;
 mod vec;
 
+use crate::deps::Crate;
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
@@ -177,8 +178,8 @@ impl Project {
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
 
-    let ref crate_dir = make_crate_dir(prj);
-    let ref include_dir = make_include_dir(prj)?;
+    let crate_dir = make_crate_dir(prj);
+    let include_dir = make_include_dir(prj)?;
 
     let mut build = Build::new();
     build.cpp(true);
@@ -188,21 +189,31 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
+    let mut crates = deps::direct_dependencies();
+    crates.insert(
+        0,
+        Crate {
+            crate_dir,
+            include_dir: Some(include_dir),
+        },
+    );
+
     eprintln!("\nCXX include path:");
-    build.include(include_dir);
-    eprintln!("  {}", include_dir.display());
-    if let Some(crate_dir) = crate_dir {
-        // Placed after the generated code directory (include_dir) on the
-        // include line so that `#include "path/to/file.rs"` from C++
-        // "magically" works and refers to the API generated from that Rust
-        // source file.
-        build.include(crate_dir);
-        eprintln!("  {}", crate_dir.display());
-    }
-    for dep in deps::include_dirs() {
-        build.include(&dep);
-        eprintln!("  {}", dep.display());
+    for krate in crates {
+        if let Some(include_dir) = &krate.include_dir {
+            build.include(include_dir);
+            eprintln!("  {}", include_dir.display());
+        }
+        if let Some(crate_dir) = &krate.crate_dir {
+            // Placed after the generated code directory (include_dir) on the
+            // include line so that `#include "path/to/file.rs"` from C++
+            // "magically" works and refers to the API generated from that Rust
+            // source file.
+            build.include(crate_dir);
+            eprintln!("  {}", crate_dir.display());
+        }
     }
+
     Ok(build)
 }
 

From a2c9b9e3fcabd7799f97dc3ce67c362d7e45c164 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 18:34:19 +0000
Subject: [PATCH 1270/2232] Merge pull request #418 from dtolnay/crate


Start building structured dependency information
---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 05a15d3..57e96c9 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -2,8 +2,15 @@ use std::collections::BTreeMap;
 use std::env;
 use std::path::PathBuf;
 
-pub fn include_dirs() -> impl Iterator<Item = PathBuf> {
-    let mut env_include_dirs = BTreeMap::new();
+#[derive(Default)]
+pub struct Crate {
+    pub crate_dir: Option<PathBuf>,
+    pub include_dir: Option<PathBuf>,
+}
+
+pub fn direct_dependencies() -> Vec<Crate> {
+    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
+
     for (k, v) in env::vars_os() {
         let mut k = k.to_string_lossy().into_owned();
         // Only variables set from a build script of direct dependencies are
@@ -22,17 +29,15 @@ pub fn include_dirs() -> impl Iterator<Item = PathBuf> {
         //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
         //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
         if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_INCLUDE") {
-                // Tweak to ensure sorted before the other one, for the same
-                // reason as the comment on ordering of include_dir vs crate_dir
-                // above.
-                k.replace_range(k.len() - "INCLUDE".len().., "0");
-                env_include_dirs.insert(k, PathBuf::from(v));
-            } else if k.ends_with("_CXXBRIDGE_CRATE") {
-                k.replace_range(k.len() - "CRATE".len().., "1");
-                env_include_dirs.insert(k, PathBuf::from(v));
+            if k.ends_with("_CXXBRIDGE_CRATE") {
+                k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
+                crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
+                k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
+                crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
             }
         }
     }
-    env_include_dirs.into_iter().map(|entry| entry.1)
+
+    crates.into_iter().map(|entry| entry.1).collect()
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 6908f3c..b684a25 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -65,6 +65,7 @@ mod syntax;
 mod target;
 mod vec;
 
+use crate::deps::Crate;
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
@@ -177,8 +178,8 @@ impl Project {
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
 
-    let ref crate_dir = make_crate_dir(prj);
-    let ref include_dir = make_include_dir(prj)?;
+    let crate_dir = make_crate_dir(prj);
+    let include_dir = make_include_dir(prj)?;
 
     let mut build = Build::new();
     build.cpp(true);
@@ -188,21 +189,31 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
+    let mut crates = deps::direct_dependencies();
+    crates.insert(
+        0,
+        Crate {
+            crate_dir,
+            include_dir: Some(include_dir),
+        },
+    );
+
     eprintln!("\nCXX include path:");
-    build.include(include_dir);
-    eprintln!("  {}", include_dir.display());
-    if let Some(crate_dir) = crate_dir {
-        // Placed after the generated code directory (include_dir) on the
-        // include line so that `#include "path/to/file.rs"` from C++
-        // "magically" works and refers to the API generated from that Rust
-        // source file.
-        build.include(crate_dir);
-        eprintln!("  {}", crate_dir.display());
-    }
-    for dep in deps::include_dirs() {
-        build.include(&dep);
-        eprintln!("  {}", dep.display());
+    for krate in crates {
+        if let Some(include_dir) = &krate.include_dir {
+            build.include(include_dir);
+            eprintln!("  {}", include_dir.display());
+        }
+        if let Some(crate_dir) = &krate.crate_dir {
+            // Placed after the generated code directory (include_dir) on the
+            // include line so that `#include "path/to/file.rs"` from C++
+            // "magically" works and refers to the API generated from that Rust
+            // source file.
+            build.include(crate_dir);
+            eprintln!("  {}", crate_dir.display());
+        }
     }
+
     Ok(build)
 }
 

From ffb7502f311be8a83823790bfcf9e57d8aaf4ccd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 18:35:59 +0000
Subject: [PATCH 1271/2232] Centralize cargo k/v printing in dependency manager


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 57e96c9..6e177c9 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -8,6 +8,17 @@ pub struct Crate {
     pub include_dir: Option<PathBuf>,
 }
 
+impl Crate {
+    pub fn print_to_cargo(&self) {
+        if let Some(crate_dir) = &self.crate_dir {
+            println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
+        }
+        if let Some(include_dir) = &self.include_dir {
+            println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
+        }
+    }
+}
+
 pub fn direct_dependencies() -> Vec<Crate> {
     let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
 
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b684a25..ed820d4 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -180,6 +180,11 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
+    let this_crate = Crate {
+        crate_dir,
+        include_dir: Some(include_dir),
+    };
+    this_crate.print_to_cargo();
 
     let mut build = Build::new();
     build.cpp(true);
@@ -190,13 +195,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     }
 
     let mut crates = deps::direct_dependencies();
-    crates.insert(
-        0,
-        Crate {
-            crate_dir,
-            include_dir: Some(include_dir),
-        },
-    );
+    crates.insert(0, this_crate);
 
     eprintln!("\nCXX include path:");
     for krate in crates {
@@ -219,14 +218,11 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
     if prj.include_prefix.as_os_str().is_empty() {
-        let crate_dir = prj.manifest_dir.clone();
-        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
-        return Some(crate_dir);
+        return Some(prj.manifest_dir.clone());
     }
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
     let link = crate_dir.join(&prj.include_prefix);
     if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
-        println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         Some(crate_dir)
     } else {
         None
@@ -244,7 +240,6 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
         out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
         out::symlink_file(shared_cxx_h, cxx_h)?;
     }
-    println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
     Ok(include_dir)
 }
 

From dea530d48c9c8d7afd91a95f8c907fbfdc59713a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 18:54:48 +0000
Subject: [PATCH 1272/2232] Track include_prefix and links attribute across deps


Necessary for implementing CFG.exported_header_prefixes and
CFG.exported_header_links.

---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 6e177c9..c585203 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -1,15 +1,24 @@
 use std::collections::BTreeMap;
 use std::env;
+use std::ffi::OsString;
 use std::path::PathBuf;
 
 #[derive(Default)]
 pub struct Crate {
+    pub include_prefix: Option<PathBuf>,
+    pub links: Option<OsString>,
     pub crate_dir: Option<PathBuf>,
     pub include_dir: Option<PathBuf>,
 }
 
 impl Crate {
     pub fn print_to_cargo(&self) {
+        if let Some(include_prefix) = &self.include_prefix {
+            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
+        }
+        if let Some(links) = &self.links {
+            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
+        }
         if let Some(crate_dir) = &self.crate_dir {
             println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         }
@@ -40,7 +49,13 @@ pub fn direct_dependencies() -> Vec<Crate> {
         //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
         //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
         if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_CRATE") {
+            if k.ends_with("_CXXBRIDGE_PREFIX") {
+                k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
+                crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_LINKS") {
+                k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
+                crates.entry(k).or_default().links = Some(v);
+            } else if k.ends_with("_CXXBRIDGE_CRATE") {
                 k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
                 crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
             } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ed820d4..2ec45e0 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -181,6 +181,8 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
     let this_crate = Crate {
+        include_prefix: Some(prj.include_prefix.clone()),
+        links: env::var_os("CARGO_MANIFEST_LINKS"),
         crate_dir,
         include_dir: Some(include_dir),
     };

From 7b2c8bfb068ab2890f477eee7a39eb4256e82679 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 19:01:13 +0000
Subject: [PATCH 1273/2232] Merge pull request #419 from dtolnay/deps


Track include_prefix and links attribute across deps
---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 6e177c9..c585203 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -1,15 +1,24 @@
 use std::collections::BTreeMap;
 use std::env;
+use std::ffi::OsString;
 use std::path::PathBuf;
 
 #[derive(Default)]
 pub struct Crate {
+    pub include_prefix: Option<PathBuf>,
+    pub links: Option<OsString>,
     pub crate_dir: Option<PathBuf>,
     pub include_dir: Option<PathBuf>,
 }
 
 impl Crate {
     pub fn print_to_cargo(&self) {
+        if let Some(include_prefix) = &self.include_prefix {
+            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
+        }
+        if let Some(links) = &self.links {
+            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
+        }
         if let Some(crate_dir) = &self.crate_dir {
             println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
         }
@@ -40,7 +49,13 @@ pub fn direct_dependencies() -> Vec<Crate> {
         //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
         //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
         if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_CRATE") {
+            if k.ends_with("_CXXBRIDGE_PREFIX") {
+                k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
+                crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
+            } else if k.ends_with("_CXXBRIDGE_LINKS") {
+                k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
+                crates.entry(k).or_default().links = Some(v);
+            } else if k.ends_with("_CXXBRIDGE_CRATE") {
                 k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
                 crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
             } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ed820d4..2ec45e0 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -181,6 +181,8 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
     let this_crate = Crate {
+        include_prefix: Some(prj.include_prefix.clone()),
+        links: env::var_os("CARGO_MANIFEST_LINKS"),
         crate_dir,
         include_dir: Some(include_dir),
     };

From 804fb11724767f9acd48974cf3074b221fd22509 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:07:48 +0000
Subject: [PATCH 1274/2232] Reduce nesting in direct_dependencies()


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index c585203..43d262a 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -31,37 +31,49 @@ impl Crate {
 pub fn direct_dependencies() -> Vec<Crate> {
     let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
 
+    // Only variables set from a build script of direct dependencies are
+    // observable. That's exactly what we want! Your crate needs to declare a
+    // direct dependency on the other crate in order to be able to #include its
+    // headers.
+    //
+    // Also, they're only observable if the dependency's manifest contains a
+    // `links` key. This is important because Cargo imposes no ordering on the
+    // execution of build scripts without a `links` key. When exposing a
+    // generated header for the current crate to #include, we need to be sure
+    // the dependency's build script has already executed and emitted that
+    // generated header.
+    //
+    // References:
+    //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+    //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
     for (k, v) in env::vars_os() {
         let mut k = k.to_string_lossy().into_owned();
-        // Only variables set from a build script of direct dependencies are
-        // observable. That's exactly what we want! Your crate needs to declare
-        // a direct dependency on the other crate in order to be able to
-        // #include its headers.
-        //
-        // Also, they're only observable if the dependency's manifest contains a
-        // `links` key. This is important because Cargo imposes no ordering on
-        // the execution of build scripts without a `links` key. When exposing a
-        // generated header for the current crate to #include, we need to be
-        // sure the dependency's build script has already executed and emitted
-        // that generated header.
-        //
-        // References:
-        //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
-        //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
-        if k.starts_with("DEP_") {
-            if k.ends_with("_CXXBRIDGE_PREFIX") {
-                k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
-                crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
-            } else if k.ends_with("_CXXBRIDGE_LINKS") {
-                k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
-                crates.entry(k).or_default().links = Some(v);
-            } else if k.ends_with("_CXXBRIDGE_CRATE") {
-                k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
-                crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
-            } else if k.ends_with("_CXXBRIDGE_INCLUDE") {
-                k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
-                crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
-            }
+        if !k.starts_with("DEP_") {
+            continue;
+        }
+
+        if k.ends_with("_CXXBRIDGE_PREFIX") {
+            k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
+            crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
+            continue;
+        }
+
+        if k.ends_with("_CXXBRIDGE_LINKS") {
+            k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
+            crates.entry(k).or_default().links = Some(v);
+            continue;
+        }
+
+        if k.ends_with("_CXXBRIDGE_CRATE") {
+            k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
+            crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
+            continue;
+        }
+
+        if k.ends_with("_CXXBRIDGE_INCLUDE") {
+            k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
+            crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
+            continue;
         }
     }
 

From cf7b21bc2d6c3d3d12934598f7b6e24a7b2b5de0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:21:48 +0000
Subject: [PATCH 1275/2232] Preserve more than just the two default exported dirs


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 43d262a..558956d 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -7,23 +7,26 @@ use std::path::PathBuf;
 pub struct Crate {
     pub include_prefix: Option<PathBuf>,
     pub links: Option<OsString>,
-    pub crate_dir: Option<PathBuf>,
-    pub include_dir: Option<PathBuf>,
+    pub exported_header_dirs: Vec<PathBuf>,
 }
 
 impl Crate {
     pub fn print_to_cargo(&self) {
         if let Some(include_prefix) = &self.include_prefix {
-            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
+            println!(
+                "cargo:CXXBRIDGE_PREFIX={}",
+                include_prefix.to_string_lossy(),
+            );
         }
         if let Some(links) = &self.links {
             println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
         }
-        if let Some(crate_dir) = &self.crate_dir {
-            println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
-        }
-        if let Some(include_dir) = &self.include_dir {
-            println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
+        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
+            println!(
+                "cargo:CXXBRIDGE_DIR{}={}",
+                i,
+                exported_dir.to_string_lossy(),
+            );
         }
     }
 }
@@ -64,17 +67,18 @@ pub fn direct_dependencies() -> Vec<Crate> {
             continue;
         }
 
-        if k.ends_with("_CXXBRIDGE_CRATE") {
-            k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
-            crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
+        let without_counter = k.trim_end_matches(|ch: char| ch.is_ascii_digit());
+        let counter_len = k.len() - without_counter.len();
+        if counter_len == 0 || !without_counter.ends_with("_CXXBRIDGE_DIR") {
             continue;
         }
 
-        if k.ends_with("_CXXBRIDGE_INCLUDE") {
-            k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
-            crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
-            continue;
-        }
+        k.truncate(k.len() - counter_len - "_CXXBRIDGE_DIR".len());
+        crates
+            .entry(k)
+            .or_default()
+            .exported_header_dirs
+            .push(PathBuf::from(v));
     }
 
     crates.into_iter().map(|entry| entry.1).collect()
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 2ec45e0..8c4e999 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -180,12 +180,18 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
-    let this_crate = Crate {
+    let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
         links: env::var_os("CARGO_MANIFEST_LINKS"),
-        crate_dir,
-        include_dir: Some(include_dir),
+        exported_header_dirs: Vec::new(),
     };
+
+    // The crate_dir is placed after the generated code directory (include_dir)
+    // on the include line so that `#include "path/to/file.rs"` from C++
+    // "magically" works and refers to the API generated from that Rust source
+    // file.
+    this_crate.exported_header_dirs.push(include_dir);
+    this_crate.exported_header_dirs.extend(crate_dir);
     this_crate.print_to_cargo();
 
     let mut build = Build::new();
@@ -201,17 +207,9 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     eprintln!("\nCXX include path:");
     for krate in crates {
-        if let Some(include_dir) = &krate.include_dir {
-            build.include(include_dir);
-            eprintln!("  {}", include_dir.display());
-        }
-        if let Some(crate_dir) = &krate.crate_dir {
-            // Placed after the generated code directory (include_dir) on the
-            // include line so that `#include "path/to/file.rs"` from C++
-            // "magically" works and refers to the API generated from that Rust
-            // source file.
-            build.include(crate_dir);
-            eprintln!("  {}", crate_dir.display());
+        for header_dir in &krate.exported_header_dirs {
+            build.include(header_dir);
+            eprintln!("  {}", header_dir.display());
         }
     }
 

From d1be0b7226709d89361d15905d058ac3f1d9437c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:22:19 +0000
Subject: [PATCH 1276/2232] Preserve counter order of exported dirs


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 558956d..4e34835 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -33,6 +33,7 @@ impl Crate {
 
 pub fn direct_dependencies() -> Vec<Crate> {
     let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
+    let mut exported_header_dirs: BTreeMap<String, Vec<(usize, PathBuf)>> = BTreeMap::new();
 
     // Only variables set from a build script of direct dependencies are
     // observable. That's exactly what we want! Your crate needs to declare a
@@ -73,12 +74,23 @@ pub fn direct_dependencies() -> Vec<Crate> {
             continue;
         }
 
+        let sort_key = k[k.len() - counter_len..]
+            .parse::<usize>()
+            .unwrap_or(usize::MAX);
         k.truncate(k.len() - counter_len - "_CXXBRIDGE_DIR".len());
+        exported_header_dirs
+            .entry(k)
+            .or_default()
+            .push((sort_key, PathBuf::from(v)));
+    }
+
+    for (k, mut dirs) in exported_header_dirs {
+        dirs.sort_by_key(|(sort_key, _dir)| *sort_key);
         crates
             .entry(k)
             .or_default()
             .exported_header_dirs
-            .push(PathBuf::from(v));
+            .extend(dirs.into_iter().map(|(_sort_key, dir)| dir));
     }
 
     crates.into_iter().map(|entry| entry.1).collect()

From d3a6f61fc688fe76dcb6851665b4db1e58f3c8e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:27:06 +0000
Subject: [PATCH 1277/2232] Clean up wording of include_dir vs crate_dir sort comment


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8c4e999..7bfc3e7 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -186,10 +186,10 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         exported_header_dirs: Vec::new(),
     };
 
-    // The crate_dir is placed after the generated code directory (include_dir)
-    // on the include line so that `#include "path/to/file.rs"` from C++
-    // "magically" works and refers to the API generated from that Rust source
-    // file.
+    // The generated code directory (include_dir) is placed in front of
+    // crate_dir on the include line so that `#include "path/to/file.rs"` from
+    // C++ "magically" works and refers to the API generated from that Rust
+    // source file.
     this_crate.exported_header_dirs.push(include_dir);
     this_crate.exported_header_dirs.extend(crate_dir);
     this_crate.print_to_cargo();

From b14375ff9df9f85cd3c0225219fc52d6c1a48c68 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:34:06 +0000
Subject: [PATCH 1278/2232] Merge pull request #420 from dtolnay/dirs


Preserve more than just the two default exported dirs
---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 43d262a..4e34835 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -7,29 +7,33 @@ use std::path::PathBuf;
 pub struct Crate {
     pub include_prefix: Option<PathBuf>,
     pub links: Option<OsString>,
-    pub crate_dir: Option<PathBuf>,
-    pub include_dir: Option<PathBuf>,
+    pub exported_header_dirs: Vec<PathBuf>,
 }
 
 impl Crate {
     pub fn print_to_cargo(&self) {
         if let Some(include_prefix) = &self.include_prefix {
-            println!("cargo:CXXBRIDGE_PREFIX={}", include_prefix.to_string_lossy());
+            println!(
+                "cargo:CXXBRIDGE_PREFIX={}",
+                include_prefix.to_string_lossy(),
+            );
         }
         if let Some(links) = &self.links {
             println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
         }
-        if let Some(crate_dir) = &self.crate_dir {
-            println!("cargo:CXXBRIDGE_CRATE={}", crate_dir.to_string_lossy());
-        }
-        if let Some(include_dir) = &self.include_dir {
-            println!("cargo:CXXBRIDGE_INCLUDE={}", include_dir.to_string_lossy());
+        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
+            println!(
+                "cargo:CXXBRIDGE_DIR{}={}",
+                i,
+                exported_dir.to_string_lossy(),
+            );
         }
     }
 }
 
 pub fn direct_dependencies() -> Vec<Crate> {
     let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
+    let mut exported_header_dirs: BTreeMap<String, Vec<(usize, PathBuf)>> = BTreeMap::new();
 
     // Only variables set from a build script of direct dependencies are
     // observable. That's exactly what we want! Your crate needs to declare a
@@ -64,17 +68,29 @@ pub fn direct_dependencies() -> Vec<Crate> {
             continue;
         }
 
-        if k.ends_with("_CXXBRIDGE_CRATE") {
-            k.truncate(k.len() - "_CXXBRIDGE_CRATE".len());
-            crates.entry(k).or_default().crate_dir = Some(PathBuf::from(v));
+        let without_counter = k.trim_end_matches(|ch: char| ch.is_ascii_digit());
+        let counter_len = k.len() - without_counter.len();
+        if counter_len == 0 || !without_counter.ends_with("_CXXBRIDGE_DIR") {
             continue;
         }
 
-        if k.ends_with("_CXXBRIDGE_INCLUDE") {
-            k.truncate(k.len() - "_CXXBRIDGE_INCLUDE".len());
-            crates.entry(k).or_default().include_dir = Some(PathBuf::from(v));
-            continue;
-        }
+        let sort_key = k[k.len() - counter_len..]
+            .parse::<usize>()
+            .unwrap_or(usize::MAX);
+        k.truncate(k.len() - counter_len - "_CXXBRIDGE_DIR".len());
+        exported_header_dirs
+            .entry(k)
+            .or_default()
+            .push((sort_key, PathBuf::from(v)));
+    }
+
+    for (k, mut dirs) in exported_header_dirs {
+        dirs.sort_by_key(|(sort_key, _dir)| *sort_key);
+        crates
+            .entry(k)
+            .or_default()
+            .exported_header_dirs
+            .extend(dirs.into_iter().map(|(_sort_key, dir)| dir));
     }
 
     crates.into_iter().map(|entry| entry.1).collect()
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 2ec45e0..7bfc3e7 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -180,12 +180,18 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
-    let this_crate = Crate {
+    let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
         links: env::var_os("CARGO_MANIFEST_LINKS"),
-        crate_dir,
-        include_dir: Some(include_dir),
+        exported_header_dirs: Vec::new(),
     };
+
+    // The generated code directory (include_dir) is placed in front of
+    // crate_dir on the include line so that `#include "path/to/file.rs"` from
+    // C++ "magically" works and refers to the API generated from that Rust
+    // source file.
+    this_crate.exported_header_dirs.push(include_dir);
+    this_crate.exported_header_dirs.extend(crate_dir);
     this_crate.print_to_cargo();
 
     let mut build = Build::new();
@@ -201,17 +207,9 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     eprintln!("\nCXX include path:");
     for krate in crates {
-        if let Some(include_dir) = &krate.include_dir {
-            build.include(include_dir);
-            eprintln!("  {}", include_dir.display());
-        }
-        if let Some(crate_dir) = &krate.crate_dir {
-            // Placed after the generated code directory (include_dir) on the
-            // include line so that `#include "path/to/file.rs"` from C++
-            // "magically" works and refers to the API generated from that Rust
-            // source file.
-            build.include(crate_dir);
-            eprintln!("  {}", crate_dir.display());
+        for header_dir in &krate.exported_header_dirs {
+            build.include(header_dir);
+            eprintln!("  {}", header_dir.display());
         }
     }
 

From 93fbc099cc9e1b25b9d0ef40b7c2a4046cbdd4c8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:40:36 +0000
Subject: [PATCH 1279/2232] Implement CFG.exported_header_dirs


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 7bfc3e7..60797a5 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -192,6 +192,11 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     // source file.
     this_crate.exported_header_dirs.push(include_dir);
     this_crate.exported_header_dirs.extend(crate_dir);
+    for exported_dir in &CFG.exported_header_dirs {
+        this_crate
+            .exported_header_dirs
+            .push(PathBuf::from(exported_dir));
+    }
     this_crate.print_to_cargo();
 
     let mut build = Build::new();

From 82294ccbd582df3166a94a71aee503fdb5bc003a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:41:55 +0000
Subject: [PATCH 1280/2232] Detect non-absolute exported header dirs


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 2fbd41d..069723b 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -2,6 +2,7 @@ use crate::gen::fs;
 use std::error::Error as StdError;
 use std::ffi::OsString;
 use std::fmt::{self, Display};
+use std::path::Path;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
@@ -9,6 +10,7 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 pub(super) enum Error {
     NoEnv(OsString),
     Fs(fs::Error),
+    ExportedDirNotAbsolute(&'static Path),
 }
 
 impl Display for Error {
@@ -18,6 +20,11 @@ impl Display for Error {
                 write!(f, "missing {} environment variable", var.to_string_lossy())
             }
             Error::Fs(err) => err.fmt(f),
+            Error::ExportedDirNotAbsolute(path) => write!(
+                f,
+                "element of CFG.exported_header_dirs must be absolute path, but was: {:?}",
+                path,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 60797a5..d5588b1 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -193,6 +193,9 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     this_crate.exported_header_dirs.push(include_dir);
     this_crate.exported_header_dirs.extend(crate_dir);
     for exported_dir in &CFG.exported_header_dirs {
+        if !exported_dir.is_absolute() {
+            return Err(Error::ExportedDirNotAbsolute(exported_dir));
+        }
         this_crate
             .exported_header_dirs
             .push(PathBuf::from(exported_dir));

From b31e8edd6576023fa9d6dab04bb788811902fad1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 21:52:10 +0000
Subject: [PATCH 1281/2232] Merge pull request #421 from dtolnay/dirs


Implement CFG.exported_header_dirs
---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 2fbd41d..069723b 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -2,6 +2,7 @@ use crate::gen::fs;
 use std::error::Error as StdError;
 use std::ffi::OsString;
 use std::fmt::{self, Display};
+use std::path::Path;
 
 pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 
@@ -9,6 +10,7 @@ pub(super) type Result<T, E = Error> = std::result::Result<T, E>;
 pub(super) enum Error {
     NoEnv(OsString),
     Fs(fs::Error),
+    ExportedDirNotAbsolute(&'static Path),
 }
 
 impl Display for Error {
@@ -18,6 +20,11 @@ impl Display for Error {
                 write!(f, "missing {} environment variable", var.to_string_lossy())
             }
             Error::Fs(err) => err.fmt(f),
+            Error::ExportedDirNotAbsolute(path) => write!(
+                f,
+                "element of CFG.exported_header_dirs must be absolute path, but was: {:?}",
+                path,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 7bfc3e7..d5588b1 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -192,6 +192,14 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     // source file.
     this_crate.exported_header_dirs.push(include_dir);
     this_crate.exported_header_dirs.extend(crate_dir);
+    for exported_dir in &CFG.exported_header_dirs {
+        if !exported_dir.is_absolute() {
+            return Err(Error::ExportedDirNotAbsolute(exported_dir));
+        }
+        this_crate
+            .exported_header_dirs
+            .push(PathBuf::from(exported_dir));
+    }
     this_crate.print_to_cargo();
 
     let mut build = Build::new();

From 737502e4bdd1df8e5bf094e208bd770746e72c5c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:00:46 +0000
Subject: [PATCH 1282/2232] Track visibility of exported headers


---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 4e34835..fb80072 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -7,7 +7,12 @@ use std::path::PathBuf;
 pub struct Crate {
     pub include_prefix: Option<PathBuf>,
     pub links: Option<OsString>,
-    pub exported_header_dirs: Vec<PathBuf>,
+    pub header_dirs: Vec<HeaderDir>,
+}
+
+pub struct HeaderDir {
+    pub exported: bool,
+    pub path: PathBuf,
 }
 
 impl Crate {
@@ -21,12 +26,14 @@ impl Crate {
         if let Some(links) = &self.links {
             println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
         }
-        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
-            println!(
-                "cargo:CXXBRIDGE_DIR{}={}",
-                i,
-                exported_dir.to_string_lossy(),
-            );
+        for (i, header_dir) in self.header_dirs.iter().enumerate() {
+            if header_dir.exported {
+                println!(
+                    "cargo:CXXBRIDGE_DIR{}={}",
+                    i,
+                    header_dir.path.to_string_lossy(),
+                );
+            }
         }
     }
 }
@@ -89,8 +96,11 @@ pub fn direct_dependencies() -> Vec<Crate> {
         crates
             .entry(k)
             .or_default()
-            .exported_header_dirs
-            .extend(dirs.into_iter().map(|(_sort_key, dir)| dir));
+            .header_dirs
+            .extend(dirs.into_iter().map(|(_sort_key, dir)| HeaderDir {
+                exported: true,
+                path: dir,
+            }));
     }
 
     crates.into_iter().map(|entry| entry.1).collect()
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index d5588b1..df2ffad 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -65,7 +65,7 @@ mod syntax;
 mod target;
 mod vec;
 
-use crate::deps::Crate;
+use crate::deps::{Crate, HeaderDir};
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
@@ -183,22 +183,31 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
         links: env::var_os("CARGO_MANIFEST_LINKS"),
-        exported_header_dirs: Vec::new(),
+        header_dirs: Vec::new(),
     };
 
     // The generated code directory (include_dir) is placed in front of
     // crate_dir on the include line so that `#include "path/to/file.rs"` from
     // C++ "magically" works and refers to the API generated from that Rust
     // source file.
-    this_crate.exported_header_dirs.push(include_dir);
-    this_crate.exported_header_dirs.extend(crate_dir);
+    this_crate.header_dirs.push(HeaderDir {
+        exported: true,
+        path: include_dir,
+    });
+    if let Some(crate_dir) = crate_dir {
+        this_crate.header_dirs.push(HeaderDir {
+            exported: true,
+            path: crate_dir,
+        });
+    }
     for exported_dir in &CFG.exported_header_dirs {
         if !exported_dir.is_absolute() {
             return Err(Error::ExportedDirNotAbsolute(exported_dir));
         }
-        this_crate
-            .exported_header_dirs
-            .push(PathBuf::from(exported_dir));
+        this_crate.header_dirs.push(HeaderDir {
+            exported: true,
+            path: PathBuf::from(exported_dir),
+        });
     }
     this_crate.print_to_cargo();
 
@@ -215,9 +224,9 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     eprintln!("\nCXX include path:");
     for krate in crates {
-        for header_dir in &krate.exported_header_dirs {
-            build.include(header_dir);
-            eprintln!("  {}", header_dir.display());
+        for header_dir in &krate.header_dirs {
+            build.include(&header_dir.path);
+            eprintln!("  {}", header_dir.path.display());
         }
     }
 

From 9b02aa09d8a64106aee2bda59dc5ea854d2dbf02 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:01:11 +0000
Subject: [PATCH 1283/2232] Distinguish exported vs private header dirs in logging


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index df2ffad..783eb04 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -226,7 +226,11 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     for krate in crates {
         for header_dir in &krate.header_dirs {
             build.include(&header_dir.path);
-            eprintln!("  {}", header_dir.path.display());
+            if header_dir.exported {
+                eprintln!("  {}", header_dir.path.display());
+            } else {
+                eprintln!("  {} (private)", header_dir.path.display());
+            }
         }
     }
 

From 9554c82cef234c8540fe8e86b8d922c07d2a53f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:21:25 +0000
Subject: [PATCH 1284/2232] Merge pull request #422 from dtolnay/exported


Track visibility of exported headers
---

diff --git a/gen/build/src/deps.rs b/gen/build/src/deps.rs
index 4e34835..fb80072 100644
--- a/gen/build/src/deps.rs
+++ b/gen/build/src/deps.rs
@@ -7,7 +7,12 @@ use std::path::PathBuf;
 pub struct Crate {
     pub include_prefix: Option<PathBuf>,
     pub links: Option<OsString>,
-    pub exported_header_dirs: Vec<PathBuf>,
+    pub header_dirs: Vec<HeaderDir>,
+}
+
+pub struct HeaderDir {
+    pub exported: bool,
+    pub path: PathBuf,
 }
 
 impl Crate {
@@ -21,12 +26,14 @@ impl Crate {
         if let Some(links) = &self.links {
             println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
         }
-        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
-            println!(
-                "cargo:CXXBRIDGE_DIR{}={}",
-                i,
-                exported_dir.to_string_lossy(),
-            );
+        for (i, header_dir) in self.header_dirs.iter().enumerate() {
+            if header_dir.exported {
+                println!(
+                    "cargo:CXXBRIDGE_DIR{}={}",
+                    i,
+                    header_dir.path.to_string_lossy(),
+                );
+            }
         }
     }
 }
@@ -89,8 +96,11 @@ pub fn direct_dependencies() -> Vec<Crate> {
         crates
             .entry(k)
             .or_default()
-            .exported_header_dirs
-            .extend(dirs.into_iter().map(|(_sort_key, dir)| dir));
+            .header_dirs
+            .extend(dirs.into_iter().map(|(_sort_key, dir)| HeaderDir {
+                exported: true,
+                path: dir,
+            }));
     }
 
     crates.into_iter().map(|entry| entry.1).collect()
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index d5588b1..783eb04 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -65,7 +65,7 @@ mod syntax;
 mod target;
 mod vec;
 
-use crate::deps::Crate;
+use crate::deps::{Crate, HeaderDir};
 use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
@@ -183,22 +183,31 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
         links: env::var_os("CARGO_MANIFEST_LINKS"),
-        exported_header_dirs: Vec::new(),
+        header_dirs: Vec::new(),
     };
 
     // The generated code directory (include_dir) is placed in front of
     // crate_dir on the include line so that `#include "path/to/file.rs"` from
     // C++ "magically" works and refers to the API generated from that Rust
     // source file.
-    this_crate.exported_header_dirs.push(include_dir);
-    this_crate.exported_header_dirs.extend(crate_dir);
+    this_crate.header_dirs.push(HeaderDir {
+        exported: true,
+        path: include_dir,
+    });
+    if let Some(crate_dir) = crate_dir {
+        this_crate.header_dirs.push(HeaderDir {
+            exported: true,
+            path: crate_dir,
+        });
+    }
     for exported_dir in &CFG.exported_header_dirs {
         if !exported_dir.is_absolute() {
             return Err(Error::ExportedDirNotAbsolute(exported_dir));
         }
-        this_crate
-            .exported_header_dirs
-            .push(PathBuf::from(exported_dir));
+        this_crate.header_dirs.push(HeaderDir {
+            exported: true,
+            path: PathBuf::from(exported_dir),
+        });
     }
     this_crate.print_to_cargo();
 
@@ -215,9 +224,13 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
 
     eprintln!("\nCXX include path:");
     for krate in crates {
-        for header_dir in &krate.exported_header_dirs {
-            build.include(header_dir);
-            eprintln!("  {}", header_dir.display());
+        for header_dir in &krate.header_dirs {
+            build.include(&header_dir.path);
+            if header_dir.exported {
+                eprintln!("  {}", header_dir.path.display());
+            } else {
+                eprintln!("  {} (private)", header_dir.path.display());
+            }
         }
     }
 

From 887d4d05a069313e5f7c96ef2887d7ce58876994 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:21:36 +0000
Subject: [PATCH 1285/2232] Implement CFG.exported_header_links


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index deca600..8ee96cb 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -188,18 +188,13 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
-    let mut crates = deps::direct_dependencies();
-    crates.insert(0, this_crate);
-
     eprintln!("\nCXX include path:");
-    for krate in crates {
-        for header_dir in &krate.header_dirs {
-            build.include(&header_dir.path);
-            if header_dir.exported {
-                eprintln!("  {}", header_dir.path.display());
-            } else {
-                eprintln!("  {} (private)", header_dir.path.display());
-            }
+    for header_dir in this_crate.header_dirs {
+        build.include(&header_dir.path);
+        if header_dir.exported {
+            eprintln!("  {}", header_dir.path.display());
+        } else {
+            eprintln!("  {} (private)", header_dir.path.display());
         }
     }
 
@@ -242,6 +237,25 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         });
     }
 
+    for krate in deps::direct_dependencies() {
+        let links_attribute = match krate.links {
+            Some(links) => links,
+            None => continue,
+        };
+
+        let exported = CFG
+            .exported_header_links
+            .iter()
+            .any(|exported| links_attribute == *exported);
+
+        this_crate
+            .header_dirs
+            .extend(krate.header_dirs.into_iter().map(|dir| HeaderDir {
+                exported,
+                path: dir.path,
+            }));
+    }
+
     Ok(this_crate)
 }
 

From 53ea91c98fef614f047e1903b34fcd2a65533c0b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:21:36 +0000
Subject: [PATCH 1286/2232] Factor out this_crate initialization


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 783eb04..deca600 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -177,9 +177,39 @@ impl Project {
 // on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
     let ref prj = Project::init()?;
+    let this_crate = make_this_crate(prj)?;
+    this_crate.print_to_cargo();
+
+    let mut build = Build::new();
+    build.cpp(true);
+    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
+
+    for path in rust_source_files {
+        generate_bridge(prj, &mut build, path.as_ref())?;
+    }
+
+    let mut crates = deps::direct_dependencies();
+    crates.insert(0, this_crate);
+
+    eprintln!("\nCXX include path:");
+    for krate in crates {
+        for header_dir in &krate.header_dirs {
+            build.include(&header_dir.path);
+            if header_dir.exported {
+                eprintln!("  {}", header_dir.path.display());
+            } else {
+                eprintln!("  {} (private)", header_dir.path.display());
+            }
+        }
+    }
 
+    Ok(build)
+}
+
+fn make_this_crate(prj: &Project) -> Result<Crate> {
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
+
     let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
         links: env::var_os("CARGO_MANIFEST_LINKS"),
@@ -194,12 +224,14 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         exported: true,
         path: include_dir,
     });
+
     if let Some(crate_dir) = crate_dir {
         this_crate.header_dirs.push(HeaderDir {
             exported: true,
             path: crate_dir,
         });
     }
+
     for exported_dir in &CFG.exported_header_dirs {
         if !exported_dir.is_absolute() {
             return Err(Error::ExportedDirNotAbsolute(exported_dir));
@@ -209,32 +241,8 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
             path: PathBuf::from(exported_dir),
         });
     }
-    this_crate.print_to_cargo();
-
-    let mut build = Build::new();
-    build.cpp(true);
-    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
-
-    for path in rust_source_files {
-        generate_bridge(prj, &mut build, path.as_ref())?;
-    }
-
-    let mut crates = deps::direct_dependencies();
-    crates.insert(0, this_crate);
 
-    eprintln!("\nCXX include path:");
-    for krate in crates {
-        for header_dir in &krate.header_dirs {
-            build.include(&header_dir.path);
-            if header_dir.exported {
-                eprintln!("  {}", header_dir.path.display());
-            } else {
-                eprintln!("  {} (private)", header_dir.path.display());
-            }
-        }
-    }
-
-    Ok(build)
+    Ok(this_crate)
 }
 
 fn make_crate_dir(prj: &Project) -> Option<PathBuf> {

From 8af4914f6b2bdf7df3a5b75cfd1b5cfaf2502f6b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:32:01 +0000
Subject: [PATCH 1287/2232] Merge pull request #423 from dtolnay/links


Implement CFG.exported_header_links
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index deca600..8ee96cb 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -188,18 +188,13 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
-    let mut crates = deps::direct_dependencies();
-    crates.insert(0, this_crate);
-
     eprintln!("\nCXX include path:");
-    for krate in crates {
-        for header_dir in &krate.header_dirs {
-            build.include(&header_dir.path);
-            if header_dir.exported {
-                eprintln!("  {}", header_dir.path.display());
-            } else {
-                eprintln!("  {} (private)", header_dir.path.display());
-            }
+    for header_dir in this_crate.header_dirs {
+        build.include(&header_dir.path);
+        if header_dir.exported {
+            eprintln!("  {}", header_dir.path.display());
+        } else {
+            eprintln!("  {} (private)", header_dir.path.display());
         }
     }
 
@@ -242,6 +237,25 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         });
     }
 
+    for krate in deps::direct_dependencies() {
+        let links_attribute = match krate.links {
+            Some(links) => links,
+            None => continue,
+        };
+
+        let exported = CFG
+            .exported_header_links
+            .iter()
+            .any(|exported| links_attribute == *exported);
+
+        this_crate
+            .header_dirs
+            .extend(krate.header_dirs.into_iter().map(|dir| HeaderDir {
+                exported,
+                path: dir.path,
+            }));
+    }
+
     Ok(this_crate)
 }
 

From d5bd218813becac61b79115a50e037bd285fa06e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:37:47 +0000
Subject: [PATCH 1288/2232] Arrange exported_header_links handling to make room for exported_header_prefixes


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8ee96cb..d302ba0 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -238,15 +238,15 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     }
 
     for krate in deps::direct_dependencies() {
-        let links_attribute = match krate.links {
-            Some(links) => links,
-            None => continue,
+        let is_link_exported = || match &krate.links {
+            None => false,
+            Some(links_attribute) => CFG
+                .exported_header_links
+                .iter()
+                .any(|exported| links_attribute == *exported),
         };
 
-        let exported = CFG
-            .exported_header_links
-            .iter()
-            .any(|exported| links_attribute == *exported);
+        let exported = is_link_exported();
 
         this_crate
             .header_dirs

From 4697ed0e558085993c6d090ec42c0741e93e5335 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:38:53 +0000
Subject: [PATCH 1289/2232] Implement CFG.exported_header_prefixes


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index d302ba0..21e4ea8 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -246,7 +246,15 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
                 .any(|exported| links_attribute == *exported),
         };
 
-        let exported = is_link_exported();
+        let is_prefix_exported = || match &krate.include_prefix {
+            None => false,
+            Some(include_prefix) => CFG
+                .exported_header_prefixes
+                .iter()
+                .any(|exported| include_prefix.starts_with(exported)),
+        };
+
+        let exported = is_link_exported() || is_prefix_exported();
 
         this_crate
             .header_dirs

From 40b79a03b3c4caff8f63d438cb2a3e687a7cd3f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:46:22 +0000
Subject: [PATCH 1290/2232] Merge pull request #424 from dtolnay/prefixes


Implement CFG.exported_header_prefixes
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8ee96cb..21e4ea8 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -238,15 +238,23 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     }
 
     for krate in deps::direct_dependencies() {
-        let links_attribute = match krate.links {
-            Some(links) => links,
-            None => continue,
+        let is_link_exported = || match &krate.links {
+            None => false,
+            Some(links_attribute) => CFG
+                .exported_header_links
+                .iter()
+                .any(|exported| links_attribute == *exported),
         };
 
-        let exported = CFG
-            .exported_header_links
-            .iter()
-            .any(|exported| links_attribute == *exported);
+        let is_prefix_exported = || match &krate.include_prefix {
+            None => false,
+            Some(include_prefix) => CFG
+                .exported_header_prefixes
+                .iter()
+                .any(|exported| include_prefix.starts_with(exported)),
+        };
+
+        let exported = is_link_exported() || is_prefix_exported();
 
         this_crate
             .header_dirs

From 225ea21a23ff3a7fb3fec7d7f14445c0220f2fdf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:49:10 +0000
Subject: [PATCH 1291/2232] Validate cfg


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 069723b..877a973 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -11,6 +11,7 @@ pub(super) enum Error {
     NoEnv(OsString),
     Fs(fs::Error),
     ExportedDirNotAbsolute(&'static Path),
+    ExportedEmptyPrefix,
 }
 
 impl Display for Error {
@@ -25,6 +26,9 @@ impl Display for Error {
                 "element of CFG.exported_header_dirs must be absolute path, but was: {:?}",
                 path,
             ),
+            Error::ExportedEmptyPrefix => {
+                f.write_str("element of CFG.exported_header_prefixes must not be empty string")
+            }
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 21e4ea8..066b458 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -176,6 +176,8 @@ impl Project {
 // current build as well as for downstream builds that have a direct dependency
 // on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
+    validate_cfg()?;
+
     let ref prj = Project::init()?;
     let this_crate = make_this_crate(prj)?;
     this_crate.print_to_cargo();
@@ -201,6 +203,22 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     Ok(build)
 }
 
+fn validate_cfg() -> Result<()> {
+    for exported_dir in &CFG.exported_header_dirs {
+        if !exported_dir.is_absolute() {
+            return Err(Error::ExportedDirNotAbsolute(exported_dir));
+        }
+    }
+
+    for prefix in &CFG.exported_header_prefixes {
+        if prefix.is_empty() {
+            return Err(Error::ExportedEmptyPrefix);
+        }
+    }
+
+    Ok(())
+}
+
 fn make_this_crate(prj: &Project) -> Result<Crate> {
     let crate_dir = make_crate_dir(prj);
     let include_dir = make_include_dir(prj)?;
@@ -228,9 +246,6 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     }
 
     for exported_dir in &CFG.exported_header_dirs {
-        if !exported_dir.is_absolute() {
-            return Err(Error::ExportedDirNotAbsolute(exported_dir));
-        }
         this_crate.header_dirs.push(HeaderDir {
             exported: true,
             path: PathBuf::from(exported_dir),

From 2558c740b756e31a5e20ad797131402e8683ac23 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 22:52:41 +0000
Subject: [PATCH 1292/2232] Ensure error messages remain in sync with CFG


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 877a973..260116f 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -1,3 +1,4 @@
+use crate::cfg::CFG;
 use crate::gen::fs;
 use std::error::Error as StdError;
 use std::ffi::OsString;
@@ -14,6 +15,13 @@ pub(super) enum Error {
     ExportedEmptyPrefix,
 }
 
+macro_rules! expr {
+    ($expr:expr) => {{
+        let _ = $expr; // ensure it doesn't fall out of sync with CFG definition
+        stringify!($expr)
+    }};
+}
+
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
@@ -23,12 +31,15 @@ impl Display for Error {
             Error::Fs(err) => err.fmt(f),
             Error::ExportedDirNotAbsolute(path) => write!(
                 f,
-                "element of CFG.exported_header_dirs must be absolute path, but was: {:?}",
+                "element of {} must be absolute path, but was: {:?}",
+                expr!(CFG.exported_header_dirs),
                 path,
             ),
-            Error::ExportedEmptyPrefix => {
-                f.write_str("element of CFG.exported_header_prefixes must not be empty string")
-            }
+            Error::ExportedEmptyPrefix => write!(
+                f,
+                "element of {} must not be empty string",
+                expr!(CFG.exported_header_prefixes),
+            ),
         }
     }
 }

From 6fb0d22357caae5695c7fd0414d6db8ab25e6a53 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 05 2020 23:49:49 +0000
Subject: [PATCH 1293/2232] Deduplicate dirs reachable via multiple transitive dependencies


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 066b458..8097dec 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -72,6 +72,7 @@ use crate::gen::Opt;
 use crate::paths::PathExt;
 use crate::target::TargetDir;
 use cc::Build;
+use std::collections::btree_map::{BTreeMap, Entry};
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -252,6 +253,7 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         });
     }
 
+    let mut header_dirs_index = BTreeMap::new();
     for krate in deps::direct_dependencies() {
         let is_link_exported = || match &krate.links {
             None => false,
@@ -271,12 +273,22 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
 
         let exported = is_link_exported() || is_prefix_exported();
 
-        this_crate
-            .header_dirs
-            .extend(krate.header_dirs.into_iter().map(|dir| HeaderDir {
-                exported,
-                path: dir.path,
-            }));
+        for dir in krate.header_dirs {
+            // Deduplicate dirs reachable via multiple transitive dependencies.
+            match header_dirs_index.entry(dir.path.clone()) {
+                Entry::Vacant(entry) => {
+                    entry.insert(this_crate.header_dirs.len());
+                    this_crate.header_dirs.push(HeaderDir {
+                        exported,
+                        path: dir.path,
+                    });
+                }
+                Entry::Occupied(entry) => {
+                    let index = *entry.get();
+                    this_crate.header_dirs[index].exported |= exported;
+                }
+            }
+        }
     }
 
     Ok(this_crate)

From 6b064c4cb54e6a923a8189e3b6d357722d1e1549 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 00:19:18 +0000
Subject: [PATCH 1294/2232] Merge pull request #425 from dtolnay/dirs


Deduplicate dirs reachable via multiple transitive dependencies
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 066b458..8097dec 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -72,6 +72,7 @@ use crate::gen::Opt;
 use crate::paths::PathExt;
 use crate::target::TargetDir;
 use cc::Build;
+use std::collections::btree_map::{BTreeMap, Entry};
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -252,6 +253,7 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         });
     }
 
+    let mut header_dirs_index = BTreeMap::new();
     for krate in deps::direct_dependencies() {
         let is_link_exported = || match &krate.links {
             None => false,
@@ -271,12 +273,22 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
 
         let exported = is_link_exported() || is_prefix_exported();
 
-        this_crate
-            .header_dirs
-            .extend(krate.header_dirs.into_iter().map(|dir| HeaderDir {
-                exported,
-                path: dir.path,
-            }));
+        for dir in krate.header_dirs {
+            // Deduplicate dirs reachable via multiple transitive dependencies.
+            match header_dirs_index.entry(dir.path.clone()) {
+                Entry::Vacant(entry) => {
+                    entry.insert(this_crate.header_dirs.len());
+                    this_crate.header_dirs.push(HeaderDir {
+                        exported,
+                        path: dir.path,
+                    });
+                }
+                Entry::Occupied(entry) => {
+                    let index = *entry.get();
+                    this_crate.header_dirs[index].exported |= exported;
+                }
+            }
+        }
     }
 
     Ok(this_crate)

From ec4fda08a8994d41403b83991d8654dd721e256e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 00:55:27 +0000
Subject: [PATCH 1295/2232] Store Cargo links attribute with Project


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8097dec..81b7690 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -114,6 +114,8 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 struct Project {
     include_prefix: PathBuf,
     manifest_dir: PathBuf,
+    // The `links = "..."` value from Cargo.toml.
+    links_attribute: Option<OsString>,
     // Output directory as received from Cargo.
     out_dir: PathBuf,
     // Directory into which to symlink all generated code.
@@ -137,6 +139,8 @@ impl Project {
         assert!(include_prefix.is_relative());
         let include_prefix = include_prefix.components().collect();
 
+        let links_attribute = env::var_os("CARGO_MANIFEST_LINKS");
+
         let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
@@ -148,6 +152,7 @@ impl Project {
         Ok(Project {
             include_prefix,
             manifest_dir,
+            links_attribute,
             out_dir,
             shared_dir,
         })
@@ -226,7 +231,7 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
 
     let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
-        links: env::var_os("CARGO_MANIFEST_LINKS"),
+        links: prj.links_attribute.clone(),
         header_dirs: Vec::new(),
     };
 

From f27369608c98a561735c458da09fc5eed384c201 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 01:02:21 +0000
Subject: [PATCH 1296/2232] Validate that `links` attribute is set if exporting headers


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 260116f..5306564 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -13,6 +13,9 @@ pub(super) enum Error {
     Fs(fs::Error),
     ExportedDirNotAbsolute(&'static Path),
     ExportedEmptyPrefix,
+    ExportedDirsWithoutLinks,
+    ExportedPrefixesWithoutLinks,
+    ExportedLinksWithoutLinks,
 }
 
 macro_rules! expr {
@@ -22,6 +25,9 @@ macro_rules! expr {
     }};
 }
 
+const LINKS_DOCUMENTATION: &str =
+    "https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key";
+
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
@@ -40,6 +46,24 @@ impl Display for Error {
                 "element of {} must not be empty string",
                 expr!(CFG.exported_header_prefixes),
             ),
+            Error::ExportedDirsWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_dirs),
+                LINKS_DOCUMENTATION,
+            ),
+            Error::ExportedPrefixesWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_prefixes),
+                LINKS_DOCUMENTATION,
+            ),
+            Error::ExportedLinksWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_links),
+                LINKS_DOCUMENTATION,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 81b7690..b0df283 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -182,9 +182,8 @@ impl Project {
 // current build as well as for downstream builds that have a direct dependency
 // on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    validate_cfg()?;
-
     let ref prj = Project::init()?;
+    validate_cfg(prj)?;
     let this_crate = make_this_crate(prj)?;
     this_crate.print_to_cargo();
 
@@ -209,7 +208,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     Ok(build)
 }
 
-fn validate_cfg() -> Result<()> {
+fn validate_cfg(prj: &Project) -> Result<()> {
     for exported_dir in &CFG.exported_header_dirs {
         if !exported_dir.is_absolute() {
             return Err(Error::ExportedDirNotAbsolute(exported_dir));
@@ -222,6 +221,18 @@ fn validate_cfg() -> Result<()> {
         }
     }
 
+    if prj.links_attribute.is_none() {
+        if !CFG.exported_header_dirs.is_empty() {
+            return Err(Error::ExportedDirsWithoutLinks);
+        }
+        if !CFG.exported_header_prefixes.is_empty() {
+            return Err(Error::ExportedPrefixesWithoutLinks);
+        }
+        if !CFG.exported_header_links.is_empty() {
+            return Err(Error::ExportedLinksWithoutLinks);
+        }
+    }
+
     Ok(())
 }
 

From 8cb82377f8975d0528367701cce0b5c9fbdd3e0e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 01:11:38 +0000
Subject: [PATCH 1297/2232] Merge pull request #426 from dtolnay/validate


Validate that `links` attribute is set if exporting headers
---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 260116f..5306564 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -13,6 +13,9 @@ pub(super) enum Error {
     Fs(fs::Error),
     ExportedDirNotAbsolute(&'static Path),
     ExportedEmptyPrefix,
+    ExportedDirsWithoutLinks,
+    ExportedPrefixesWithoutLinks,
+    ExportedLinksWithoutLinks,
 }
 
 macro_rules! expr {
@@ -22,6 +25,9 @@ macro_rules! expr {
     }};
 }
 
+const LINKS_DOCUMENTATION: &str =
+    "https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key";
+
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
@@ -40,6 +46,24 @@ impl Display for Error {
                 "element of {} must not be empty string",
                 expr!(CFG.exported_header_prefixes),
             ),
+            Error::ExportedDirsWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_dirs),
+                LINKS_DOCUMENTATION,
+            ),
+            Error::ExportedPrefixesWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_prefixes),
+                LINKS_DOCUMENTATION,
+            ),
+            Error::ExportedLinksWithoutLinks => write!(
+                f,
+                "if {} is nonempty then `links` needs to be set in Cargo.toml; see {}",
+                expr!(CFG.exported_header_links),
+                LINKS_DOCUMENTATION,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 8097dec..b0df283 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -114,6 +114,8 @@ pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) ->
 struct Project {
     include_prefix: PathBuf,
     manifest_dir: PathBuf,
+    // The `links = "..."` value from Cargo.toml.
+    links_attribute: Option<OsString>,
     // Output directory as received from Cargo.
     out_dir: PathBuf,
     // Directory into which to symlink all generated code.
@@ -137,6 +139,8 @@ impl Project {
         assert!(include_prefix.is_relative());
         let include_prefix = include_prefix.components().collect();
 
+        let links_attribute = env::var_os("CARGO_MANIFEST_LINKS");
+
         let manifest_dir = paths::manifest_dir()?;
         let out_dir = paths::out_dir()?;
 
@@ -148,6 +152,7 @@ impl Project {
         Ok(Project {
             include_prefix,
             manifest_dir,
+            links_attribute,
             out_dir,
             shared_dir,
         })
@@ -177,9 +182,8 @@ impl Project {
 // current build as well as for downstream builds that have a direct dependency
 // on the current crate.
 fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
-    validate_cfg()?;
-
     let ref prj = Project::init()?;
+    validate_cfg(prj)?;
     let this_crate = make_this_crate(prj)?;
     this_crate.print_to_cargo();
 
@@ -204,7 +208,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     Ok(build)
 }
 
-fn validate_cfg() -> Result<()> {
+fn validate_cfg(prj: &Project) -> Result<()> {
     for exported_dir in &CFG.exported_header_dirs {
         if !exported_dir.is_absolute() {
             return Err(Error::ExportedDirNotAbsolute(exported_dir));
@@ -217,6 +221,18 @@ fn validate_cfg() -> Result<()> {
         }
     }
 
+    if prj.links_attribute.is_none() {
+        if !CFG.exported_header_dirs.is_empty() {
+            return Err(Error::ExportedDirsWithoutLinks);
+        }
+        if !CFG.exported_header_prefixes.is_empty() {
+            return Err(Error::ExportedPrefixesWithoutLinks);
+        }
+        if !CFG.exported_header_links.is_empty() {
+            return Err(Error::ExportedLinksWithoutLinks);
+        }
+    }
+
     Ok(())
 }
 
@@ -226,7 +242,7 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
 
     let mut this_crate = Crate {
         include_prefix: Some(prj.include_prefix.clone()),
-        links: env::var_os("CARGO_MANIFEST_LINKS"),
+        links: prj.links_attribute.clone(),
         header_dirs: Vec::new(),
     };
 

From 98830869882a110d38c47ec45ba1766d1fa2d35f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 01:23:47 +0000
Subject: [PATCH 1298/2232] Validate that all exported_header_prefixes/_links are used


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 5306564..e1cc345 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -16,6 +16,8 @@ pub(super) enum Error {
     ExportedDirsWithoutLinks,
     ExportedPrefixesWithoutLinks,
     ExportedLinksWithoutLinks,
+    UnusedExportedPrefix(&'static str),
+    UnusedExportedLinks(&'static str),
 }
 
 macro_rules! expr {
@@ -64,6 +66,18 @@ impl Display for Error {
                 expr!(CFG.exported_header_links),
                 LINKS_DOCUMENTATION,
             ),
+            Error::UnusedExportedPrefix(unused) => write!(
+                f,
+                "unused element in {}: {} does not match the include prefix of any direct dependency",
+                expr!(CFG.exported_header_prefixes),
+                unused,
+            ),
+            Error::UnusedExportedLinks(unused) => write!(
+                f,
+                "unused element in {}: {} does not match the `links` attribute any direct dependency",
+                expr!(CFG.exported_header_links),
+                unused,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b0df283..db15335 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -72,7 +72,8 @@ use crate::gen::Opt;
 use crate::paths::PathExt;
 use crate::target::TargetDir;
 use cc::Build;
-use std::collections::btree_map::{BTreeMap, Entry};
+use std::collections::btree_map::Entry;
+use std::collections::{BTreeMap, BTreeSet};
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -270,21 +271,29 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     }
 
     let mut header_dirs_index = BTreeMap::new();
+    let mut used_header_links = BTreeSet::new();
+    let mut used_header_prefixes = BTreeSet::new();
     for krate in deps::direct_dependencies() {
-        let is_link_exported = || match &krate.links {
+        let mut is_link_exported = || match &krate.links {
             None => false,
-            Some(links_attribute) => CFG
-                .exported_header_links
-                .iter()
-                .any(|exported| links_attribute == *exported),
+            Some(links_attribute) => CFG.exported_header_links.iter().any(|&exported| {
+                let matches = links_attribute == exported;
+                if matches {
+                    used_header_links.insert(exported);
+                }
+                matches
+            }),
         };
 
-        let is_prefix_exported = || match &krate.include_prefix {
+        let mut is_prefix_exported = || match &krate.include_prefix {
             None => false,
-            Some(include_prefix) => CFG
-                .exported_header_prefixes
-                .iter()
-                .any(|exported| include_prefix.starts_with(exported)),
+            Some(include_prefix) => CFG.exported_header_prefixes.iter().any(|&exported| {
+                let matches = include_prefix.starts_with(exported);
+                if matches {
+                    used_header_prefixes.insert(exported);
+                }
+                matches
+            }),
         };
 
         let exported = is_link_exported() || is_prefix_exported();
@@ -307,6 +316,22 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         }
     }
 
+    if let Some(unused) = CFG
+        .exported_header_links
+        .iter()
+        .find(|&exported| !used_header_links.contains(exported))
+    {
+        return Err(Error::UnusedExportedLinks(unused));
+    }
+
+    if let Some(unused) = CFG
+        .exported_header_prefixes
+        .iter()
+        .find(|&exported| !used_header_prefixes.contains(exported))
+    {
+        return Err(Error::UnusedExportedPrefix(unused));
+    }
+
     Ok(this_crate)
 }
 

From b419eed03986068ded991d370b5859ce09198531 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 01:32:58 +0000
Subject: [PATCH 1299/2232] Merge pull request #427 from dtolnay/unused


Validate that all exported_header_prefixes/_links are used
---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index 5306564..e1cc345 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -16,6 +16,8 @@ pub(super) enum Error {
     ExportedDirsWithoutLinks,
     ExportedPrefixesWithoutLinks,
     ExportedLinksWithoutLinks,
+    UnusedExportedPrefix(&'static str),
+    UnusedExportedLinks(&'static str),
 }
 
 macro_rules! expr {
@@ -64,6 +66,18 @@ impl Display for Error {
                 expr!(CFG.exported_header_links),
                 LINKS_DOCUMENTATION,
             ),
+            Error::UnusedExportedPrefix(unused) => write!(
+                f,
+                "unused element in {}: {} does not match the include prefix of any direct dependency",
+                expr!(CFG.exported_header_prefixes),
+                unused,
+            ),
+            Error::UnusedExportedLinks(unused) => write!(
+                f,
+                "unused element in {}: {} does not match the `links` attribute any direct dependency",
+                expr!(CFG.exported_header_links),
+                unused,
+            ),
         }
     }
 }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b0df283..db15335 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -72,7 +72,8 @@ use crate::gen::Opt;
 use crate::paths::PathExt;
 use crate::target::TargetDir;
 use cc::Build;
-use std::collections::btree_map::{BTreeMap, Entry};
+use std::collections::btree_map::Entry;
+use std::collections::{BTreeMap, BTreeSet};
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -270,21 +271,29 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     }
 
     let mut header_dirs_index = BTreeMap::new();
+    let mut used_header_links = BTreeSet::new();
+    let mut used_header_prefixes = BTreeSet::new();
     for krate in deps::direct_dependencies() {
-        let is_link_exported = || match &krate.links {
+        let mut is_link_exported = || match &krate.links {
             None => false,
-            Some(links_attribute) => CFG
-                .exported_header_links
-                .iter()
-                .any(|exported| links_attribute == *exported),
+            Some(links_attribute) => CFG.exported_header_links.iter().any(|&exported| {
+                let matches = links_attribute == exported;
+                if matches {
+                    used_header_links.insert(exported);
+                }
+                matches
+            }),
         };
 
-        let is_prefix_exported = || match &krate.include_prefix {
+        let mut is_prefix_exported = || match &krate.include_prefix {
             None => false,
-            Some(include_prefix) => CFG
-                .exported_header_prefixes
-                .iter()
-                .any(|exported| include_prefix.starts_with(exported)),
+            Some(include_prefix) => CFG.exported_header_prefixes.iter().any(|&exported| {
+                let matches = include_prefix.starts_with(exported);
+                if matches {
+                    used_header_prefixes.insert(exported);
+                }
+                matches
+            }),
         };
 
         let exported = is_link_exported() || is_prefix_exported();
@@ -307,6 +316,22 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         }
     }
 
+    if let Some(unused) = CFG
+        .exported_header_links
+        .iter()
+        .find(|&exported| !used_header_links.contains(exported))
+    {
+        return Err(Error::UnusedExportedLinks(unused));
+    }
+
+    if let Some(unused) = CFG
+        .exported_header_prefixes
+        .iter()
+        .find(|&exported| !used_header_prefixes.contains(exported))
+    {
+        return Err(Error::UnusedExportedPrefix(unused));
+    }
+
     Ok(this_crate)
 }
 

From 8249c83dc2f50a677d043c9ea961d77db7283d20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:01:19 +0000
Subject: [PATCH 1300/2232] Document CFG's exported header support


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 15949b5..737b047 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -21,6 +21,7 @@ syn = { version = "1.0.20", default-features = false, features = ["parsing", "pr
 
 [dev-dependencies]
 cxx-gen = { version = "0.6", path = "../lib" }
+pkg-config = "0.3"
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 00f9535..c0e8054 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -21,12 +21,11 @@ pub struct Cfg<'a> {
 ///
 /// ## **`CFG.include_prefix`**
 ///
-/// Presently the only exposed configuration is the `include_prefix`, the prefix
-/// at which C++ code from your crate as well as directly dependent crates can
-/// access the code generated during this build.
+/// The prefix at which C++ code from your crate as well as directly dependent
+/// crates can access the code generated during this build.
 ///
 /// By default, the `include_prefix` is equal to the name of the current crate.
-/// That means if our crate is called `demo` and has Rust source files in a
+/// That means if your crate is called `demo` and has Rust source files in a
 /// *src/* directory and maybe some handwritten C++ header files in an
 /// *include/* directory, then the current crate as well as downstream crates
 /// might include them as follows:
@@ -67,6 +66,164 @@ pub struct Cfg<'a> {
 /// Additionally, headers from a direct dependency are only importable if the
 /// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
 /// will not be importable from outside of the same crate.
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_dirs`**
+///
+/// A vector of absolute paths. The current crate, directly dependent crates,
+/// and further crates to which this crate's headers are exported (see below)
+/// will be able to `#include` headers from these directories.
+///
+/// Adding a directory to `exported_header_dirs` is similar to adding it to the
+/// current build via the `cc` crate's [`Build::include`][cc::Build::include],
+/// but *also* makes the directory available to downstream crates that want to
+/// `#include` one of the headers from your crate. If the dir were added only
+/// using `Build::include`, the downstream crate including your header would
+/// need to manually add the same directory to their own build as well.
+///
+/// When using `exported_header_dirs`, your crate must also set a `links` key
+/// for itself in Cargo.toml. See [*the `links` manifest key*][links]. The
+/// reason is that Cargo imposes no ordering on the execution of build scripts
+/// without a `links` key, which means the downstream crate's build script might
+/// execute before yours decides what to put into `exported_header_dirs`.
+///
+/// [links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+///
+/// ### Example
+///
+/// One of your crate's headers wants to include a system library, such as
+/// `#include "Python.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+/// use std::path::PathBuf;
+///
+/// fn main() {
+///     let python3 = pkg_config::probe_library("python3").unwrap();
+///     let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path);
+///     CFG.exported_header_dirs.extend(python_include_paths);
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
+///
+/// ### Example
+///
+/// Your crate wants to rearrange the headers that it exports vs how they're
+/// laid out locally inside the crate's source directory.
+///
+/// Suppose the crate as published contains a file at `./include/myheader.h` but
+/// wants it available to downstream crates as `#include "foo/v1/public.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+/// use std::path::Path;
+/// use std::{env, fs};
+///
+/// fn main() {
+///     let out_dir = env::var_os("OUT_DIR").unwrap();
+///     let headers = Path::new(&out_dir).join("headers");
+///     CFG.exported_header_dirs.push(&headers);
+///
+///     // We contain `include/myheader.h` locally, but
+///     // downstream will use `#include "foo/v1/public.h"`
+///     let foo = headers.join("foo").join("v1");
+///     fs::create_dir_all(&foo).unwrap();
+///     fs::copy("include/myheader.h", foo.join("public.h")).unwrap();
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_prefixes`**
+///
+/// Vector of strings. These each refer to the `include_prefix` of one of your
+/// direct dependencies, or a prefix thereof. They describe which of your
+/// dependencies participate in your crate's C++ public API, as opposed to
+/// private use by your crate's implementation.
+///
+/// As a general rule, if one of your headers `#include`s something from one of
+/// your dependencies, you need to put that dependency's `include_prefix` into
+/// `CFG.exported_header_prefixes` (*or* their `links` key into
+/// `CFG.exported_header_links`; see below). On the other hand if only your C++
+/// implementation files and *not* your headers are importing from the
+/// dependency, you do not export that dependency.
+///
+/// The significance of exported headers is that if downstream code (crate 𝒜)
+/// contains an `#include` of a header from your crate (ℬ) and your header
+/// contains an `#include` of something from your dependency (𝒞), the exported
+/// dependency 𝒞 becomes available during the downstream crate 𝒜's build.
+/// Otherwise the downstream crate 𝒜 doesn't know about 𝒞 and wouldn't be able
+/// to find what header your header is referring to, and would fail to build.
+///
+/// When using `exported_header_prefixes`, your crate must also set a `links`
+/// key for itself in Cargo.toml.
+///
+/// ### Example
+///
+/// Suppose you have a crate with 5 direct dependencies and the `include_prefix`
+/// for each one are:
+///
+/// - "crate0"
+/// - "group/api/crate1"
+/// - "group/api/crate2"
+/// - "group/api/contrib/crate3"
+/// - "detail/crate4"
+///
+/// Your header involves types from the first four so we re-export those as part
+/// of your public API, while crate4 is only used internally by your cc file not
+/// your header, so we do not export:
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.exported_header_prefixes = vec!["crate0", "group/api"];
+///
+///     cxx_build::bridge("src/bridge.rs")
+///         .file("src/impl.cc")
+///         .compile("demo");
+/// }
+/// ```
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_links`**
+///
+/// Vector of strings. These each refer to the `links` attribute ([*the `links`
+/// manifest key*][links]) of one of your crate's direct dependencies.
+///
+/// This achieves an equivalent result to `CFG.exported_header_prefixes` by
+/// re-exporting a dependency as part of your crate's public API, except with
+/// finer grained control for cases when multiple crates might be sharing the
+/// same `include_prefix` and you'd like to export some but not others. Links
+/// attributes are guaranteed to be unique identifiers by Cargo.
+///
+/// When using `exported_header_links`, your crate must also set a `links` key
+/// for itself in Cargo.toml.
+///
+/// ### Example
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.exported_header_links.push("git2");
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
 #[cfg(doc)]
 pub static mut CFG: Cfg = Cfg {
     include_prefix: "",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index bdfcc38..97d6937 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -80,6 +80,7 @@ dependencies = [
  "codespan-reporting",
  "cxx-gen",
  "lazy_static",
+ "pkg-config",
  "proc-macro2",
  "quote",
  "scratch",
@@ -188,6 +189,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "pkg-config"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From e4633a9310c2f7d211377ef458ff4497c99d7c49 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:06:28 +0000
Subject: [PATCH 1301/2232] Merge pull request #428 from dtolnay/doc


Document CFG's exported header support
---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 15949b5..737b047 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -21,6 +21,7 @@ syn = { version = "1.0.20", default-features = false, features = ["parsing", "pr
 
 [dev-dependencies]
 cxx-gen = { version = "0.6", path = "../lib" }
+pkg-config = "0.3"
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 00f9535..c0e8054 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -21,12 +21,11 @@ pub struct Cfg<'a> {
 ///
 /// ## **`CFG.include_prefix`**
 ///
-/// Presently the only exposed configuration is the `include_prefix`, the prefix
-/// at which C++ code from your crate as well as directly dependent crates can
-/// access the code generated during this build.
+/// The prefix at which C++ code from your crate as well as directly dependent
+/// crates can access the code generated during this build.
 ///
 /// By default, the `include_prefix` is equal to the name of the current crate.
-/// That means if our crate is called `demo` and has Rust source files in a
+/// That means if your crate is called `demo` and has Rust source files in a
 /// *src/* directory and maybe some handwritten C++ header files in an
 /// *include/* directory, then the current crate as well as downstream crates
 /// might include them as follows:
@@ -67,6 +66,164 @@ pub struct Cfg<'a> {
 /// Additionally, headers from a direct dependency are only importable if the
 /// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
 /// will not be importable from outside of the same crate.
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_dirs`**
+///
+/// A vector of absolute paths. The current crate, directly dependent crates,
+/// and further crates to which this crate's headers are exported (see below)
+/// will be able to `#include` headers from these directories.
+///
+/// Adding a directory to `exported_header_dirs` is similar to adding it to the
+/// current build via the `cc` crate's [`Build::include`][cc::Build::include],
+/// but *also* makes the directory available to downstream crates that want to
+/// `#include` one of the headers from your crate. If the dir were added only
+/// using `Build::include`, the downstream crate including your header would
+/// need to manually add the same directory to their own build as well.
+///
+/// When using `exported_header_dirs`, your crate must also set a `links` key
+/// for itself in Cargo.toml. See [*the `links` manifest key*][links]. The
+/// reason is that Cargo imposes no ordering on the execution of build scripts
+/// without a `links` key, which means the downstream crate's build script might
+/// execute before yours decides what to put into `exported_header_dirs`.
+///
+/// [links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+///
+/// ### Example
+///
+/// One of your crate's headers wants to include a system library, such as
+/// `#include "Python.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+/// use std::path::PathBuf;
+///
+/// fn main() {
+///     let python3 = pkg_config::probe_library("python3").unwrap();
+///     let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path);
+///     CFG.exported_header_dirs.extend(python_include_paths);
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
+///
+/// ### Example
+///
+/// Your crate wants to rearrange the headers that it exports vs how they're
+/// laid out locally inside the crate's source directory.
+///
+/// Suppose the crate as published contains a file at `./include/myheader.h` but
+/// wants it available to downstream crates as `#include "foo/v1/public.h"`.
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+/// use std::path::Path;
+/// use std::{env, fs};
+///
+/// fn main() {
+///     let out_dir = env::var_os("OUT_DIR").unwrap();
+///     let headers = Path::new(&out_dir).join("headers");
+///     CFG.exported_header_dirs.push(&headers);
+///
+///     // We contain `include/myheader.h` locally, but
+///     // downstream will use `#include "foo/v1/public.h"`
+///     let foo = headers.join("foo").join("v1");
+///     fs::create_dir_all(&foo).unwrap();
+///     fs::copy("include/myheader.h", foo.join("public.h")).unwrap();
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_prefixes`**
+///
+/// Vector of strings. These each refer to the `include_prefix` of one of your
+/// direct dependencies, or a prefix thereof. They describe which of your
+/// dependencies participate in your crate's C++ public API, as opposed to
+/// private use by your crate's implementation.
+///
+/// As a general rule, if one of your headers `#include`s something from one of
+/// your dependencies, you need to put that dependency's `include_prefix` into
+/// `CFG.exported_header_prefixes` (*or* their `links` key into
+/// `CFG.exported_header_links`; see below). On the other hand if only your C++
+/// implementation files and *not* your headers are importing from the
+/// dependency, you do not export that dependency.
+///
+/// The significance of exported headers is that if downstream code (crate 𝒜)
+/// contains an `#include` of a header from your crate (ℬ) and your header
+/// contains an `#include` of something from your dependency (𝒞), the exported
+/// dependency 𝒞 becomes available during the downstream crate 𝒜's build.
+/// Otherwise the downstream crate 𝒜 doesn't know about 𝒞 and wouldn't be able
+/// to find what header your header is referring to, and would fail to build.
+///
+/// When using `exported_header_prefixes`, your crate must also set a `links`
+/// key for itself in Cargo.toml.
+///
+/// ### Example
+///
+/// Suppose you have a crate with 5 direct dependencies and the `include_prefix`
+/// for each one are:
+///
+/// - "crate0"
+/// - "group/api/crate1"
+/// - "group/api/crate2"
+/// - "group/api/contrib/crate3"
+/// - "detail/crate4"
+///
+/// Your header involves types from the first four so we re-export those as part
+/// of your public API, while crate4 is only used internally by your cc file not
+/// your header, so we do not export:
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.exported_header_prefixes = vec!["crate0", "group/api"];
+///
+///     cxx_build::bridge("src/bridge.rs")
+///         .file("src/impl.cc")
+///         .compile("demo");
+/// }
+/// ```
+///
+/// <br>
+///
+/// ## **`CFG.exported_header_links`**
+///
+/// Vector of strings. These each refer to the `links` attribute ([*the `links`
+/// manifest key*][links]) of one of your crate's direct dependencies.
+///
+/// This achieves an equivalent result to `CFG.exported_header_prefixes` by
+/// re-exporting a dependency as part of your crate's public API, except with
+/// finer grained control for cases when multiple crates might be sharing the
+/// same `include_prefix` and you'd like to export some but not others. Links
+/// attributes are guaranteed to be unique identifiers by Cargo.
+///
+/// When using `exported_header_links`, your crate must also set a `links` key
+/// for itself in Cargo.toml.
+///
+/// ### Example
+///
+/// ```no_run
+/// // build.rs
+///
+/// use cxx_build::CFG;
+///
+/// fn main() {
+///     CFG.exported_header_links.push("git2");
+///
+///     cxx_build::bridge("src/bridge.rs").compile("demo");
+/// }
+/// ```
 #[cfg(doc)]
 pub static mut CFG: Cfg = Cfg {
     include_prefix: "",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index bdfcc38..97d6937 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -80,6 +80,7 @@ dependencies = [
  "codespan-reporting",
  "cxx-gen",
  "lazy_static",
+ "pkg-config",
  "proc-macro2",
  "quote",
  "scratch",
@@ -188,6 +189,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "pkg-config"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From cac5a839ff81376e2273c6efc725c5216c287d82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:06:43 +0000
Subject: [PATCH 1302/2232] Display field types in CFG documentation


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index c0e8054..3897516 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -19,6 +19,8 @@ pub struct Cfg<'a> {
 ///
 /// <br>
 ///
+/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>&amp;str</strong></div>
+///
 /// ## **`CFG.include_prefix`**
 ///
 /// The prefix at which C++ code from your crate as well as directly dependent
@@ -69,6 +71,8 @@ pub struct Cfg<'a> {
 ///
 /// <br>
 ///
+/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec&lt;&amp;Path&gt;</strong></div>
+///
 /// ## **`CFG.exported_header_dirs`**
 ///
 /// A vector of absolute paths. The current crate, directly dependent crates,
@@ -140,7 +144,9 @@ pub struct Cfg<'a> {
 /// }
 /// ```
 ///
-/// <br>
+/// <p style="margin:0"><br><br></p>
+///
+/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec&lt;&amp;str&gt;</strong></div>
 ///
 /// ## **`CFG.exported_header_prefixes`**
 ///
@@ -195,7 +201,9 @@ pub struct Cfg<'a> {
 /// }
 /// ```
 ///
-/// <br>
+/// <p style="margin:0"><br><br></p>
+///
+/// <div style="float:right;margin:22px 50px 0;font-size:1.15em;color:#444"><strong>Vec&lt;&amp;str&gt;</strong></div>
 ///
 /// ## **`CFG.exported_header_links`**
 ///

From 0b1a6b3353e1440bcf6dde9c5bae47da9d751cf8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:06:44 +0000
Subject: [PATCH 1303/2232] Link Cfg fields to their explanation in CFG


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index 3897516..aecd046 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -4,13 +4,13 @@ use std::path::Path;
 
 /// Build configuration. See [CFG].
 pub struct Cfg<'a> {
+    /// See [`CFG.include_prefix`][CFG#cfginclude_prefix].
     pub include_prefix: &'a str,
-    // Not implemented yet. https://github.com/dtolnay/cxx/issues/417
-    #[doc(hidden)]
+    /// See [`CFG.exported_header_dirs`][CFG#cfgexported_header_dirs].
     pub exported_header_dirs: Vec<&'a Path>,
-    #[doc(hidden)]
+    /// See [`CFG.exported_header_prefixes`][CFG#cfgexported_header_prefixes].
     pub exported_header_prefixes: Vec<&'a str>,
-    #[doc(hidden)]
+    /// See [`CFG.exported_header_links`][CFG#cfgexported_header_links].
     pub exported_header_links: Vec<&'a str>,
     marker: PhantomData<*const ()>, // !Send + !Sync
 }

From 5346b21d2f44c68cc96371a4dc960f9a0d7b8eeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:06:44 +0000
Subject: [PATCH 1304/2232] Include exported headers in Cfg's Debug impl


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index aecd046..c15a173 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -243,9 +243,19 @@ pub static mut CFG: Cfg = Cfg {
 
 impl<'a> Debug for Cfg<'a> {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        let Self {
+            include_prefix,
+            exported_header_dirs,
+            exported_header_prefixes,
+            exported_header_links,
+            marker: _,
+        } = self;
         formatter
             .debug_struct("Cfg")
-            .field("include_prefix", &self.include_prefix)
+            .field("include_prefix", include_prefix)
+            .field("exported_header_dirs", exported_header_dirs)
+            .field("exported_header_prefixes", exported_header_prefixes)
+            .field("exported_header_links", exported_header_links)
             .finish()
     }
 }

From b1141069e5aa85244f3e36929e51db35b09c9833 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 04:26:11 +0000
Subject: [PATCH 1305/2232] Quote the unrecognized element in "unused element" errors


---

diff --git a/gen/build/src/error.rs b/gen/build/src/error.rs
index e1cc345..99d7a30 100644
--- a/gen/build/src/error.rs
+++ b/gen/build/src/error.rs
@@ -68,13 +68,13 @@ impl Display for Error {
             ),
             Error::UnusedExportedPrefix(unused) => write!(
                 f,
-                "unused element in {}: {} does not match the include prefix of any direct dependency",
+                "unused element in {}: {:?} does not match the include prefix of any direct dependency",
                 expr!(CFG.exported_header_prefixes),
                 unused,
             ),
             Error::UnusedExportedLinks(unused) => write!(
                 f,
-                "unused element in {}: {} does not match the `links` attribute any direct dependency",
+                "unused element in {}: {:?} does not match the `links` attribute any direct dependency",
                 expr!(CFG.exported_header_links),
                 unused,
             ),

From db0d0fd8800216ae56aab298e54a684a4e252488 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 06:14:13 +0000
Subject: [PATCH 1306/2232] Upgrade to mdbook 0.4.4 for CNAME file support


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 39a8e48..73b8186 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -17,16 +17,14 @@ jobs:
       - name: Get mdBook
         working-directory: book
         run: |
-          export MDBOOK_VERSION="v0.4.2"
+          export MDBOOK_VERSION="v0.4.4"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
           export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
           curl -Lf "${MDBOOK_URL}" | tar -xz
 
       - name: Build
         working-directory: book
-        run: |
-          ./mdbook build
-          echo "cxx.rs" > build/CNAME
+        run: ./mdbook build
 
       - name: Push to gh-pages
         working-directory: book/build
diff --git a/book/book.toml b/book/book.toml
index bc2e913..d3187e0 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -10,4 +10,5 @@ edition = "2018"
 build-dir = "build"
 
 [output.html]
+cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"

From 20668560bbe232c1fdcf7d2ba0d865a73b7fbea8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 06:20:17 +0000
Subject: [PATCH 1307/2232] Merge pull request #429 from dtolnay/cname


Upgrade to mdbook 0.4.4 for CNAME file support
---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 39a8e48..73b8186 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -17,16 +17,14 @@ jobs:
       - name: Get mdBook
         working-directory: book
         run: |
-          export MDBOOK_VERSION="v0.4.2"
+          export MDBOOK_VERSION="v0.4.4"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
           export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
           curl -Lf "${MDBOOK_URL}" | tar -xz
 
       - name: Build
         working-directory: book
-        run: |
-          ./mdbook build
-          echo "cxx.rs" > build/CNAME
+        run: ./mdbook build
 
       - name: Push to gh-pages
         working-directory: book/build
diff --git a/book/book.toml b/book/book.toml
index bc2e913..d3187e0 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -10,4 +10,5 @@ edition = "2018"
 build-dir = "build"
 
 [output.html]
+cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"

From 7c5ce689a38d4730c9c87ec6abda39d2cd9b938d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 17:54:11 +0000
Subject: [PATCH 1308/2232] Release 0.5.5


---

diff --git a/Cargo.toml b/Cargo.toml
index 803f01e..1cdb14a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.4" # remember to update html_root_url
+version = "0.5.5" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.4", path = "macro" }
+cxxbridge-macro = { version = "=0.5.5", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.4", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.5", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.4", path = "gen/build" }
+cxx-build = { version = "=0.5.5", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 17d89d6..2c2bef9 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.4"
+version = "0.5.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 737b047..6b3647d 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.4"
+version = "0.5.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 1289c34..5bf3062 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.4"
+version = "0.5.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index b4a10f1..b4dab77 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.1"
+version = "0.6.2"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 647710c..af7a028 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.4"
+version = "0.5.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 5134268..71a21d9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.4")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.5")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 97d6937..ad3cb2a 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.4"
+version = "0.5.5"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.4"
+version = "0.5.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.1"
+version = "0.6.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.4"
+version = "0.5.5"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.4"
+version = "0.5.5"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.4"
+version = "0.5.5"
 dependencies = [
  "cxx",
  "proc-macro2",

From c90b666eec0d57e4bd17f2911e7804934112ef65 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 18:11:14 +0000
Subject: [PATCH 1309/2232] Ignore some clippy lints in test suite


Closes #430.

---

diff --git a/tests/test.rs b/tests/test.rs
index 2c6f062..e3f9fce 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
+
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;

From a972eb7d933ea889ffd008005ce28687e85f8c29 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 18:12:21 +0000
Subject: [PATCH 1310/2232] Ignore field_reassign_with_default


---

diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 1818af4..06d7bc7 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::field_reassign_with_default)]
+
 use cxx_gen::{generate_header_and_cc, Opt};
 use std::str;
 

From df67e21241836ee5e51cb9546dfddda3767a821f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 18:13:14 +0000
Subject: [PATCH 1311/2232] Resolve len_zero lint in cxx-gen test suite


---

diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index be2e60f..73a25f3 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -16,8 +16,8 @@ fn test_positive() {
     };
     let opt = Opt::default();
     let code = cxx_gen::generate_header_and_cc(rs, &opt).unwrap();
-    assert!(code.header.len() > 0);
-    assert!(code.implementation.len() > 0);
+    assert!(!code.header.is_empty());
+    assert!(!code.implementation.is_empty());
 }
 
 #[test]

From 7a0b134d9ca466eac86698be9dbe9b7804c8a1cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 18:14:43 +0000
Subject: [PATCH 1312/2232] Run clippy on test suite in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f8f66dc..26b2722 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -92,4 +92,4 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
-      - run: cargo clippy --workspace -- -Dclippy::all
+      - run: cargo clippy --workspace --tests -- -Dclippy::all

From 2e159920da42152a185a060ccf95b0b6bc1e91e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 06 2020 18:24:09 +0000
Subject: [PATCH 1313/2232] Merge pull request #433 from dtolnay/clippy


Run clippy on test suite in CI
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f8f66dc..26b2722 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -92,4 +92,4 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
-      - run: cargo clippy --workspace -- -Dclippy::all
+      - run: cargo clippy --workspace --tests -- -Dclippy::all
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index be2e60f..73a25f3 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -16,8 +16,8 @@ fn test_positive() {
     };
     let opt = Opt::default();
     let code = cxx_gen::generate_header_and_cc(rs, &opt).unwrap();
-    assert!(code.header.len() > 0);
-    assert!(code.implementation.len() > 0);
+    assert!(!code.header.is_empty());
+    assert!(!code.implementation.is_empty());
 }
 
 #[test]
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 1818af4..06d7bc7 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::field_reassign_with_default)]
+
 use cxx_gen::{generate_header_and_cc, Opt};
 use std::str;
 
diff --git a/tests/test.rs b/tests/test.rs
index 2c6f062..e3f9fce 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
+
 use cxx_test_suite::extra::ffi2;
 use cxx_test_suite::ffi;
 use std::cell::Cell;

From 102c7eaf68f45ebcd7db9f740947daa547af0601 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 09 2020 03:08:31 +0000
Subject: [PATCH 1314/2232] C++-defined methods on shared structs


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b8d1dd4..39053a1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -66,7 +66,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
 fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     let mut methods_for_type = HashMap::new();
     for api in apis {
-        if let Api::RustFunction(efn) = api {
+        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
                     .entry(&receiver.ty.rust)
@@ -84,7 +84,11 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 for next in &mut toposorted_structs {
                     if !out.types.cxx.contains(&strct.name.rust) {
                         out.next_section();
-                        write_struct(out, next);
+                        let methods = methods_for_type
+                            .get(&strct.name.rust)
+                            .map(Vec::as_slice)
+                            .unwrap_or_default();
+                        write_struct(out, next, methods);
                     }
                     structs_written.insert(&next.name.rust);
                     if next.name.rust == strct.name.rust {
@@ -173,7 +177,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -187,6 +191,16 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
+    if !methods.is_empty() {
+        writeln!(out);
+    }
+    for method in methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.name.cxx.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false);
+        writeln!(out, ";");
+    }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9ea3450..4c9ecd3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -202,6 +202,7 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
         fn set_succeed(&mut self, n: usize) -> Result<usize>;
         fn get_fail(&mut self) -> Result<usize>;
+        fn method_on_shared(self: &Shared) -> usize;
 
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 747788f..b387bbb 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,6 +35,8 @@ size_t C::set_succeed(size_t n) { return this->set2(n); }
 
 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
+size_t Shared::method_on_shared() const noexcept { return 2021; }
+
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
 std::vector<uint8_t> &C::get_v() { return this->v; }
diff --git a/tests/test.rs b/tests/test.rs
index e3f9fce..58fdd84 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -193,6 +193,7 @@ fn test_c_method_calls() {
     assert_eq!(old_value, unique_ptr.get2());
     assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
     assert!(unique_ptr.get_fail().is_err());
+    assert_eq!(2021, ffi::Shared { z: 0 }.method_on_shared());
 }
 
 #[test]

From 464aeeb515591e89dca8bf9a014ff73c045775f5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 09 2020 03:14:06 +0000
Subject: [PATCH 1315/2232] Rust-defined methods on shared structs


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4c9ecd3..96f9b07 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -202,7 +202,7 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
         fn set_succeed(&mut self, n: usize) -> Result<usize>;
         fn get_fail(&mut self) -> Result<usize>;
-        fn method_on_shared(self: &Shared) -> usize;
+        fn c_method_on_shared(self: &Shared) -> usize;
 
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
@@ -274,6 +274,7 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
+        fn r_method_on_shared(self: &Shared) -> usize;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -316,6 +317,12 @@ impl R2 {
     }
 }
 
+impl ffi::Shared {
+    fn r_method_on_shared(&self) -> usize {
+        2020
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b387bbb..fd4751e 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,7 +35,7 @@ size_t C::set_succeed(size_t n) { return this->set2(n); }
 
 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
-size_t Shared::method_on_shared() const noexcept { return 2021; }
+size_t Shared::c_method_on_shared() const noexcept { return 2021; }
 
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
@@ -626,6 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->get() == 2021);
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
+  ASSERT(Shared{0}.r_method_on_shared() == 2020);
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 
diff --git a/tests/test.rs b/tests/test.rs
index 58fdd84..a2c64c3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -193,7 +193,7 @@ fn test_c_method_calls() {
     assert_eq!(old_value, unique_ptr.get2());
     assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
     assert!(unique_ptr.get_fail().is_err());
-    assert_eq!(2021, ffi::Shared { z: 0 }.method_on_shared());
+    assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 
 #[test]

From 7f0f60f9a6b96e970b958fab1ece6dbc1850e2e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 09 2020 03:20:58 +0000
Subject: [PATCH 1316/2232] Merge pull request #437 from dtolnay/methods


Support methods/member functions on shared structs
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b8d1dd4..39053a1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -66,7 +66,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
 fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     let mut methods_for_type = HashMap::new();
     for api in apis {
-        if let Api::RustFunction(efn) = api {
+        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
                 methods_for_type
                     .entry(&receiver.ty.rust)
@@ -84,7 +84,11 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 for next in &mut toposorted_structs {
                     if !out.types.cxx.contains(&strct.name.rust) {
                         out.next_section();
-                        write_struct(out, next);
+                        let methods = methods_for_type
+                            .get(&strct.name.rust)
+                            .map(Vec::as_slice)
+                            .unwrap_or_default();
+                        write_struct(out, next, methods);
                     }
                     structs_written.insert(&next.name.rust);
                     if next.name.rust == strct.name.rust {
@@ -173,7 +177,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     }
 }
 
-fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -187,6 +191,16 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
+    if !methods.is_empty() {
+        writeln!(out);
+    }
+    for method in methods {
+        write!(out, "  ");
+        let sig = &method.sig;
+        let local_name = method.name.cxx.to_string();
+        write_rust_function_shim_decl(out, &local_name, sig, false);
+        writeln!(out, ";");
+    }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9ea3450..96f9b07 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -202,6 +202,7 @@ pub mod ffi {
         fn set2(&mut self, n: usize) -> usize;
         fn set_succeed(&mut self, n: usize) -> Result<usize>;
         fn get_fail(&mut self) -> Result<usize>;
+        fn c_method_on_shared(self: &Shared) -> usize;
 
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
@@ -273,6 +274,7 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
+        fn r_method_on_shared(self: &Shared) -> usize;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -315,6 +317,12 @@ impl R2 {
     }
 }
 
+impl ffi::Shared {
+    fn r_method_on_shared(&self) -> usize {
+        2020
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 747788f..fd4751e 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -35,6 +35,8 @@ size_t C::set_succeed(size_t n) { return this->set2(n); }
 
 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
+size_t Shared::c_method_on_shared() const noexcept { return 2021; }
+
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
 std::vector<uint8_t> &C::get_v() { return this->v; }
@@ -624,6 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->get() == 2021);
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
+  ASSERT(Shared{0}.r_method_on_shared() == 2020);
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 
diff --git a/tests/test.rs b/tests/test.rs
index e3f9fce..a2c64c3 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -193,6 +193,7 @@ fn test_c_method_calls() {
     assert_eq!(old_value, unique_ptr.get2());
     assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
     assert!(unique_ptr.get_fail().is_err());
+    assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 
 #[test]

From 7b3605583d8b46f55c14ed3fe640597f8df2c64d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 09 2020 03:23:10 +0000
Subject: [PATCH 1317/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 403b275..a9a3913 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.61/src/**"]),
+    srcs = glob(["vendor/cc-1.0.62/src/**"]),
     visibility = ["PUBLIC"],
 )
 
diff --git a/third-party/BUILD b/third-party/BUILD
index bdded93..d72b083 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -13,7 +13,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.61/src/**"]),
+    srcs = glob(["vendor/cc-1.0.62/src/**"]),
     visibility = ["//visibility:public"],
 )
 
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ad3cb2a..efd7692 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.61"
+version = "1.0.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
+checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
 
 [[package]]
 name = "clap"

From 22f5ff756399ada694baf870aa3c7f971152902d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 09 2020 03:24:15 +0000
Subject: [PATCH 1318/2232] Release 0.5.6


---

diff --git a/Cargo.toml b/Cargo.toml
index 1cdb14a..3b922bb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.5" # remember to update html_root_url
+version = "0.5.6" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.5", path = "macro" }
+cxxbridge-macro = { version = "=0.5.6", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.5", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.6", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.5", path = "gen/build" }
+cxx-build = { version = "=0.5.6", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 2c2bef9..9421f18 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.5"
+version = "0.5.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 6b3647d..a58d811 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.5"
+version = "0.5.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 5bf3062..24aecf4 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.5"
+version = "0.5.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index b4dab77..4ddde61 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.2"
+version = "0.6.3"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index af7a028..167c813 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.5"
+version = "0.5.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 71a21d9..58a08ed 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.5")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.6")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index efd7692..a41d71b 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.5"
+version = "0.5.6"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.5"
+version = "0.5.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.2"
+version = "0.6.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.5"
+version = "0.5.6"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.5"
+version = "0.5.6"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.5"
+version = "0.5.6"
 dependencies = [
  "cxx",
  "proc-macro2",

From 9e2f59069111cf6756ac4c203c765a3f8cabccde Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:17:12 +0000
Subject: [PATCH 1319/2232] Add ui test of returning a non-displayable error


---

diff --git a/tests/ui/result_no_display.rs b/tests/ui/result_no_display.rs
new file mode 100644
index 0000000..b535677
--- /dev/null
+++ b/tests/ui/result_no_display.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f() -> Result<()>;
+    }
+}
+
+pub struct NonError;
+
+fn f() -> Result<(), NonError> {
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
new file mode 100644
index 0000000..f33b1be
--- /dev/null
+++ b/tests/ui/result_no_display.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `NonError` doesn't implement `std::fmt::Display`
+  --> $DIR/result_no_display.rs:1:1
+   |
+1  | #[cxx::bridge]
+   | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+   |
+  ::: $WORKSPACE/src/result.rs
+   |
+   |     E: Display,
+   |        ------- required by this bound in `cxx::private::r#try`
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `NonError`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From c5501544e5457f3a9414b349648735ef9ccb0a15 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:30:33 +0000
Subject: [PATCH 1320/2232] Merge pull request #438 from dtolnay/result


Add ui test of returning a non-displayable error
---

diff --git a/tests/ui/result_no_display.rs b/tests/ui/result_no_display.rs
new file mode 100644
index 0000000..b535677
--- /dev/null
+++ b/tests/ui/result_no_display.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f() -> Result<()>;
+    }
+}
+
+pub struct NonError;
+
+fn f() -> Result<(), NonError> {
+    Ok(())
+}
+
+fn main() {}
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
new file mode 100644
index 0000000..f33b1be
--- /dev/null
+++ b/tests/ui/result_no_display.stderr
@@ -0,0 +1,14 @@
+error[E0277]: `NonError` doesn't implement `std::fmt::Display`
+  --> $DIR/result_no_display.rs:1:1
+   |
+1  | #[cxx::bridge]
+   | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+   |
+  ::: $WORKSPACE/src/result.rs
+   |
+   |     E: Display,
+   |        ------- required by this bound in `cxx::private::r#try`
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `NonError`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 5f8a70472a5b56dd1da968f94e42349e0dc5d765 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:30:45 +0000
Subject: [PATCH 1321/2232] Add test of missing unsafe on extern Rust sig


---

diff --git a/tests/ui/missing_unsafe.rs b/tests/ui/missing_unsafe.rs
new file mode 100644
index 0000000..d8c0a23
--- /dev/null
+++ b/tests/ui/missing_unsafe.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f(x: i32);
+    }
+}
+
+unsafe fn f(_x: i32) {}
+
+fn main() {}

From 464d3fc0ac90ad0a2f4b47f3da269c23c591271e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:30:45 +0000
Subject: [PATCH 1322/2232] Add test of unsupported elided lifetime in extern Rust sig


---

diff --git a/tests/ui/unsupported_elided.rs b/tests/ui/unsupported_elided.rs
new file mode 100644
index 0000000..4033319
--- /dev/null
+++ b/tests/ui/unsupported_elided.rs
@@ -0,0 +1,20 @@
+use std::marker::PhantomData;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type T;
+
+        fn f(t: &T) -> &str;
+    }
+}
+
+pub struct T<'a> {
+    _lifetime: PhantomData<&'a ()>,
+}
+
+fn f<'a>(_t: &T<'a>) -> &'a str {
+    ""
+}
+
+fn main() {}

From 26219468557e72ae2a5195e64d46c63ac1c6ff40 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:30:45 +0000
Subject: [PATCH 1323/2232] Enforce accurate unsafety declaration on extern Rust sigs


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b5d3067..57b64b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -563,14 +563,10 @@ fn expand_rust_function_shim_impl(
     });
     let vars = receiver_var.into_iter().chain(arg_vars);
 
+    let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
+
     let mut call = match invoke {
-        Some(ident) => match &sig.receiver {
-            None => quote!(super::#ident),
-            Some(receiver) => {
-                let receiver_type = &receiver.ty;
-                quote!(#receiver_type::#ident)
-            }
-        },
+        Some(_) => quote!(#local_name),
         None => quote!(::std::mem::transmute::<*const (), #sig>(__extern)),
     };
     call.extend(quote! { (#(#vars),*) });
@@ -648,11 +644,61 @@ fn expand_rust_function_shim_impl(
         #[export_name = #link_name]
         unsafe extern "C" fn #local_name(#(#all_args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
+            #wrap_super
             #expr
         }
     }
 }
 
+// A wrapper like `fn f(x: Arg) { super::f(x) }` just to ensure we have the
+// accurate unsafety declaration and no problematic elided lifetimes.
+fn expand_rust_function_shim_super(
+    sig: &Signature,
+    local_name: &Ident,
+    invoke: &Ident,
+) -> TokenStream {
+    let unsafety = sig.unsafety;
+
+    let receiver_var = sig
+        .receiver
+        .as_ref()
+        .map(|receiver| Ident::new("__self", receiver.var.span));
+    let receiver = sig.receiver.iter().map(|receiver| {
+        let receiver_type = receiver.ty();
+        quote!(#receiver_var: #receiver_type)
+    });
+    let args = sig.args.iter().map(|arg| quote!(#arg));
+    let all_args = receiver.chain(args);
+
+    let ret = if sig.throws {
+        let ok = match &sig.ret {
+            Some(ret) => quote!(#ret),
+            None => quote!(()),
+        };
+        quote!(-> ::std::result::Result<#ok, impl ::std::fmt::Display>)
+    } else {
+        expand_return_type(&sig.ret)
+    };
+
+    let arg_vars = sig.args.iter().map(|arg| &arg.ident);
+    let vars = receiver_var.iter().chain(arg_vars);
+
+    let span = invoke.span();
+    let call = match &sig.receiver {
+        None => quote_spanned!(span=> super::#invoke),
+        Some(receiver) => {
+            let receiver_type = &receiver.ty;
+            quote_spanned!(span=> #receiver_type::#invoke)
+        }
+    };
+
+    quote_spanned! {span=>
+        #unsafety fn #local_name(#(#all_args,)*) #ret {
+            #call(#(#vars,)*)
+        }
+    }
+}
+
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let ident = &alias.name.rust;
diff --git a/tests/ui/missing_unsafe.stderr b/tests/ui/missing_unsafe.stderr
new file mode 100644
index 0000000..df1bce2
--- /dev/null
+++ b/tests/ui/missing_unsafe.stderr
@@ -0,0 +1,7 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/missing_unsafe.rs:4:12
+  |
+4 |         fn f(x: i32);
+  |            ^ call to unsafe function
+  |
+  = note: consult the function's documentation for information on how to avoid undefined behavior
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
index f33b1be..e92cd36 100644
--- a/tests/ui/result_no_display.stderr
+++ b/tests/ui/result_no_display.stderr
@@ -1,14 +1,8 @@
 error[E0277]: `NonError` doesn't implement `std::fmt::Display`
-  --> $DIR/result_no_display.rs:1:1
-   |
-1  | #[cxx::bridge]
-   | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
-   |
-  ::: $WORKSPACE/src/result.rs
-   |
-   |     E: Display,
-   |        ------- required by this bound in `cxx::private::r#try`
-   |
-   = help: the trait `std::fmt::Display` is not implemented for `NonError`
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+ --> $DIR/result_no_display.rs:1:1
+  |
+1 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+  |
+  = help: the trait `std::fmt::Display` is not implemented for `NonError`
+  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
diff --git a/tests/ui/unsupported_elided.stderr b/tests/ui/unsupported_elided.stderr
new file mode 100644
index 0000000..5136390
--- /dev/null
+++ b/tests/ui/unsupported_elided.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/unsupported_elided.rs:8:24
+  |
+8 |         fn f(t: &T) -> &str;
+  |                 --     ^ expected named lifetime parameter
+  |
+  = help: this function's return type contains a borrowed value, but the signature does not say which one of `t`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+  |
+8 |         fn f<'a>(t: &'a T) -> &'a str;
+  |             ^^^^    ^^^^^     ^^^

From 0e7e37f8e28b960c9f76d7153ebad3087dce1991 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:41:35 +0000
Subject: [PATCH 1324/2232] Suppress 'consider choosing a more descriptive name' clippy lint in tests


    warning: consider choosing a more descriptive name
       --> tests/ffi/lib.rs:247:30
        |
    247 |         fn r_return_identity(_: usize) -> usize;
        |                              ^
        |
        = note: `#[warn(clippy::just_underscores_and_digits)]` on by default
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits

    warning: consider choosing a more descriptive name
       --> tests/ffi/lib.rs:248:25
        |
    248 |         fn r_return_sum(_: usize, _: usize) -> usize;
        |                         ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits

    warning: consider choosing a more descriptive name
       --> tests/ffi/lib.rs:248:35
        |
    248 |         fn r_return_sum(_: usize, _: usize) -> usize;
        |                                   ^
        |
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits

---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 96f9b07..cf8e876 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,5 +1,6 @@
 #![allow(
     clippy::boxed_local,
+    clippy::just_underscores_and_digits,
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref
 )]

From 3db709c0c5a0c67a75a7ec81e54f7987b4bbea83 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:47:06 +0000
Subject: [PATCH 1325/2232] Merge pull request #439 from dtolnay/sig


Enforce accurate unsafety declaration on extern Rust sigs
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b5d3067..57b64b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -563,14 +563,10 @@ fn expand_rust_function_shim_impl(
     });
     let vars = receiver_var.into_iter().chain(arg_vars);
 
+    let wrap_super = invoke.map(|invoke| expand_rust_function_shim_super(sig, &local_name, invoke));
+
     let mut call = match invoke {
-        Some(ident) => match &sig.receiver {
-            None => quote!(super::#ident),
-            Some(receiver) => {
-                let receiver_type = &receiver.ty;
-                quote!(#receiver_type::#ident)
-            }
-        },
+        Some(_) => quote!(#local_name),
         None => quote!(::std::mem::transmute::<*const (), #sig>(__extern)),
     };
     call.extend(quote! { (#(#vars),*) });
@@ -648,11 +644,61 @@ fn expand_rust_function_shim_impl(
         #[export_name = #link_name]
         unsafe extern "C" fn #local_name(#(#all_args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
+            #wrap_super
             #expr
         }
     }
 }
 
+// A wrapper like `fn f(x: Arg) { super::f(x) }` just to ensure we have the
+// accurate unsafety declaration and no problematic elided lifetimes.
+fn expand_rust_function_shim_super(
+    sig: &Signature,
+    local_name: &Ident,
+    invoke: &Ident,
+) -> TokenStream {
+    let unsafety = sig.unsafety;
+
+    let receiver_var = sig
+        .receiver
+        .as_ref()
+        .map(|receiver| Ident::new("__self", receiver.var.span));
+    let receiver = sig.receiver.iter().map(|receiver| {
+        let receiver_type = receiver.ty();
+        quote!(#receiver_var: #receiver_type)
+    });
+    let args = sig.args.iter().map(|arg| quote!(#arg));
+    let all_args = receiver.chain(args);
+
+    let ret = if sig.throws {
+        let ok = match &sig.ret {
+            Some(ret) => quote!(#ret),
+            None => quote!(()),
+        };
+        quote!(-> ::std::result::Result<#ok, impl ::std::fmt::Display>)
+    } else {
+        expand_return_type(&sig.ret)
+    };
+
+    let arg_vars = sig.args.iter().map(|arg| &arg.ident);
+    let vars = receiver_var.iter().chain(arg_vars);
+
+    let span = invoke.span();
+    let call = match &sig.receiver {
+        None => quote_spanned!(span=> super::#invoke),
+        Some(receiver) => {
+            let receiver_type = &receiver.ty;
+            quote_spanned!(span=> #receiver_type::#invoke)
+        }
+    };
+
+    quote_spanned! {span=>
+        #unsafety fn #local_name(#(#all_args,)*) #ret {
+            #call(#(#vars,)*)
+        }
+    }
+}
+
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let ident = &alias.name.rust;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 96f9b07..cf8e876 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,5 +1,6 @@
 #![allow(
     clippy::boxed_local,
+    clippy::just_underscores_and_digits,
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref
 )]
diff --git a/tests/ui/missing_unsafe.rs b/tests/ui/missing_unsafe.rs
new file mode 100644
index 0000000..d8c0a23
--- /dev/null
+++ b/tests/ui/missing_unsafe.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f(x: i32);
+    }
+}
+
+unsafe fn f(_x: i32) {}
+
+fn main() {}
diff --git a/tests/ui/missing_unsafe.stderr b/tests/ui/missing_unsafe.stderr
new file mode 100644
index 0000000..df1bce2
--- /dev/null
+++ b/tests/ui/missing_unsafe.stderr
@@ -0,0 +1,7 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/missing_unsafe.rs:4:12
+  |
+4 |         fn f(x: i32);
+  |            ^ call to unsafe function
+  |
+  = note: consult the function's documentation for information on how to avoid undefined behavior
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
index f33b1be..e92cd36 100644
--- a/tests/ui/result_no_display.stderr
+++ b/tests/ui/result_no_display.stderr
@@ -1,14 +1,8 @@
 error[E0277]: `NonError` doesn't implement `std::fmt::Display`
-  --> $DIR/result_no_display.rs:1:1
-   |
-1  | #[cxx::bridge]
-   | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
-   |
-  ::: $WORKSPACE/src/result.rs
-   |
-   |     E: Display,
-   |        ------- required by this bound in `cxx::private::r#try`
-   |
-   = help: the trait `std::fmt::Display` is not implemented for `NonError`
-   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+ --> $DIR/result_no_display.rs:1:1
+  |
+1 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+  |
+  = help: the trait `std::fmt::Display` is not implemented for `NonError`
+  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
diff --git a/tests/ui/unsupported_elided.rs b/tests/ui/unsupported_elided.rs
new file mode 100644
index 0000000..4033319
--- /dev/null
+++ b/tests/ui/unsupported_elided.rs
@@ -0,0 +1,20 @@
+use std::marker::PhantomData;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type T;
+
+        fn f(t: &T) -> &str;
+    }
+}
+
+pub struct T<'a> {
+    _lifetime: PhantomData<&'a ()>,
+}
+
+fn f<'a>(_t: &T<'a>) -> &'a str {
+    ""
+}
+
+fn main() {}
diff --git a/tests/ui/unsupported_elided.stderr b/tests/ui/unsupported_elided.stderr
new file mode 100644
index 0000000..5136390
--- /dev/null
+++ b/tests/ui/unsupported_elided.stderr
@@ -0,0 +1,11 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/unsupported_elided.rs:8:24
+  |
+8 |         fn f(t: &T) -> &str;
+  |                 --     ^ expected named lifetime parameter
+  |
+  = help: this function's return type contains a borrowed value, but the signature does not say which one of `t`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+  |
+8 |         fn f<'a>(t: &'a T) -> &'a str;
+  |             ^^^^    ^^^^^     ^^^

From 5d164678aed8cd27fca15694a12051e8644b1b1a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:47:14 +0000
Subject: [PATCH 1326/2232] Improve placement of diagnostic on Result without Display impl


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 57b64b5..a01c1c6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -670,12 +670,14 @@ fn expand_rust_function_shim_super(
     let args = sig.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
 
-    let ret = if sig.throws {
+    let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
         let ok = match &sig.ret {
             Some(ret) => quote!(#ret),
             None => quote!(()),
         };
-        quote!(-> ::std::result::Result<#ok, impl ::std::fmt::Display>)
+        let impl_trait = quote_spanned!(result.span=> impl);
+        let display = quote_spanned!(rangle.span=> ::std::fmt::Display);
+        quote!(-> ::std::result::Result<#ok, #impl_trait #display>)
     } else {
         expand_return_type(&sig.ret)
     };
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
index e92cd36..d0502f9 100644
--- a/tests/ui/result_no_display.stderr
+++ b/tests/ui/result_no_display.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `NonError` doesn't implement `std::fmt::Display`
- --> $DIR/result_no_display.rs:1:1
+ --> $DIR/result_no_display.rs:4:19
   |
-1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+4 |         fn f() -> Result<()>;
+  |                   ^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `NonError`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

From 0cb4514cfb42e5b4ecf76701a6387c364070b1ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 04:53:04 +0000
Subject: [PATCH 1327/2232] Merge pull request #440 from dtolnay/result


Improve placement of diagnostic on Result without Display impl
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 57b64b5..a01c1c6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -670,12 +670,14 @@ fn expand_rust_function_shim_super(
     let args = sig.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
 
-    let ret = if sig.throws {
+    let ret = if let Some((result, _langle, rangle)) = sig.throws_tokens {
         let ok = match &sig.ret {
             Some(ret) => quote!(#ret),
             None => quote!(()),
         };
-        quote!(-> ::std::result::Result<#ok, impl ::std::fmt::Display>)
+        let impl_trait = quote_spanned!(result.span=> impl);
+        let display = quote_spanned!(rangle.span=> ::std::fmt::Display);
+        quote!(-> ::std::result::Result<#ok, #impl_trait #display>)
     } else {
         expand_return_type(&sig.ret)
     };
diff --git a/tests/ui/result_no_display.stderr b/tests/ui/result_no_display.stderr
index e92cd36..d0502f9 100644
--- a/tests/ui/result_no_display.stderr
+++ b/tests/ui/result_no_display.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `NonError` doesn't implement `std::fmt::Display`
- --> $DIR/result_no_display.rs:1:1
+ --> $DIR/result_no_display.rs:4:19
   |
-1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
+4 |         fn f() -> Result<()>;
+  |                   ^^^^^^^^^^ `NonError` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `NonError`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

From 74608d79bf7312d4e80ffa98e554c72196870b18 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 16:49:23 +0000
Subject: [PATCH 1328/2232] Add test of indirect return on member function


    cxxbridge/sources/tests/ffi/lib.rs.cc: In member function ‘rust::cxxbridge05::String tests::Shared::r_method_on_shared() const’:
    cxxbridge/sources/tests/ffi/lib.rs.cc:1583:52: error: no match for ‘operator&’ (operand types are ‘const tests::Shared’ and ‘rust::cxxbridge05::String’)
     1583 |   tests$cxxbridge05$Shared$r_method_on_shared(*this&return$.value);
          |                                               ~~~~~^~~~~~~~~~~~~~
          |                                               |             |
          |                                               |             rust::cxxbridge05::String
          |                                               const tests::Shared

---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 96f9b07..7461d66 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -274,7 +274,7 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
-        fn r_method_on_shared(self: &Shared) -> usize;
+        fn r_method_on_shared(self: &Shared) -> String;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -318,8 +318,8 @@ impl R2 {
 }
 
 impl ffi::Shared {
-    fn r_method_on_shared(&self) -> usize {
-        2020
+    fn r_method_on_shared(&self) -> String {
+        "2020".to_owned()
     }
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index fd4751e..c3c797a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -626,7 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->get() == 2021);
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
-  ASSERT(Shared{0}.r_method_on_shared() == 2020);
+  ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 

From 9d840365ccd50f11d6e2b4d935d2c3cd4b592a09 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 16:50:40 +0000
Subject: [PATCH 1329/2232] Fix placement of commas in C++ member functions that call Rust methods


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 39053a1..69b9f2e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -698,11 +698,13 @@ fn write_rust_function_shim_impl(
         write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
+    let mut needs_comma = false;
     if sig.receiver.is_some() {
         write!(out, "*this");
+        needs_comma = true;
     }
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 || sig.receiver.is_some() {
+    for arg in &sig.args {
+        if needs_comma {
             write!(out, ", ");
         }
         match &arg.ty {
@@ -725,15 +727,17 @@ fn write_rust_function_shim_impl(
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
+        needs_comma = true;
     }
     if indirect_return {
-        if !sig.args.is_empty() {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "&return$.value");
+        needs_comma = true;
     }
     if indirect_call {
-        if !sig.args.is_empty() || indirect_return {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "extern$");

From 4ee0f84397c4236f1c35853f5e83c965509cc055 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 16:56:37 +0000
Subject: [PATCH 1330/2232] Merge pull request #443 from dtolnay/comma


Fix placement of commas in C++ member functions that call Rust methods
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 39053a1..69b9f2e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -698,11 +698,13 @@ fn write_rust_function_shim_impl(
         write!(out, "::rust::repr::PtrLen error$ = ");
     }
     write!(out, "{}(", invoke);
+    let mut needs_comma = false;
     if sig.receiver.is_some() {
         write!(out, "*this");
+        needs_comma = true;
     }
-    for (i, arg) in sig.args.iter().enumerate() {
-        if i > 0 || sig.receiver.is_some() {
+    for arg in &sig.args {
+        if needs_comma {
             write!(out, ", ");
         }
         match &arg.ty {
@@ -725,15 +727,17 @@ fn write_rust_function_shim_impl(
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
+        needs_comma = true;
     }
     if indirect_return {
-        if !sig.args.is_empty() {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "&return$.value");
+        needs_comma = true;
     }
     if indirect_call {
-        if !sig.args.is_empty() || indirect_return {
+        if needs_comma {
             write!(out, ", ");
         }
         write!(out, "extern$");
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cf8e876..0f3f0d4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -275,7 +275,7 @@ pub mod ffi {
         fn r_return_r2(n: usize) -> Box<R2>;
         fn get(self: &R2) -> usize;
         fn set(self: &mut R2, n: usize) -> usize;
-        fn r_method_on_shared(self: &Shared) -> usize;
+        fn r_method_on_shared(self: &Shared) -> String;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -319,8 +319,8 @@ impl R2 {
 }
 
 impl ffi::Shared {
-    fn r_method_on_shared(&self) -> usize {
-        2020
+    fn r_method_on_shared(&self) -> String {
+        "2020".to_owned()
     }
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index fd4751e..c3c797a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -626,7 +626,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r2->get() == 2021);
   ASSERT(r2->set(2020) == 2020);
   ASSERT(r2->get() == 2020);
-  ASSERT(Shared{0}.r_method_on_shared() == 2020);
+  ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 

From 07c5141446ec214e3a1047321c6bcf35318a4b62 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 16:57:44 +0000
Subject: [PATCH 1331/2232] Release 0.5.7


---

diff --git a/Cargo.toml b/Cargo.toml
index 3b922bb..7c869e4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.6" # remember to update html_root_url
+version = "0.5.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.6", path = "macro" }
+cxxbridge-macro = { version = "=0.5.7", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.6", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.7", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.6", path = "gen/build" }
+cxx-build = { version = "=0.5.7", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 9421f18..de74ed1 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index a58d811..b694f9a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 24aecf4..fe09585 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 4ddde61..3a6988d 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.3"
+version = "0.6.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 167c813..1a78458 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 58a08ed..2265032 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.7")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a41d71b..9750d48 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.3"
+version = "0.6.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.6"
+version = "0.5.7"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From 9b193c388bdd75e191e07c7768934c04993340aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 10 2020 16:59:14 +0000
Subject: [PATCH 1332/2232] Merge 0.5.7 into master


---

diff --git a/Cargo.toml b/Cargo.toml
index 3b922bb..7c869e4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.6" # remember to update html_root_url
+version = "0.5.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.6", path = "macro" }
+cxxbridge-macro = { version = "=0.5.7", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.6", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.7", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.6", path = "gen/build" }
+cxx-build = { version = "=0.5.7", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 9421f18..de74ed1 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index a58d811..b694f9a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 24aecf4..fe09585 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 4ddde61..3a6988d 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.3"
+version = "0.6.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 167c813..1a78458 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.6"
+version = "0.5.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 58a08ed..2265032 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.7")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a41d71b..9750d48 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.3"
+version = "0.6.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.6"
+version = "0.5.7"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.6"
+version = "0.5.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From 302b1753c8147bdffca1e8d27604ffa05df11a67 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 02:45:14 +0000
Subject: [PATCH 1333/2232] Consistently use &Namespace in parser function signatures


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2136653..aa1eef6 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -30,11 +30,11 @@ pub fn parse_items(
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(cx, item, namespace.clone()) {
+            Item::Struct(item) => match parse_struct(cx, item, namespace) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item, namespace.clone()) {
+            Item::Enum(item) => match parse_enum(cx, item, namespace) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
@@ -52,7 +52,7 @@ pub fn parse_items(
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -67,6 +67,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
 
     let mut doc = Doc::new();
     let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &item.attrs,
@@ -78,7 +79,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
         },
     );
 
-    let fields = match item.fields {
+    let named_fields = match item.fields {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
         Fields::Unnamed(_) => {
@@ -86,26 +87,28 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
         }
     };
 
+    let fields = named_fields
+        .named
+        .into_iter()
+        .map(|field| {
+            Ok(Var {
+                ident: field.ident.unwrap(),
+                ty: parse_type(&field.ty, &namespace)?,
+            })
+        })
+        .collect::<Result<_>>()?;
+
     Ok(Api::Struct(Struct {
         doc,
         derives,
         struct_token: item.struct_token,
-        name: Pair::new(namespace.clone(), item.ident),
-        brace_token: fields.brace_token,
-        fields: fields
-            .named
-            .into_iter()
-            .map(|field| {
-                Ok(Var {
-                    ident: field.ident.unwrap(),
-                    ty: parse_type(&field.ty, &namespace)?,
-                })
-            })
-            .collect::<Result<_>>()?,
+        name: Pair::new(namespace, item.ident),
+        brace_token: named_fields.brace_token,
+        fields,
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -120,6 +123,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Resu
 
     let mut doc = Doc::new();
     let mut repr = None;
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &item.attrs,
@@ -214,13 +218,12 @@ fn parse_foreign_mod(
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, namespace.clone()) {
+                match parse_extern_type(cx, foreign, lang, trusted, namespace) {
                     Ok(ety) => items.push(ety),
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, namespace.clone())
-            {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, namespace) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -231,7 +234,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, namespace.clone()) {
+                match parse_extern_verbatim(cx, tokens, lang, namespace) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }
@@ -283,9 +286,10 @@ fn parse_extern_type(
     foreign_type: &ForeignItemType,
     lang: Lang,
     trusted: bool,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     let mut doc = Doc::new();
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_type.attrs,
@@ -315,7 +319,7 @@ fn parse_extern_fn(
     cx: &mut Errors,
     foreign_fn: &ForeignItemFn,
     lang: Lang,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
@@ -334,6 +338,7 @@ fn parse_extern_fn(
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_fn.attrs,
@@ -438,7 +443,7 @@ fn parse_extern_verbatim(
     cx: &mut Errors,
     tokens: &TokenStream,
     lang: Lang,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     // type Alias = crate::path::to::Type;
     let parse = |input: ParseStream| -> Result<TypeAlias> {
@@ -455,6 +460,7 @@ fn parse_extern_verbatim(
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
         let mut doc = Doc::new();
+        let mut namespace = namespace.clone();
         attrs::parse(
             cx,
             &attrs,

From 7feb26428160d2054919be1e7c3479849d2b17ea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 02:51:42 +0000
Subject: [PATCH 1334/2232] Parse namespace attribute on foreign mods


---

diff --git a/syntax/file.rs b/syntax/file.rs
index 33340d8..fd6dd98 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -94,7 +94,7 @@ impl Parse for Item {
             RustItem::Struct(item) => Ok(Item::Struct(ItemStruct { attrs, ..item })),
             RustItem::Enum(item) => Ok(Item::Enum(ItemEnum { attrs, ..item })),
             RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
-                attrs: item.attrs,
+                attrs,
                 unsafety,
                 abi: item.abi,
                 brace_token: item.brace_token,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index aa1eef6..a5f8bd1 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -214,16 +214,26 @@ fn parse_foreign_mod(
 
     let trusted = trusted || foreign_mod.unsafety.is_some();
 
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &foreign_mod.attrs,
+        attrs::Parser {
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, namespace) {
+                match parse_extern_type(cx, foreign, lang, trusted, &namespace) {
                     Ok(ety) => items.push(ety),
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, namespace) {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, &namespace) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -234,7 +244,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, namespace) {
+                match parse_extern_verbatim(cx, tokens, lang, &namespace) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }

From c1e475e7bb9b0acb279845ece94949e578845969 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:03:25 +0000
Subject: [PATCH 1335/2232] Merge pull request #444 from dtolnay/namespace


Parse namespace attribute on foreign mods
---

diff --git a/syntax/file.rs b/syntax/file.rs
index 33340d8..fd6dd98 100644
--- a/syntax/file.rs
+++ b/syntax/file.rs
@@ -94,7 +94,7 @@ impl Parse for Item {
             RustItem::Struct(item) => Ok(Item::Struct(ItemStruct { attrs, ..item })),
             RustItem::Enum(item) => Ok(Item::Enum(ItemEnum { attrs, ..item })),
             RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
-                attrs: item.attrs,
+                attrs,
                 unsafety,
                 abi: item.abi,
                 brace_token: item.brace_token,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2136653..a5f8bd1 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -30,11 +30,11 @@ pub fn parse_items(
     let mut apis = Vec::new();
     for item in items {
         match item {
-            Item::Struct(item) => match parse_struct(cx, item, namespace.clone()) {
+            Item::Struct(item) => match parse_struct(cx, item, namespace) {
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item, namespace.clone()) {
+            Item::Enum(item) => match parse_enum(cx, item, namespace) {
                 Ok(enm) => apis.push(enm),
                 Err(err) => cx.push(err),
             },
@@ -52,7 +52,7 @@ pub fn parse_items(
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let struct_token = item.struct_token;
@@ -67,6 +67,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
 
     let mut doc = Doc::new();
     let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &item.attrs,
@@ -78,7 +79,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
         },
     );
 
-    let fields = match item.fields {
+    let named_fields = match item.fields {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
         Fields::Unnamed(_) => {
@@ -86,26 +87,28 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, mut namespace: Namespace) -> 
         }
     };
 
+    let fields = named_fields
+        .named
+        .into_iter()
+        .map(|field| {
+            Ok(Var {
+                ident: field.ident.unwrap(),
+                ty: parse_type(&field.ty, &namespace)?,
+            })
+        })
+        .collect::<Result<_>>()?;
+
     Ok(Api::Struct(Struct {
         doc,
         derives,
         struct_token: item.struct_token,
-        name: Pair::new(namespace.clone(), item.ident),
-        brace_token: fields.brace_token,
-        fields: fields
-            .named
-            .into_iter()
-            .map(|field| {
-                Ok(Var {
-                    ident: field.ident.unwrap(),
-                    ty: parse_type(&field.ty, &namespace)?,
-                })
-            })
-            .collect::<Result<_>>()?,
+        name: Pair::new(namespace, item.ident),
+        brace_token: named_fields.brace_token,
+        fields,
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
     let generics = &item.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
         let enum_token = item.enum_token;
@@ -120,6 +123,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, mut namespace: Namespace) -> Resu
 
     let mut doc = Doc::new();
     let mut repr = None;
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &item.attrs,
@@ -210,17 +214,26 @@ fn parse_foreign_mod(
 
     let trusted = trusted || foreign_mod.unsafety.is_some();
 
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &foreign_mod.attrs,
+        attrs::Parser {
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
     let mut items = Vec::new();
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, namespace.clone()) {
+                match parse_extern_type(cx, foreign, lang, trusted, &namespace) {
                     Ok(ety) => items.push(ety),
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, namespace.clone())
-            {
+            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, &namespace) {
                 Ok(efn) => items.push(efn),
                 Err(err) => cx.push(err),
             },
@@ -231,7 +244,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, namespace.clone()) {
+                match parse_extern_verbatim(cx, tokens, lang, &namespace) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }
@@ -283,9 +296,10 @@ fn parse_extern_type(
     foreign_type: &ForeignItemType,
     lang: Lang,
     trusted: bool,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     let mut doc = Doc::new();
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_type.attrs,
@@ -315,7 +329,7 @@ fn parse_extern_fn(
     cx: &mut Errors,
     foreign_fn: &ForeignItemFn,
     lang: Lang,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
     if !generics.params.is_empty() || generics.where_clause.is_some() {
@@ -334,6 +348,7 @@ fn parse_extern_fn(
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
+    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_fn.attrs,
@@ -438,7 +453,7 @@ fn parse_extern_verbatim(
     cx: &mut Errors,
     tokens: &TokenStream,
     lang: Lang,
-    mut namespace: Namespace,
+    namespace: &Namespace,
 ) -> Result<Api> {
     // type Alias = crate::path::to::Type;
     let parse = |input: ParseStream| -> Result<TypeAlias> {
@@ -455,6 +470,7 @@ fn parse_extern_verbatim(
         let ty: RustType = input.parse()?;
         let semi_token: Token![;] = input.parse()?;
         let mut doc = Doc::new();
+        let mut namespace = namespace.clone();
         attrs::parse(
             cx,
             &attrs,

From a5a1301058ac6d4d1422a9050a57ef14acfb49e4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:03:52 +0000
Subject: [PATCH 1336/2232] Provide rust::Fn call operator in generated header


Even though the generated code does not use them, this avoids a
situation where the user's code includes a generated header (but not
rust/cxx.h) and thus gets the class definition of rust::Fn, but with the
function call operators undefined. Previously they'd have gotten missing
template errors unless they also included rust/cxx.h.

---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index f3240d0..8a25769 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -72,6 +72,10 @@ pub(super) fn write(out: &mut OutFile) {
         builtin.unsafe_bitcopy = true;
     }
 
+    if builtin.rust_fn {
+        include.utility = true;
+    }
+
     if builtin.rust_error {
         include.exception = true;
         builtin.friend_impl = true;
diff --git a/include/cxx.h b/include/cxx.h
index b048e27..0313d34 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -215,7 +215,6 @@ private:
 #endif // CXXBRIDGE05_RUST_VEC
 
 #ifndef CXXBRIDGE05_RUST_FN
-#define CXXBRIDGE05_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -316,6 +315,8 @@ template <typename Exception>
 void panic [[noreturn]] (const char *msg);
 #endif // CXXBRIDGE05_PANIC
 
+#ifndef CXXBRIDGE05_RUST_FN
+#define CXXBRIDGE05_RUST_FN
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -325,6 +326,7 @@ template <typename Ret, typename... Args, bool Throws>
 Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
+#endif // CXXBRIDGE05_RUST_FN
 
 #ifndef CXXBRIDGE05_RUST_BITCOPY
 #define CXXBRIDGE05_RUST_BITCOPY

From 16eeec21f503fda93d86e199536c9a001edfee86 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:10:06 +0000
Subject: [PATCH 1337/2232] Merge pull request #445 from dtolnay/fn


Provide rust::Fn call operator in generated header
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index f3240d0..8a25769 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -72,6 +72,10 @@ pub(super) fn write(out: &mut OutFile) {
         builtin.unsafe_bitcopy = true;
     }
 
+    if builtin.rust_fn {
+        include.utility = true;
+    }
+
     if builtin.rust_error {
         include.exception = true;
         builtin.friend_impl = true;
diff --git a/include/cxx.h b/include/cxx.h
index b048e27..0313d34 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -215,7 +215,6 @@ private:
 #endif // CXXBRIDGE05_RUST_VEC
 
 #ifndef CXXBRIDGE05_RUST_FN
-#define CXXBRIDGE05_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -316,6 +315,8 @@ template <typename Exception>
 void panic [[noreturn]] (const char *msg);
 #endif // CXXBRIDGE05_PANIC
 
+#ifndef CXXBRIDGE05_RUST_FN
+#define CXXBRIDGE05_RUST_FN
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -325,6 +326,7 @@ template <typename Ret, typename... Args, bool Throws>
 Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
+#endif // CXXBRIDGE05_RUST_FN
 
 #ifndef CXXBRIDGE05_RUST_BITCOPY
 #define CXXBRIDGE05_RUST_BITCOPY

From ea6f86c89b3c9a385fca79289ac536e3255368f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:10:27 +0000
Subject: [PATCH 1338/2232] Fill in <utility> header needed by Box<T>::Box(T&&)


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8a25769..72b411c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -62,6 +62,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_box {
         include.new = true;
         include.type_traits = true;
+        include.utility = true;
     }
 
     if builtin.rust_vec {

From 5c830f0d1635f2dd4e676b4963ebeb0229fc9ad4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:11:15 +0000
Subject: [PATCH 1339/2232] Release 0.5.8


---

diff --git a/Cargo.toml b/Cargo.toml
index 7c869e4..267e95e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.7" # remember to update html_root_url
+version = "0.5.8" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.7", path = "macro" }
+cxxbridge-macro = { version = "=0.5.8", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.7", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.8", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.7", path = "gen/build" }
+cxx-build = { version = "=0.5.8", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index de74ed1..70de409 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b694f9a..3839e88 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index fe09585..e5883c9 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 3a6988d..66ca30d 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.4"
+version = "0.6.5"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1a78458..3adcb38 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 2265032..281d2c8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 9750d48..89742fd 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.4"
+version = "0.6.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.7"
+version = "0.5.8"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cxx",
  "proc-macro2",

From ba1551a6ff6caad94b85f1451751951c85ff1914 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 03:13:00 +0000
Subject: [PATCH 1340/2232] Merge 0.5.8 into master


---

diff --git a/Cargo.toml b/Cargo.toml
index 7c869e4..267e95e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.7" # remember to update html_root_url
+version = "0.5.8" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.7", path = "macro" }
+cxxbridge-macro = { version = "=0.5.8", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.7", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.8", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.7", path = "gen/build" }
+cxx-build = { version = "=0.5.8", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index de74ed1..70de409 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b694f9a..3839e88 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index fe09585..e5883c9 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 3a6988d..66ca30d 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.4"
+version = "0.6.5"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8a25769..72b411c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -62,6 +62,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_box {
         include.new = true;
         include.type_traits = true;
+        include.utility = true;
     }
 
     if builtin.rust_vec {
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1a78458..3adcb38 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.7"
+version = "0.5.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 2265032..281d2c8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -349,7 +349,7 @@
 //! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 9750d48..89742fd 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.4"
+version = "0.6.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.7"
+version = "0.5.8"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.7"
+version = "0.5.8"
 dependencies = [
  "cxx",
  "proc-macro2",

From fb6b73c777536666e3e272992596c724a2614ff9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 04:08:14 +0000
Subject: [PATCH 1341/2232] Add rust::Vec push_back and emplace_back


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 72b411c..41d037a 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -69,6 +69,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.array = true;
         include.new = true;
         include.type_traits = true;
+        include.utility = true;
         builtin.panic = true;
         builtin.unsafe_bitcopy = true;
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 69b9f2e..5fe8ee3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1078,6 +1078,16 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
     );
     writeln!(
         out,
+        "void cxxbridge05$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge05$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
         instance,
     );
@@ -1133,6 +1143,28 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(
+        out,
+        "void Vec<{}>::reserve_total(size_t cap) noexcept {{",
+        inner,
+    );
+    writeln!(
+        out,
+        "  return cxxbridge05$rust_vec${}$reserve_total(this, cap);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge05$rust_vec${}$set_len(this, len);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
     writeln!(out, "  return cxxbridge05$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index 0313d34..7dfbbca 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -169,6 +169,7 @@ public:
   size_t size() const noexcept;
   bool empty() const noexcept;
   const T *data() const noexcept;
+  T *data() noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
@@ -176,6 +177,12 @@ public:
   const T &front() const;
   const T &back() const;
 
+  void reserve(size_t new_cap);
+  void push_back(const T &value);
+  void push_back(T &&value);
+  template <class... Args>
+  void emplace_back(Args &&... args);
+
   class const_iterator final {
   public:
     using difference_type = ptrdiff_t;
@@ -207,6 +214,8 @@ public:
 
 private:
   static size_t stride() noexcept;
+  void reserve_total(size_t cap) noexcept;
+  void set_len(size_t len) noexcept;
   void drop() noexcept;
 
   // Size and alignment statically verified by rust_vec.rs.
@@ -498,6 +507,11 @@ bool Vec<T>::empty() const noexcept {
 }
 
 template <typename T>
+T *Vec<T>::data() noexcept {
+  return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());
+}
+
+template <typename T>
 const T &Vec<T>::operator[](size_t n) const noexcept {
   auto data = reinterpret_cast<const char *>(this->data());
   return *reinterpret_cast<const T *>(data + n * this->stride());
@@ -522,6 +536,32 @@ const T &Vec<T>::back() const {
 }
 
 template <typename T>
+void Vec<T>::reserve(size_t new_cap) {
+  this->reserve_total(new_cap);
+}
+
+template <typename T>
+void Vec<T>::push_back(const T &value) {
+  this->emplace_back(value);
+}
+
+template <typename T>
+void Vec<T>::push_back(T &&value) {
+  this->emplace_back(std::move(value));
+}
+
+template <typename T>
+template <typename... Args>
+void Vec<T>::emplace_back(Args &&... args) {
+  auto size = this->size();
+  this->reserve_total(size + 1);
+  ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
+                               size * this->stride()))
+      T(std::forward<Args>(args)...);
+  this->set_len(size + 1);
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b5d3067..0ae7168 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -727,6 +727,8 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
+    let link_reserve_total = format!("{}reserve_total", link_prefix);
+    let link_set_len = format!("{}set_len", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem.rust);
@@ -734,6 +736,8 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
+    let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
+    let local_set_len = format_ident!("{}set_len", local_prefix);
     let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = elem.span();
@@ -759,6 +763,16 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
             (*this).as_ptr()
         }
         #[doc(hidden)]
+        #[export_name = #link_reserve_total]
+        unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
+            (*this).reserve_total(cap);
+        }
+        #[doc(hidden)]
+        #[export_name = #link_set_len]
+        unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
+            (*this).set_len(len);
+        }
+        #[doc(hidden)]
         #[export_name = #link_stride]
         unsafe extern "C" fn #local_stride() -> usize {
             ::std::mem::size_of::<#elem>()
diff --git a/src/cxx.cc b/src/cxx.cc
index 5877b35..cbaecbf 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -267,6 +267,10 @@ void cxxbridge05$unique_ptr$std$string$drop(
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(                       \
+      rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept;                          \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,    \
+                                                  size_t len) noexcept;        \
   size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
@@ -287,6 +291,14 @@ void cxxbridge05$unique_ptr$std$string$drop(
     return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
+  void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept {                     \
+    cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(this, cap);               \
+  }                                                                            \
+  template <>                                                                  \
+  void Vec<CXX_TYPE>::set_len(size_t len) noexcept {                           \
+    cxxbridge05$rust_vec$##RUST_TYPE##$set_len(this, len);                     \
+  }                                                                            \
+  template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
     return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
   }
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index f1a7741..8ddc4a7 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -44,6 +44,17 @@ impl<T> RustVec<T> {
     pub fn as_ptr(&self) -> *const T {
         self.repr.as_ptr()
     }
+
+    pub fn reserve_total(&mut self, cap: usize) {
+        let len = self.repr.len();
+        if cap > len {
+            self.repr.reserve(cap - len);
+        }
+    }
+
+    pub unsafe fn set_len(&mut self, len: usize) {
+        self.repr.set_len(len);
+    }
 }
 
 impl RustVec<RustString> {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 00a7f16..90fbc54 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -35,6 +35,18 @@ macro_rules! rust_vec_shims {
                 }
             }
             attr! {
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$reserve_total")]
+                unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, cap: usize) {
+                    (*this).reserve_total(cap);
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$set_len")]
+                unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) {
+                    (*this).repr.set_len(len);
+                }
+            }
+            attr! {
                 #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7461d66..9e67d7f 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -168,6 +168,7 @@ pub mod ffi {
         fn c_take_rust_vec_string(v: Vec<String>);
         fn c_take_rust_vec_index(v: Vec<u8>);
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
+        fn c_take_rust_vec_shared_push(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c3c797a..2305766 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -356,6 +356,14 @@ void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
+  v.push_back(Shared{3});
+  v.emplace_back(Shared{2});
+  if (v[v.size() - 2].z == 3 && v.back().z == 2) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7fc5633..2217c36 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -130,6 +130,7 @@ void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v);
 void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v);
 void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_push(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
diff --git a/tests/test.rs b/tests/test.rs
index a2c64c3..2bae4d8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -133,6 +133,7 @@ fn test_c_take() {
     let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }];
     check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared_forward_iterator(
         shared_test_vec,
     ));

From 3f76b5d7809c4250c2369171d3eeac540d253b59 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 04:16:14 +0000
Subject: [PATCH 1342/2232] Merge pull request #446 from dtolnay/push


Add rust::Vec push_back and emplace_back
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 72b411c..41d037a 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -69,6 +69,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.array = true;
         include.new = true;
         include.type_traits = true;
+        include.utility = true;
         builtin.panic = true;
         builtin.unsafe_bitcopy = true;
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 69b9f2e..5fe8ee3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1078,6 +1078,16 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
     );
     writeln!(
         out,
+        "void cxxbridge05$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge05$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
         instance,
     );
@@ -1133,6 +1143,28 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(
+        out,
+        "void Vec<{}>::reserve_total(size_t cap) noexcept {{",
+        inner,
+    );
+    writeln!(
+        out,
+        "  return cxxbridge05$rust_vec${}$reserve_total(this, cap);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
+    writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge05$rust_vec${}$set_len(this, len);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
     writeln!(out, "  return cxxbridge05$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index 0313d34..7dfbbca 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -169,6 +169,7 @@ public:
   size_t size() const noexcept;
   bool empty() const noexcept;
   const T *data() const noexcept;
+  T *data() noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
@@ -176,6 +177,12 @@ public:
   const T &front() const;
   const T &back() const;
 
+  void reserve(size_t new_cap);
+  void push_back(const T &value);
+  void push_back(T &&value);
+  template <class... Args>
+  void emplace_back(Args &&... args);
+
   class const_iterator final {
   public:
     using difference_type = ptrdiff_t;
@@ -207,6 +214,8 @@ public:
 
 private:
   static size_t stride() noexcept;
+  void reserve_total(size_t cap) noexcept;
+  void set_len(size_t len) noexcept;
   void drop() noexcept;
 
   // Size and alignment statically verified by rust_vec.rs.
@@ -498,6 +507,11 @@ bool Vec<T>::empty() const noexcept {
 }
 
 template <typename T>
+T *Vec<T>::data() noexcept {
+  return const_cast<T *>(const_cast<const Vec<T> *>(this)->data());
+}
+
+template <typename T>
 const T &Vec<T>::operator[](size_t n) const noexcept {
   auto data = reinterpret_cast<const char *>(this->data());
   return *reinterpret_cast<const T *>(data + n * this->stride());
@@ -522,6 +536,32 @@ const T &Vec<T>::back() const {
 }
 
 template <typename T>
+void Vec<T>::reserve(size_t new_cap) {
+  this->reserve_total(new_cap);
+}
+
+template <typename T>
+void Vec<T>::push_back(const T &value) {
+  this->emplace_back(value);
+}
+
+template <typename T>
+void Vec<T>::push_back(T &&value) {
+  this->emplace_back(std::move(value));
+}
+
+template <typename T>
+template <typename... Args>
+void Vec<T>::emplace_back(Args &&... args) {
+  auto size = this->size();
+  this->reserve_total(size + 1);
+  ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
+                               size * this->stride()))
+      T(std::forward<Args>(args)...);
+  this->set_len(size + 1);
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index a01c1c6..903585e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -775,6 +775,8 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
     let link_data = format!("{}data", link_prefix);
+    let link_reserve_total = format!("{}reserve_total", link_prefix);
+    let link_set_len = format!("{}set_len", link_prefix);
     let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem.rust);
@@ -782,6 +784,8 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
+    let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
+    let local_set_len = format_ident!("{}set_len", local_prefix);
     let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = elem.span();
@@ -807,6 +811,16 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
             (*this).as_ptr()
         }
         #[doc(hidden)]
+        #[export_name = #link_reserve_total]
+        unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
+            (*this).reserve_total(cap);
+        }
+        #[doc(hidden)]
+        #[export_name = #link_set_len]
+        unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
+            (*this).set_len(len);
+        }
+        #[doc(hidden)]
         #[export_name = #link_stride]
         unsafe extern "C" fn #local_stride() -> usize {
             ::std::mem::size_of::<#elem>()
diff --git a/src/cxx.cc b/src/cxx.cc
index 5877b35..cbaecbf 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -267,6 +267,10 @@ void cxxbridge05$unique_ptr$std$string$drop(
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(                       \
+      rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept;                          \
+  void cxxbridge05$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,    \
+                                                  size_t len) noexcept;        \
   size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
@@ -287,6 +291,14 @@ void cxxbridge05$unique_ptr$std$string$drop(
     return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
   }                                                                            \
   template <>                                                                  \
+  void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept {                     \
+    cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(this, cap);               \
+  }                                                                            \
+  template <>                                                                  \
+  void Vec<CXX_TYPE>::set_len(size_t len) noexcept {                           \
+    cxxbridge05$rust_vec$##RUST_TYPE##$set_len(this, len);                     \
+  }                                                                            \
+  template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
     return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
   }
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index f1a7741..8ddc4a7 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -44,6 +44,17 @@ impl<T> RustVec<T> {
     pub fn as_ptr(&self) -> *const T {
         self.repr.as_ptr()
     }
+
+    pub fn reserve_total(&mut self, cap: usize) {
+        let len = self.repr.len();
+        if cap > len {
+            self.repr.reserve(cap - len);
+        }
+    }
+
+    pub unsafe fn set_len(&mut self, len: usize) {
+        self.repr.set_len(len);
+    }
 }
 
 impl RustVec<RustString> {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 00a7f16..90fbc54 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -35,6 +35,18 @@ macro_rules! rust_vec_shims {
                 }
             }
             attr! {
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$reserve_total")]
+                unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, cap: usize) {
+                    (*this).reserve_total(cap);
+                }
+            }
+            attr! {
+                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$set_len")]
+                unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) {
+                    (*this).repr.set_len(len);
+                }
+            }
+            attr! {
                 #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0f3f0d4..4c7cbe4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -169,6 +169,7 @@ pub mod ffi {
         fn c_take_rust_vec_string(v: Vec<String>);
         fn c_take_rust_vec_index(v: Vec<u8>);
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
+        fn c_take_rust_vec_shared_push(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index c3c797a..2305766 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -356,6 +356,14 @@ void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_push(rust::Vec<Shared> v) {
+  v.push_back(Shared{3});
+  v.emplace_back(Shared{2});
+  if (v[v.size() - 2].z == 3 && v.back().z == 2) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v) {
   uint8_t sum = std::accumulate(v.begin(), v.end(), 0);
   if (sum == 200) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7fc5633..2217c36 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -130,6 +130,7 @@ void c_take_rust_vec_ns_shared(rust::Vec<::A::AShared> v);
 void c_take_rust_vec_nested_ns_shared(rust::Vec<::A::B::ABShared> v);
 void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_push(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
diff --git a/tests/test.rs b/tests/test.rs
index a2c64c3..2bae4d8 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -133,6 +133,7 @@ fn test_c_take() {
     let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }];
     check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone()));
+    check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone()));
     check!(ffi::c_take_rust_vec_shared_forward_iterator(
         shared_test_vec,
     ));

From 7614e7706886e247ae5229c8d2a2b90e48a1b6d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 06:55:40 +0000
Subject: [PATCH 1343/2232] Switch to short form url links in rustdoc


---

diff --git a/src/lib.rs b/src/lib.rs
index 281d2c8..d9e3367 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -58,7 +58,7 @@
 //! # Example
 //!
 //! A runnable version of this example is provided under the *demo* directory of
-//! [https://github.com/dtolnay/cxx]. To try it out, run `cargo run` from that
+//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
 //! directory.
 //!
 //! ```no_run
@@ -253,7 +253,7 @@
 //! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
 //! way of invoking the C++ code generator as a standalone command line tool.
 //! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
-//! built from the *gen/cmd* directory of [https://github.com/dtolnay/cxx].
+//! built from the *gen/cmd* directory of <https://github.com/dtolnay/cxx>.
 //!
 //! ```bash
 //! $ cargo install cxxbridge-cmd
@@ -328,7 +328,7 @@
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
-//! in [https://github.com/dtolnay/cxx]. You will need to include this header in
+//! in <https://github.com/dtolnay/cxx>. You will need to include this header in
 //! your C++ code when working with those types.
 //!
 //! The following types are intended to be supported "soon" but are just not
@@ -345,8 +345,6 @@
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 //! </table>
-//!
-//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
 #![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]

From 36c2f84fdf70c1eff8ce5f3e2efed8dfc16e7d46 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 07:04:50 +0000
Subject: [PATCH 1344/2232] Merge pull request #448 from dtolnay/link


Switch to short form url links in rustdoc
---

diff --git a/src/lib.rs b/src/lib.rs
index 281d2c8..d9e3367 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -58,7 +58,7 @@
 //! # Example
 //!
 //! A runnable version of this example is provided under the *demo* directory of
-//! [https://github.com/dtolnay/cxx]. To try it out, run `cargo run` from that
+//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
 //! directory.
 //!
 //! ```no_run
@@ -253,7 +253,7 @@
 //! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate
 //! way of invoking the C++ code generator as a standalone command line tool.
 //! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be
-//! built from the *gen/cmd* directory of [https://github.com/dtolnay/cxx].
+//! built from the *gen/cmd* directory of <https://github.com/dtolnay/cxx>.
 //!
 //! ```bash
 //! $ cargo install cxxbridge-cmd
@@ -328,7 +328,7 @@
 //! </table>
 //!
 //! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file
-//! in [https://github.com/dtolnay/cxx]. You will need to include this header in
+//! in <https://github.com/dtolnay/cxx>. You will need to include this header in
 //! your C++ code when working with those types.
 //!
 //! The following types are intended to be supported "soon" but are just not
@@ -345,8 +345,6 @@
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 //! </table>
-//!
-//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
 
 #![no_std]
 #![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]

From 4ca366fa57662f0753ddb3400ebba592fcba70af Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 07:05:05 +0000
Subject: [PATCH 1345/2232] Switch intro example to blobstore client


---

diff --git a/README.md b/README.md
index 7906020..9c0289b 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,12 @@ function calls Rust's `len()`.
 
 ## Example
 
+In this example we are writing a Rust application that wishes to take advantage
+of an existing C++ client for a large-file blobstore service. The blobstore
+supports a `put` operation for a discontiguous buffer upload. For example we
+might be uploading snapshots of a circular buffer which would tend to consist of
+2 chunks, or fragments of a file spread across memory for some other reason.
+
 A runnable version of this example is provided under the *demo* directory of
 this repo. To try it out, run `cargo run` from that directory.
 
@@ -70,49 +76,49 @@ this repo. To try it out, run `cargo run` from that directory.
 #[cxx::bridge]
 mod ffi {
     // Any shared structs, whose fields will be visible to both languages.
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
+    }
+
+    extern "Rust" {
+        // Zero or more opaque types which both languages can pass around but
+        // only Rust can see the fields.
+        type MultiBuf;
+
+        // Functions implemented in Rust.
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "C" {
+    extern "C++" {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
-        include!("demo/include/demo.h");
+        include!("demo/include/blobstore.h");
 
         // Zero or more opaque types which both languages can pass around but
         // only C++ can see the fields.
-        type ThingC;
+        type BlobstoreClient;
 
         // Functions implemented in C++.
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
-    }
-
-    extern "Rust" {
-        // Zero or more opaque types which both languages can pass around but
-        // only Rust can see the fields.
-        type ThingR;
-
-        // Functions implemented in Rust.
-        fn print_r(r: &ThingR);
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
     }
 }
 ```
 
-Now we simply provide C++ definitions of all the things in the `extern "C"`
-block and Rust definitions of all the things in the `extern "Rust"` block, and
-get to call back and forth safely.
+Now we simply provide Rust definitions of all the things in the `extern "Rust"`
+block and C++ definitions of all the things in the `extern "C++"` block, and get
+to call back and forth safely.
 
 Here are links to the complete set of source files involved in the demo:
 
 - [demo/src/main.rs](demo/src/main.rs)
 - [demo/build.rs](demo/build.rs)
-- [demo/include/demo.h](demo/include/demo.h)
-- [demo/src/demo.cc](demo/src/demo.cc)
+- [demo/include/blobstore.h](demo/include/blobstore.h)
+- [demo/src/blobstore.cc](demo/src/blobstore.cc)
 
 To look at the code generated in both languages for the example by the CXX code
 generators:
diff --git a/demo/BUCK b/demo/BUCK
index 846c149..43b83aa 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -4,8 +4,8 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":blobstore-sys",
         ":bridge",
-        ":demo-sys",
         "//:cxx",
     ],
 )
@@ -13,21 +13,21 @@ rust_binary(
 rust_cxx_bridge(
     name = "bridge",
     src = "src/main.rs",
-    deps = [":demo-include"],
+    deps = [":blobstore-include"],
 )
 
 cxx_library(
-    name = "demo-sys",
-    srcs = ["src/demo.cc"],
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
     compiler_flags = ["-std=c++14"],
     deps = [
+        ":blobstore-include",
         ":bridge/include",
-        ":demo-include",
     ],
 )
 
 cxx_library(
-    name = "demo-include",
-    exported_headers = ["include/demo.h"],
+    name = "blobstore-include",
+    exported_headers = ["include/blobstore.h"],
     deps = ["//:core"],
 )
diff --git a/demo/BUILD b/demo/BUILD
index 5bc8c77..cce8119 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -6,8 +6,8 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":blobstore-sys",
         ":bridge",
-        ":demo-sys",
         "//:cxx",
     ],
 )
@@ -15,21 +15,21 @@ rust_binary(
 rust_cxx_bridge(
     name = "bridge",
     src = "src/main.rs",
-    deps = [":demo-include"],
+    deps = [":blobstore-include"],
 )
 
 cc_library(
-    name = "demo-sys",
-    srcs = ["src/demo.cc"],
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
     copts = ["-std=c++14"],
     deps = [
+        ":blobstore-include",
         ":bridge/include",
-        ":demo-include",
     ],
 )
 
 cc_library(
-    name = "demo-include",
-    hdrs = ["include/demo.h"],
+    name = "blobstore-include",
+    hdrs = ["include/blobstore.h"],
     deps = ["//:core"],
 )
diff --git a/demo/build.rs b/demo/build.rs
index a3c31b3..c1b55cc 100644
--- a/demo/build.rs
+++ b/demo/build.rs
@@ -1,10 +1,10 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
-        .file("src/demo.cc")
+        .file("src/blobstore.cc")
         .flag_if_supported("-std=c++14")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=src/demo.cc");
-    println!("cargo:rerun-if-changed=include/demo.h");
+    println!("cargo:rerun-if-changed=src/blobstore.cc");
+    println!("cargo:rerun-if-changed=include/blobstore.h");
 }
diff --git a/demo/include/blobstore.h b/demo/include/blobstore.h
new file mode 100644
index 0000000..d89583a
--- /dev/null
+++ b/demo/include/blobstore.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "rust/cxx.h"
+#include <memory>
+
+namespace org {
+namespace blobstore {
+
+struct MultiBuf;
+struct BlobMetadata;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+  void tag(uint64_t blobid, rust::Str tag) const;
+  BlobMetadata metadata(uint64_t blobid) const;
+
+private:
+  class impl;
+  std::shared_ptr<impl> impl;
+};
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+
+} // namespace blobstore
+} // namespace org
diff --git a/demo/include/demo.h b/demo/include/demo.h
deleted file mode 100644
index fafc474..0000000
--- a/demo/include/demo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-#include "rust/cxx.h"
-#include <memory>
-#include <string>
-
-namespace org {
-namespace example {
-
-class ThingC {
-public:
-  ThingC(std::string appname);
-  ~ThingC();
-
-  std::string appname;
-};
-
-struct SharedThing;
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
-
-} // namespace example
-} // namespace org
diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
new file mode 100644
index 0000000..a75affc
--- /dev/null
+++ b/demo/src/blobstore.cc
@@ -0,0 +1,71 @@
+#include "demo/include/blobstore.h"
+#include "demo/src/main.rs.h"
+#include <algorithm>
+#include <functional>
+#include <set>
+#include <string>
+#include <unordered_map>
+
+namespace org {
+namespace blobstore {
+
+// Toy implementation of an in-memory blobstore.
+//
+// In reality the implementation of BlobstoreClient could be a large complex C++
+// library.
+class BlobstoreClient::impl {
+  friend BlobstoreClient;
+  using Blob = struct {
+    std::string data;
+    std::set<std::string> tags;
+  };
+  std::unordered_map<uint64_t, Blob> blobs;
+};
+
+BlobstoreClient::BlobstoreClient() : impl(new typename BlobstoreClient::impl) {}
+
+// Upload a new blob and return a blobid that serves as a handle to the blob.
+uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+  std::string contents;
+
+  // Traverse the caller's chunk iterator.
+  //
+  // In reality there might be sophisticated batching of chunks and/or parallel
+  // upload implemented by the blobstore's C++ client.
+  while (true) {
+    auto chunk = next_chunk(buf);
+    if (chunk.size() == 0) {
+      break;
+    }
+    contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+  }
+
+  // Insert into map and provide caller the handle.
+  auto blobid = std::hash<std::string>{}(contents);
+  impl->blobs[blobid] = {std::move(contents), {}};
+  return blobid;
+}
+
+// Add tag to an existing blob.
+void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {
+  impl->blobs[blobid].tags.emplace(tag);
+}
+
+// Retrieve metadata about a blob.
+BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
+  BlobMetadata metadata{};
+  auto blob = impl->blobs.find(blobid);
+  if (blob != impl->blobs.end()) {
+    metadata.size = blob->second.data.size();
+    std::for_each(blob->second.tags.begin(), blob->second.tags.end(),
+                  [&](auto &t) { metadata.tags.emplace_back(t); });
+  }
+  return metadata;
+}
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::make_unique<BlobstoreClient>();
+}
+
+} // namespace blobstore
+} // namespace org
diff --git a/demo/src/demo.cc b/demo/src/demo.cc
deleted file mode 100644
index 79c693f..0000000
--- a/demo/src/demo.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "demo/include/demo.h"
-#include "demo/src/main.rs.h"
-#include <iostream>
-
-namespace org {
-namespace example {
-
-ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
-
-ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::make_unique<ThingC>(std::string(appname));
-}
-
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
-void do_thing(SharedThing state) { print_r(*state.y); }
-
-} // namespace example
-} // namespace org
diff --git a/demo/src/main.rs b/demo/src/main.rs
index 8f62084..10f57e5 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -1,39 +1,59 @@
-#[cxx::bridge(namespace = "org::example")]
+#[cxx::bridge(namespace = "org::blobstore")]
 mod ffi {
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
+    // Shared structs with fields visible to both languages.
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
     }
 
-    extern "C" {
-        include!("demo/include/demo.h");
+    // Rust types and signatures exposed to C++.
+    extern "Rust" {
+        type MultiBuf;
 
-        type ThingC;
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "Rust" {
-        type ThingR;
-        fn print_r(r: &ThingR);
+    // C++ types and signatures exposed to Rust.
+    extern "C++" {
+        include!("demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
     }
 }
 
-pub struct ThingR(usize);
-
-fn print_r(r: &ThingR) {
-    println!("called back with r={}", r.0);
+// An iterator over contiguous chunks of a discontiguous file object.
+//
+// Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
+// over some more complex Rust data structure like a rope, or maybe loading
+// chunks lazily from somewhere.
+pub struct MultiBuf {
+    chunks: Vec<Vec<u8>>,
+    pos: usize,
+}
+pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+    let next = buf.chunks.get(buf.pos);
+    buf.pos += 1;
+    next.map(Vec::as_slice).unwrap_or(&[])
 }
 
 fn main() {
-    let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
-
-    ffi::do_thing(ffi::SharedThing {
-        z: 222,
-        y: Box::new(ThingR(333)),
-        x,
-    });
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+
+    // Add a tag.
+    client.tag(blobid, "rust");
+
+    // Read back the tags.
+    let metadata = client.metadata(blobid);
+    println!("tags = {:?}", metadata.tags);
 }
diff --git a/src/lib.rs b/src/lib.rs
index d9e3367..a7e20fc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,6 +57,13 @@
 //!
 //! # Example
 //!
+//! In this example we are writing a Rust application that wishes to take
+//! advantage of an existing C++ client for a large-file blobstore service. The
+//! blobstore supports a `put` operation for a discontiguous buffer upload. For
+//! example we might be uploading snapshots of a circular buffer which would
+//! tend to consist of 2 chunks, or fragments of a file spread across memory for
+//! some other reason.
+//!
 //! A runnable version of this example is provided under the *demo* directory of
 //! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
 //! directory.
@@ -65,57 +72,57 @@
 //! #[cxx::bridge]
 //! mod ffi {
 //!     // Any shared structs, whose fields will be visible to both languages.
-//!     struct SharedThing {
-//!         z: i32,
-//!         y: Box<ThingR>,
-//!         x: UniquePtr<ThingC>,
+//!     struct BlobMetadata {
+//!         size: usize,
+//!         tags: Vec<String>,
+//!     }
+//!
+//!     extern "Rust" {
+//!         // Zero or more opaque types which both languages can pass around but
+//!         // only Rust can see the fields.
+//!         type MultiBuf;
+//!
+//!         // Functions implemented in Rust.
+//!         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
 //!     }
 //!
-//!     extern "C" {
+//!     extern "C++" {
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
-//!         include!("demo/include/demo.h");
+//!         include!("demo/include/blobstore.h");
 //!
 //!         // Zero or more opaque types which both languages can pass around but
 //!         // only C++ can see the fields.
-//!         type ThingC;
+//!         type BlobstoreClient;
 //!
 //!         // Functions implemented in C++.
-//!         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-//!         fn get_name(thing: &ThingC) -> &CxxString;
-//!         fn do_thing(state: SharedThing);
-//!     }
-//!
-//!     extern "Rust" {
-//!         // Zero or more opaque types which both languages can pass around but
-//!         // only Rust can see the fields.
-//!         type ThingR;
-//!
-//!         // Functions implemented in Rust.
-//!         fn print_r(r: &ThingR);
+//!         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+//!         fn put(&self, parts: &mut MultiBuf) -> u64;
+//!         fn tag(&self, blobid: u64, tag: &str);
+//!         fn metadata(&self, blobid: u64) -> BlobMetadata;
 //!     }
 //! }
 //! #
-//! # pub struct ThingR(usize);
+//! # pub struct MultiBuf;
 //! #
-//! # fn print_r(r: &ThingR) {
-//! #     println!("called back with r={}", r.0);
+//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] {
+//! #     unimplemented!()
 //! # }
 //! #
 //! # fn main() {}
 //! ```
 //!
-//! Now we simply provide C++ definitions of all the things in the `extern "C"`
-//! block and Rust definitions of all the things in the `extern "Rust"` block,
-//! and get to call back and forth safely.
+//! Now we simply provide Rust definitions of all the things in the `extern
+//! "Rust"` block and C++ definitions of all the things in the `extern "C++"`
+//! block, and get to call back and forth safely.
 //!
 //! Here are links to the complete set of source files involved in the demo:
 //!
 //! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
 //! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
-//! - [demo/include/demo.h](https://github.com/dtolnay/cxx/blob/master/demo/include/demo.h)
-//! - [demo/src/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/demo.cc)
+//! - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
+//! - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
 //!
 //! To look at the code generated in both languages for the example by the CXX
 //! code generators:

From ced948046e121392735f42faad8cf304d9ddfd98 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 07:13:11 +0000
Subject: [PATCH 1346/2232] Fix blobstore compilation on macOS and MSVC


macOS:

    src/blobstore.cc:25:73: error: typename specifier refers to non-type member 'impl' in 'org::blobstore::BlobstoreClient'
    BlobstoreClient::BlobstoreClient() : impl(new typename BlobstoreClient::impl) {}
                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
    cxxbridge/crate/demo/include/blobstore.h:20:25: note: referenced member 'impl' is declared here
      std::shared_ptr<impl> impl;
                            ^

MSVC:

    src/blobstore.cc(25): error C2061: syntax error: identifier 'impl'

---

diff --git a/demo/include/blobstore.h b/demo/include/blobstore.h
index d89583a..68a7fc2 100644
--- a/demo/include/blobstore.h
+++ b/demo/include/blobstore.h
@@ -16,8 +16,8 @@ public:
   BlobMetadata metadata(uint64_t blobid) const;
 
 private:
-  class impl;
-  std::shared_ptr<impl> impl;
+  class Impl;
+  std::shared_ptr<Impl> impl;
 };
 
 std::unique_ptr<BlobstoreClient> new_blobstore_client();
diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
index a75affc..0036a32 100644
--- a/demo/src/blobstore.cc
+++ b/demo/src/blobstore.cc
@@ -13,7 +13,7 @@ namespace blobstore {
 //
 // In reality the implementation of BlobstoreClient could be a large complex C++
 // library.
-class BlobstoreClient::impl {
+class BlobstoreClient::Impl {
   friend BlobstoreClient;
   using Blob = struct {
     std::string data;
@@ -22,7 +22,7 @@ class BlobstoreClient::impl {
   std::unordered_map<uint64_t, Blob> blobs;
 };
 
-BlobstoreClient::BlobstoreClient() : impl(new typename BlobstoreClient::impl) {}
+BlobstoreClient::BlobstoreClient() : impl(new BlobstoreClient::Impl) {}
 
 // Upload a new blob and return a blobid that serves as a handle to the blob.
 uint64_t BlobstoreClient::put(MultiBuf &buf) const {

From 9be07db23bd2cd79ab7808209dc2cc3f43f7b4c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 17:34:00 +0000
Subject: [PATCH 1347/2232] Merge pull request #449 from dtolnay/blobstore


Switch intro example to blobstore client
---

diff --git a/README.md b/README.md
index 7906020..9c0289b 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,12 @@ function calls Rust's `len()`.
 
 ## Example
 
+In this example we are writing a Rust application that wishes to take advantage
+of an existing C++ client for a large-file blobstore service. The blobstore
+supports a `put` operation for a discontiguous buffer upload. For example we
+might be uploading snapshots of a circular buffer which would tend to consist of
+2 chunks, or fragments of a file spread across memory for some other reason.
+
 A runnable version of this example is provided under the *demo* directory of
 this repo. To try it out, run `cargo run` from that directory.
 
@@ -70,49 +76,49 @@ this repo. To try it out, run `cargo run` from that directory.
 #[cxx::bridge]
 mod ffi {
     // Any shared structs, whose fields will be visible to both languages.
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
+    }
+
+    extern "Rust" {
+        // Zero or more opaque types which both languages can pass around but
+        // only Rust can see the fields.
+        type MultiBuf;
+
+        // Functions implemented in Rust.
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "C" {
+    extern "C++" {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
-        include!("demo/include/demo.h");
+        include!("demo/include/blobstore.h");
 
         // Zero or more opaque types which both languages can pass around but
         // only C++ can see the fields.
-        type ThingC;
+        type BlobstoreClient;
 
         // Functions implemented in C++.
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
-    }
-
-    extern "Rust" {
-        // Zero or more opaque types which both languages can pass around but
-        // only Rust can see the fields.
-        type ThingR;
-
-        // Functions implemented in Rust.
-        fn print_r(r: &ThingR);
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
     }
 }
 ```
 
-Now we simply provide C++ definitions of all the things in the `extern "C"`
-block and Rust definitions of all the things in the `extern "Rust"` block, and
-get to call back and forth safely.
+Now we simply provide Rust definitions of all the things in the `extern "Rust"`
+block and C++ definitions of all the things in the `extern "C++"` block, and get
+to call back and forth safely.
 
 Here are links to the complete set of source files involved in the demo:
 
 - [demo/src/main.rs](demo/src/main.rs)
 - [demo/build.rs](demo/build.rs)
-- [demo/include/demo.h](demo/include/demo.h)
-- [demo/src/demo.cc](demo/src/demo.cc)
+- [demo/include/blobstore.h](demo/include/blobstore.h)
+- [demo/src/blobstore.cc](demo/src/blobstore.cc)
 
 To look at the code generated in both languages for the example by the CXX code
 generators:
diff --git a/demo/BUCK b/demo/BUCK
index 846c149..43b83aa 100644
--- a/demo/BUCK
+++ b/demo/BUCK
@@ -4,8 +4,8 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":blobstore-sys",
         ":bridge",
-        ":demo-sys",
         "//:cxx",
     ],
 )
@@ -13,21 +13,21 @@ rust_binary(
 rust_cxx_bridge(
     name = "bridge",
     src = "src/main.rs",
-    deps = [":demo-include"],
+    deps = [":blobstore-include"],
 )
 
 cxx_library(
-    name = "demo-sys",
-    srcs = ["src/demo.cc"],
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
     compiler_flags = ["-std=c++14"],
     deps = [
+        ":blobstore-include",
         ":bridge/include",
-        ":demo-include",
     ],
 )
 
 cxx_library(
-    name = "demo-include",
-    exported_headers = ["include/demo.h"],
+    name = "blobstore-include",
+    exported_headers = ["include/blobstore.h"],
     deps = ["//:core"],
 )
diff --git a/demo/BUILD b/demo/BUILD
index 5bc8c77..cce8119 100644
--- a/demo/BUILD
+++ b/demo/BUILD
@@ -6,8 +6,8 @@ rust_binary(
     name = "demo",
     srcs = glob(["src/**/*.rs"]),
     deps = [
+        ":blobstore-sys",
         ":bridge",
-        ":demo-sys",
         "//:cxx",
     ],
 )
@@ -15,21 +15,21 @@ rust_binary(
 rust_cxx_bridge(
     name = "bridge",
     src = "src/main.rs",
-    deps = [":demo-include"],
+    deps = [":blobstore-include"],
 )
 
 cc_library(
-    name = "demo-sys",
-    srcs = ["src/demo.cc"],
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
     copts = ["-std=c++14"],
     deps = [
+        ":blobstore-include",
         ":bridge/include",
-        ":demo-include",
     ],
 )
 
 cc_library(
-    name = "demo-include",
-    hdrs = ["include/demo.h"],
+    name = "blobstore-include",
+    hdrs = ["include/blobstore.h"],
     deps = ["//:core"],
 )
diff --git a/demo/build.rs b/demo/build.rs
index a3c31b3..c1b55cc 100644
--- a/demo/build.rs
+++ b/demo/build.rs
@@ -1,10 +1,10 @@
 fn main() {
     cxx_build::bridge("src/main.rs")
-        .file("src/demo.cc")
+        .file("src/blobstore.cc")
         .flag_if_supported("-std=c++14")
         .compile("cxxbridge-demo");
 
     println!("cargo:rerun-if-changed=src/main.rs");
-    println!("cargo:rerun-if-changed=src/demo.cc");
-    println!("cargo:rerun-if-changed=include/demo.h");
+    println!("cargo:rerun-if-changed=src/blobstore.cc");
+    println!("cargo:rerun-if-changed=include/blobstore.h");
 }
diff --git a/demo/include/blobstore.h b/demo/include/blobstore.h
new file mode 100644
index 0000000..68a7fc2
--- /dev/null
+++ b/demo/include/blobstore.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "rust/cxx.h"
+#include <memory>
+
+namespace org {
+namespace blobstore {
+
+struct MultiBuf;
+struct BlobMetadata;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+  void tag(uint64_t blobid, rust::Str tag) const;
+  BlobMetadata metadata(uint64_t blobid) const;
+
+private:
+  class Impl;
+  std::shared_ptr<Impl> impl;
+};
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+
+} // namespace blobstore
+} // namespace org
diff --git a/demo/include/demo.h b/demo/include/demo.h
deleted file mode 100644
index fafc474..0000000
--- a/demo/include/demo.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-#include "rust/cxx.h"
-#include <memory>
-#include <string>
-
-namespace org {
-namespace example {
-
-class ThingC {
-public:
-  ThingC(std::string appname);
-  ~ThingC();
-
-  std::string appname;
-};
-
-struct SharedThing;
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname);
-const std::string &get_name(const ThingC &thing);
-void do_thing(SharedThing state);
-
-} // namespace example
-} // namespace org
diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
new file mode 100644
index 0000000..0036a32
--- /dev/null
+++ b/demo/src/blobstore.cc
@@ -0,0 +1,71 @@
+#include "demo/include/blobstore.h"
+#include "demo/src/main.rs.h"
+#include <algorithm>
+#include <functional>
+#include <set>
+#include <string>
+#include <unordered_map>
+
+namespace org {
+namespace blobstore {
+
+// Toy implementation of an in-memory blobstore.
+//
+// In reality the implementation of BlobstoreClient could be a large complex C++
+// library.
+class BlobstoreClient::Impl {
+  friend BlobstoreClient;
+  using Blob = struct {
+    std::string data;
+    std::set<std::string> tags;
+  };
+  std::unordered_map<uint64_t, Blob> blobs;
+};
+
+BlobstoreClient::BlobstoreClient() : impl(new BlobstoreClient::Impl) {}
+
+// Upload a new blob and return a blobid that serves as a handle to the blob.
+uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+  std::string contents;
+
+  // Traverse the caller's chunk iterator.
+  //
+  // In reality there might be sophisticated batching of chunks and/or parallel
+  // upload implemented by the blobstore's C++ client.
+  while (true) {
+    auto chunk = next_chunk(buf);
+    if (chunk.size() == 0) {
+      break;
+    }
+    contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+  }
+
+  // Insert into map and provide caller the handle.
+  auto blobid = std::hash<std::string>{}(contents);
+  impl->blobs[blobid] = {std::move(contents), {}};
+  return blobid;
+}
+
+// Add tag to an existing blob.
+void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {
+  impl->blobs[blobid].tags.emplace(tag);
+}
+
+// Retrieve metadata about a blob.
+BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
+  BlobMetadata metadata{};
+  auto blob = impl->blobs.find(blobid);
+  if (blob != impl->blobs.end()) {
+    metadata.size = blob->second.data.size();
+    std::for_each(blob->second.tags.begin(), blob->second.tags.end(),
+                  [&](auto &t) { metadata.tags.emplace_back(t); });
+  }
+  return metadata;
+}
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::make_unique<BlobstoreClient>();
+}
+
+} // namespace blobstore
+} // namespace org
diff --git a/demo/src/demo.cc b/demo/src/demo.cc
deleted file mode 100644
index 79c693f..0000000
--- a/demo/src/demo.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "demo/include/demo.h"
-#include "demo/src/main.rs.h"
-#include <iostream>
-
-namespace org {
-namespace example {
-
-ThingC::ThingC(std::string appname) : appname(std::move(appname)) {}
-
-ThingC::~ThingC() { std::cout << "done with ThingC" << std::endl; }
-
-std::unique_ptr<ThingC> make_demo(rust::Str appname) {
-  return std::make_unique<ThingC>(std::string(appname));
-}
-
-const std::string &get_name(const ThingC &thing) { return thing.appname; }
-
-void do_thing(SharedThing state) { print_r(*state.y); }
-
-} // namespace example
-} // namespace org
diff --git a/demo/src/main.rs b/demo/src/main.rs
index 8f62084..10f57e5 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -1,39 +1,59 @@
-#[cxx::bridge(namespace = "org::example")]
+#[cxx::bridge(namespace = "org::blobstore")]
 mod ffi {
-    struct SharedThing {
-        z: i32,
-        y: Box<ThingR>,
-        x: UniquePtr<ThingC>,
+    // Shared structs with fields visible to both languages.
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
     }
 
-    extern "C" {
-        include!("demo/include/demo.h");
+    // Rust types and signatures exposed to C++.
+    extern "Rust" {
+        type MultiBuf;
 
-        type ThingC;
-        fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-        fn get_name(thing: &ThingC) -> &CxxString;
-        fn do_thing(state: SharedThing);
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "Rust" {
-        type ThingR;
-        fn print_r(r: &ThingR);
+    // C++ types and signatures exposed to Rust.
+    extern "C++" {
+        include!("demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
     }
 }
 
-pub struct ThingR(usize);
-
-fn print_r(r: &ThingR) {
-    println!("called back with r={}", r.0);
+// An iterator over contiguous chunks of a discontiguous file object.
+//
+// Toy implementation uses a Vec<Vec<u8>> but in reality this might be iterating
+// over some more complex Rust data structure like a rope, or maybe loading
+// chunks lazily from somewhere.
+pub struct MultiBuf {
+    chunks: Vec<Vec<u8>>,
+    pos: usize,
+}
+pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+    let next = buf.chunks.get(buf.pos);
+    buf.pos += 1;
+    next.map(Vec::as_slice).unwrap_or(&[])
 }
 
 fn main() {
-    let x = ffi::make_demo("demo of cxx::bridge");
-    println!("this is a {}", ffi::get_name(x.as_ref().unwrap()));
-
-    ffi::do_thing(ffi::SharedThing {
-        z: 222,
-        y: Box::new(ThingR(333)),
-        x,
-    });
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+
+    // Add a tag.
+    client.tag(blobid, "rust");
+
+    // Read back the tags.
+    let metadata = client.metadata(blobid);
+    println!("tags = {:?}", metadata.tags);
 }
diff --git a/src/lib.rs b/src/lib.rs
index d9e3367..a7e20fc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,6 +57,13 @@
 //!
 //! # Example
 //!
+//! In this example we are writing a Rust application that wishes to take
+//! advantage of an existing C++ client for a large-file blobstore service. The
+//! blobstore supports a `put` operation for a discontiguous buffer upload. For
+//! example we might be uploading snapshots of a circular buffer which would
+//! tend to consist of 2 chunks, or fragments of a file spread across memory for
+//! some other reason.
+//!
 //! A runnable version of this example is provided under the *demo* directory of
 //! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
 //! directory.
@@ -65,57 +72,57 @@
 //! #[cxx::bridge]
 //! mod ffi {
 //!     // Any shared structs, whose fields will be visible to both languages.
-//!     struct SharedThing {
-//!         z: i32,
-//!         y: Box<ThingR>,
-//!         x: UniquePtr<ThingC>,
+//!     struct BlobMetadata {
+//!         size: usize,
+//!         tags: Vec<String>,
+//!     }
+//!
+//!     extern "Rust" {
+//!         // Zero or more opaque types which both languages can pass around but
+//!         // only Rust can see the fields.
+//!         type MultiBuf;
+//!
+//!         // Functions implemented in Rust.
+//!         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
 //!     }
 //!
-//!     extern "C" {
+//!     extern "C++" {
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
-//!         include!("demo/include/demo.h");
+//!         include!("demo/include/blobstore.h");
 //!
 //!         // Zero or more opaque types which both languages can pass around but
 //!         // only C++ can see the fields.
-//!         type ThingC;
+//!         type BlobstoreClient;
 //!
 //!         // Functions implemented in C++.
-//!         fn make_demo(appname: &str) -> UniquePtr<ThingC>;
-//!         fn get_name(thing: &ThingC) -> &CxxString;
-//!         fn do_thing(state: SharedThing);
-//!     }
-//!
-//!     extern "Rust" {
-//!         // Zero or more opaque types which both languages can pass around but
-//!         // only Rust can see the fields.
-//!         type ThingR;
-//!
-//!         // Functions implemented in Rust.
-//!         fn print_r(r: &ThingR);
+//!         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+//!         fn put(&self, parts: &mut MultiBuf) -> u64;
+//!         fn tag(&self, blobid: u64, tag: &str);
+//!         fn metadata(&self, blobid: u64) -> BlobMetadata;
 //!     }
 //! }
 //! #
-//! # pub struct ThingR(usize);
+//! # pub struct MultiBuf;
 //! #
-//! # fn print_r(r: &ThingR) {
-//! #     println!("called back with r={}", r.0);
+//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] {
+//! #     unimplemented!()
 //! # }
 //! #
 //! # fn main() {}
 //! ```
 //!
-//! Now we simply provide C++ definitions of all the things in the `extern "C"`
-//! block and Rust definitions of all the things in the `extern "Rust"` block,
-//! and get to call back and forth safely.
+//! Now we simply provide Rust definitions of all the things in the `extern
+//! "Rust"` block and C++ definitions of all the things in the `extern "C++"`
+//! block, and get to call back and forth safely.
 //!
 //! Here are links to the complete set of source files involved in the demo:
 //!
 //! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
 //! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs)
-//! - [demo/include/demo.h](https://github.com/dtolnay/cxx/blob/master/demo/include/demo.h)
-//! - [demo/src/demo.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/demo.cc)
+//! - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
+//! - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
 //!
 //! To look at the code generated in both languages for the example by the CXX
 //! code generators:

From a91ac38a1509d86b0a3c95bfcad41df6799228f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 17:34:59 +0000
Subject: [PATCH 1348/2232] Release 0.5.9


---

diff --git a/Cargo.toml b/Cargo.toml
index 267e95e..f0692ae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.8" # remember to update html_root_url
+version = "0.5.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.8", path = "macro" }
+cxxbridge-macro = { version = "=0.5.9", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.8", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.9", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.8", path = "gen/build" }
+cxx-build = { version = "=0.5.9", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 70de409..cc5f230 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3839e88..3f7b0ea 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e5883c9..f3bdebf 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 66ca30d..2de0f28 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.5"
+version = "0.6.6"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 3adcb38..6b07a07 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index a7e20fc..17d7548 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,7 +354,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.9")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 89742fd..76b95f0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.5"
+version = "0.6.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.8"
+version = "0.5.9"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cxx",
  "proc-macro2",

From 4ab117115718908768df8366ac130bbbb3478331 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 17:35:58 +0000
Subject: [PATCH 1349/2232] Merge 0.5.9 into master


---

diff --git a/Cargo.toml b/Cargo.toml
index 267e95e..f0692ae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.8" # remember to update html_root_url
+version = "0.5.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.8", path = "macro" }
+cxxbridge-macro = { version = "=0.5.9", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.8", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.9", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.8", path = "gen/build" }
+cxx-build = { version = "=0.5.9", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 70de409..cc5f230 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3839e88..3f7b0ea 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e5883c9..f3bdebf 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 66ca30d..2de0f28 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.5"
+version = "0.6.6"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 3adcb38..6b07a07 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.8"
+version = "0.5.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index a7e20fc..17d7548 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,7 +354,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.8")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.9")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 89742fd..76b95f0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.5"
+version = "0.6.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.8"
+version = "0.5.9"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.8"
+version = "0.5.9"
 dependencies = [
  "cxx",
  "proc-macro2",

From ce2982396814a7f78d38ff8e2561b8fbd10b10d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 18:15:13 +0000
Subject: [PATCH 1350/2232] Rename rust::Slice<T> to rust::Slice<const T>


---

diff --git a/README.md b/README.md
index 9c0289b..49b8d09 100644
--- a/README.md
+++ b/README.md
@@ -315,7 +315,7 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5fe8ee3..5708b49 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -432,7 +432,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         }
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(")
+            write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
         }
         _ => {}
     }
@@ -471,7 +471,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         } else if let Type::SliceRefU8(_) = arg.ty {
             write!(
                 out,
-                "::rust::Slice<uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
+                "::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
                 arg.ident,
             );
         } else if out.types.needs_indirect_abi(&arg.ty) {
@@ -688,7 +688,7 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::slice(");
+                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::slice(");
             }
             _ => {}
         }
@@ -714,7 +714,7 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(");
+                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
             }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -885,7 +885,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, "::rust::Str");
         }
         Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<uint8_t>");
+            write!(out, "::rust::Slice<const uint8_t>");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 7dfbbca..83a0ccd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -90,13 +90,16 @@ private:
 #ifndef CXXBRIDGE05_RUST_SLICE
 template <typename T>
 class Slice final {
+  static_assert(std::is_const<T>::value,
+                "&[T] needs to be written as rust::Slice<const T> in C++");
+
 public:
   Slice() noexcept;
-  Slice(const T *, size_t count) noexcept;
+  Slice(T *, size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
 
-  const T *data() const noexcept;
+  T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
 
@@ -108,7 +111,7 @@ private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
-  const T *ptr;
+  T *ptr;
   size_t len;
 };
 #endif // CXXBRIDGE05_RUST_SLICE
@@ -358,13 +361,13 @@ inline size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE05_RUST_SLICE
 #define CXXBRIDGE05_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : ptr(reinterpret_cast<const T *>(this)), len(0) {}
+Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(this)), len(0) {}
 
 template <typename T>
-Slice<T>::Slice(const T *s, size_t count) noexcept : ptr(s), len(count) {}
+Slice<T>::Slice(T *s, size_t count) noexcept : ptr(s), len(count) {}
 
 template <typename T>
-const T *Slice<T>::data() const noexcept {
+T *Slice<T>::data() const noexcept {
   return this->ptr;
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 17d7548..1b71536 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -324,7 +324,7 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2305766..fdf7a14 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -76,10 +76,10 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
-rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared) {
+rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
   (void)shared;
-  return rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA),
-                              sizeof(SLICE_DATA));
+  return rust::Slice<const uint8_t>(
+      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
 }
 
 rust::String c_return_rust_string() { return "2020"; }
@@ -240,7 +240,7 @@ void c_take_str(rust::Str s) {
   }
 }
 
-void c_take_sliceu8(rust::Slice<uint8_t> s) {
+void c_take_sliceu8(rust::Slice<const uint8_t> s) {
   if (std::string(reinterpret_cast<const char *>(s.data()), s.size()) ==
       "2020") {
     cxx_test_suite_set_correct();
@@ -436,7 +436,9 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; }
 
 rust::Str c_try_return_str(rust::Str s) { return s; }
 
-rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t> s) { return s; }
+rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
+  return s;
+}
 
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
@@ -608,7 +610,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<uint8_t>(
+  r_take_sliceu8(rust::Slice<const uint8_t>(
       reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA)));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 2217c36..d231939 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -84,7 +84,7 @@ const size_t &c_return_ns_ref(const ::A::AShared &shared);
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
-rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -114,7 +114,7 @@ void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
-void c_take_sliceu8(rust::Slice<uint8_t> s);
+void c_take_sliceu8(rust::Slice<const uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
@@ -148,7 +148,7 @@ size_t c_fail_return_primitive();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
-rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
+rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();

From c72a9f6ad64a5b924d0ac6ca4de5c49c344060c2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 18:57:50 +0000
Subject: [PATCH 1351/2232] Update cxx::bridge modules to use extern "C++" as the ABI


---

diff --git a/README.md b/README.md
index 9c0289b..a962b52 100644
--- a/README.md
+++ b/README.md
@@ -151,7 +151,7 @@ items:
 - **Functions** &mdash; implemented in either language, callable from the other
   language.
 
-Within the `extern "C"` part of the CXX bridge we list the types and functions
+Within the `extern "C++"` part of the CXX bridge we list the types and functions
 for which C++ is the source of truth, as well as the header(s) that declare
 those APIs. In the future it's possible that this section could be generated
 bindgen-style from the headers but for now we need the signatures written out;
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index 73a25f3..ebb69a8 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -6,7 +6,7 @@ fn test_positive() {
     let rs = quote! {
         #[cxx::bridge]
         mod ffi {
-            extern "C" {
+            extern "C++" {
                 fn in_C();
             }
             extern "Rust" {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index e55a08a..852aacc 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -27,7 +27,7 @@ use syn::parse_macro_input;
 /// is intended to be used.
 ///
 /// The only additional thing to note here is namespace support &mdash; if the
-/// types and functions on the `extern "C"` side of our bridge are in a
+/// types and functions on the `extern "C++"` side of our bridge are in a
 /// namespace, specify that namespace as an argument of the cxx::bridge
 /// attribute macro.
 ///
diff --git a/src/exception.rs b/src/exception.rs
index 0ffca66..f61e8fa 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,7 +1,7 @@
 use alloc::boxed::Box;
 use core::fmt::{self, Debug, Display};
 
-/// Exception thrown from an `extern "C"` function.
+/// Exception thrown from an `extern "C++"` function.
 #[derive(Debug)]
 pub struct Exception {
     pub(crate) what: Box<str>,
diff --git a/src/extern_type.rs b/src/extern_type.rs
index f92ff40..008fdc1 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -30,7 +30,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// # mod file1 {
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         type Demo;
 ///
 ///         fn create_demo() -> UniquePtr<Demo>;
@@ -41,7 +41,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// // file2.rs
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         type Demo = crate::file1::ffi::Demo;
 ///
 ///         fn take_ref_demo(demo: &Demo);
@@ -80,7 +80,7 @@ use self::kind::{Kind, Opaque, Trivial};
 ///
 /// #[cxx::bridge(namespace = "folly")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         include!("rust_cxx_bindings.h");
 ///
 ///         type StringPiece = crate::folly_sys::StringPiece;
diff --git a/src/lib.rs b/src/lib.rs
index 17d7548..c72e362 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -156,7 +156,7 @@
 //! - **Functions** &mdash; implemented in either language, callable from the
 //!   other language.
 //!
-//! Within the `extern "C"` part of the CXX bridge we list the types and
+//! Within the `extern "C++"` part of the CXX bridge we list the types and
 //! functions for which C++ is the source of truth, as well as the header(s)
 //! that declare those APIs. In the future it's possible that this section could
 //! be generated bindgen-style from the headers but for now we need the
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a5f8bd1..b557584 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -280,7 +280,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
         None => {
             return Err(Error::new_spanned(
                 abi,
-                "ABI name is required, extern \"C\" or extern \"Rust\"",
+                "ABI name is required, extern \"C++\" or extern \"Rust\"",
             ));
         }
     };
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 06d7bc7..340e2d7 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -6,7 +6,7 @@ use std::str;
 const BRIDGE0: &str = r#"
     #[cxx::bridge]
     mod ffi {
-        extern "C" {
+        extern "C++" {
             pub fn do_cpp_thing(foo: &str);
         }
     }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index cd76a7d..b5ed579 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -15,7 +15,7 @@ pub mod ffi2 {
     impl UniquePtr<F> {}
     impl UniquePtr<G> {}
 
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9e67d7f..850a2af 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -115,7 +115,7 @@ pub mod ffi {
         i: i32,
     }
 
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C;
@@ -218,7 +218,7 @@ pub mod ffi {
         fn ns_c_take_ns_shared(shared: AShared);
     }
 
-    extern "C" {
+    extern "C++" {
         type COwnedEnum;
     }
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 899d45b..cf53cde 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -3,7 +3,7 @@
 #[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
diff --git a/tests/ui/by_value_not_supported.rs b/tests/ui/by_value_not_supported.rs
index 3ff950a..62bf8d4 100644
--- a/tests/ui/by_value_not_supported.rs
+++ b/tests/ui/by_value_not_supported.rs
@@ -6,7 +6,7 @@ mod ffi {
         s: CxxString,
     }
 
-    extern "C" {
+    extern "C++" {
         type C;
     }
 
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
index ee39fef..b07697a 100644
--- a/tests/ui/disallow_lifetime.rs
+++ b/tests/ui/disallow_lifetime.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type C;
         fn f(&'static self);
     }
diff --git a/tests/ui/include.rs b/tests/ui/include.rs
index 82fa8de..3e848b5 100644
--- a/tests/ui/include.rs
+++ b/tests/ui/include.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         include!("path/to" what);
         include!(<path/to> what);
         include!(<path/to);
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
index 526d036..2318533 100644
--- a/tests/ui/reference_to_reference.rs
+++ b/tests/ui/reference_to_reference.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type ThingC;
         fn repro_c(t: &&ThingC);
     }
diff --git a/tests/ui/reserved_name.rs b/tests/ui/reserved_name.rs
index 27acca5..409e67c 100644
--- a/tests/ui/reserved_name.rs
+++ b/tests/ui/reserved_name.rs
@@ -4,7 +4,7 @@ mod ffi {
         val: usize,
     }
 
-    extern "C" {
+    extern "C++" {
         type Box;
     }
 
diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
index 720ca69..5226ca8 100644
--- a/tests/ui/unique_ptr_to_opaque.rs
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -11,7 +11,7 @@ mod outside {
 
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type C = crate::outside::C;
     }
 
diff --git a/tests/ui/unique_ptr_twice.rs b/tests/ui/unique_ptr_twice.rs
index b6cb4d4..14c6f62 100644
--- a/tests/ui/unique_ptr_twice.rs
+++ b/tests/ui/unique_ptr_twice.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod here {
-    extern "C" {
+    extern "C++" {
         type C;
     }
 
@@ -9,7 +9,7 @@ mod here {
 
 #[cxx::bridge]
 mod there {
-    extern "C" {
+    extern "C++" {
         type C = crate::here::C;
     }
 
diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
index 917e991..13c23ae 100644
--- a/tests/ui/unnamed_receiver.rs
+++ b/tests/ui/unnamed_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type One;
         type Two;
         fn f(&mut self);
diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
index 823bfcf..5b09c56 100644
--- a/tests/ui/unrecognized_receiver.rs
+++ b/tests/ui/unrecognized_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         fn f(self: &Unrecognized);
     }
 }
diff --git a/tests/ui/wrong_type_id.rs b/tests/ui/wrong_type_id.rs
index e3d1380..9137e51 100644
--- a/tests/ui/wrong_type_id.rs
+++ b/tests/ui/wrong_type_id.rs
@@ -1,13 +1,13 @@
 #[cxx::bridge(namespace = "folly")]
 mod here {
-    extern "C" {
+    extern "C++" {
         type StringPiece;
     }
 }
 
 #[cxx::bridge(namespace = "folly")]
 mod there {
-    extern "C" {
+    extern "C++" {
         type ByteRange = crate::here::StringPiece;
     }
 }

From 86857455387b4a986de763dd4084716481ece177 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:03:34 +0000
Subject: [PATCH 1352/2232] Merge pull request #455 from dtolnay/cxxabi


Update cxx::bridge modules to use extern "C++" as the ABI
---

diff --git a/README.md b/README.md
index 9c0289b..a962b52 100644
--- a/README.md
+++ b/README.md
@@ -151,7 +151,7 @@ items:
 - **Functions** &mdash; implemented in either language, callable from the other
   language.
 
-Within the `extern "C"` part of the CXX bridge we list the types and functions
+Within the `extern "C++"` part of the CXX bridge we list the types and functions
 for which C++ is the source of truth, as well as the header(s) that declare
 those APIs. In the future it's possible that this section could be generated
 bindgen-style from the headers but for now we need the signatures written out;
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index 73a25f3..ebb69a8 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -6,7 +6,7 @@ fn test_positive() {
     let rs = quote! {
         #[cxx::bridge]
         mod ffi {
-            extern "C" {
+            extern "C++" {
                 fn in_C();
             }
             extern "Rust" {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index e55a08a..852aacc 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -27,7 +27,7 @@ use syn::parse_macro_input;
 /// is intended to be used.
 ///
 /// The only additional thing to note here is namespace support &mdash; if the
-/// types and functions on the `extern "C"` side of our bridge are in a
+/// types and functions on the `extern "C++"` side of our bridge are in a
 /// namespace, specify that namespace as an argument of the cxx::bridge
 /// attribute macro.
 ///
diff --git a/src/exception.rs b/src/exception.rs
index 0ffca66..f61e8fa 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,7 +1,7 @@
 use alloc::boxed::Box;
 use core::fmt::{self, Debug, Display};
 
-/// Exception thrown from an `extern "C"` function.
+/// Exception thrown from an `extern "C++"` function.
 #[derive(Debug)]
 pub struct Exception {
     pub(crate) what: Box<str>,
diff --git a/src/extern_type.rs b/src/extern_type.rs
index f92ff40..008fdc1 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -30,7 +30,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// # mod file1 {
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         type Demo;
 ///
 ///         fn create_demo() -> UniquePtr<Demo>;
@@ -41,7 +41,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// // file2.rs
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         type Demo = crate::file1::ffi::Demo;
 ///
 ///         fn take_ref_demo(demo: &Demo);
@@ -80,7 +80,7 @@ use self::kind::{Kind, Opaque, Trivial};
 ///
 /// #[cxx::bridge(namespace = "folly")]
 /// pub mod ffi {
-///     extern "C" {
+///     extern "C++" {
 ///         include!("rust_cxx_bindings.h");
 ///
 ///         type StringPiece = crate::folly_sys::StringPiece;
diff --git a/src/lib.rs b/src/lib.rs
index 17d7548..c72e362 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -156,7 +156,7 @@
 //! - **Functions** &mdash; implemented in either language, callable from the
 //!   other language.
 //!
-//! Within the `extern "C"` part of the CXX bridge we list the types and
+//! Within the `extern "C++"` part of the CXX bridge we list the types and
 //! functions for which C++ is the source of truth, as well as the header(s)
 //! that declare those APIs. In the future it's possible that this section could
 //! be generated bindgen-style from the headers but for now we need the
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a5f8bd1..b557584 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -280,7 +280,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
         None => {
             return Err(Error::new_spanned(
                 abi,
-                "ABI name is required, extern \"C\" or extern \"Rust\"",
+                "ABI name is required, extern \"C++\" or extern \"Rust\"",
             ));
         }
     };
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 06d7bc7..340e2d7 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -6,7 +6,7 @@ use std::str;
 const BRIDGE0: &str = r#"
     #[cxx::bridge]
     mod ffi {
-        extern "C" {
+        extern "C++" {
             pub fn do_cpp_thing(foo: &str);
         }
     }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index cd76a7d..b5ed579 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -15,7 +15,7 @@ pub mod ffi2 {
     impl UniquePtr<F> {}
     impl UniquePtr<G> {}
 
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 4c7cbe4..6ece294 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -116,7 +116,7 @@ pub mod ffi {
         i: i32,
     }
 
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C;
@@ -219,7 +219,7 @@ pub mod ffi {
         fn ns_c_take_ns_shared(shared: AShared);
     }
 
-    extern "C" {
+    extern "C++" {
         type COwnedEnum;
     }
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 899d45b..cf53cde 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -3,7 +3,7 @@
 #[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    extern "C" {
+    extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
diff --git a/tests/ui/by_value_not_supported.rs b/tests/ui/by_value_not_supported.rs
index 3ff950a..62bf8d4 100644
--- a/tests/ui/by_value_not_supported.rs
+++ b/tests/ui/by_value_not_supported.rs
@@ -6,7 +6,7 @@ mod ffi {
         s: CxxString,
     }
 
-    extern "C" {
+    extern "C++" {
         type C;
     }
 
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
index ee39fef..b07697a 100644
--- a/tests/ui/disallow_lifetime.rs
+++ b/tests/ui/disallow_lifetime.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type C;
         fn f(&'static self);
     }
diff --git a/tests/ui/include.rs b/tests/ui/include.rs
index 82fa8de..3e848b5 100644
--- a/tests/ui/include.rs
+++ b/tests/ui/include.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         include!("path/to" what);
         include!(<path/to> what);
         include!(<path/to);
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
index 526d036..2318533 100644
--- a/tests/ui/reference_to_reference.rs
+++ b/tests/ui/reference_to_reference.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type ThingC;
         fn repro_c(t: &&ThingC);
     }
diff --git a/tests/ui/reserved_name.rs b/tests/ui/reserved_name.rs
index 27acca5..409e67c 100644
--- a/tests/ui/reserved_name.rs
+++ b/tests/ui/reserved_name.rs
@@ -4,7 +4,7 @@ mod ffi {
         val: usize,
     }
 
-    extern "C" {
+    extern "C++" {
         type Box;
     }
 
diff --git a/tests/ui/unique_ptr_to_opaque.rs b/tests/ui/unique_ptr_to_opaque.rs
index 720ca69..5226ca8 100644
--- a/tests/ui/unique_ptr_to_opaque.rs
+++ b/tests/ui/unique_ptr_to_opaque.rs
@@ -11,7 +11,7 @@ mod outside {
 
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type C = crate::outside::C;
     }
 
diff --git a/tests/ui/unique_ptr_twice.rs b/tests/ui/unique_ptr_twice.rs
index b6cb4d4..14c6f62 100644
--- a/tests/ui/unique_ptr_twice.rs
+++ b/tests/ui/unique_ptr_twice.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod here {
-    extern "C" {
+    extern "C++" {
         type C;
     }
 
@@ -9,7 +9,7 @@ mod here {
 
 #[cxx::bridge]
 mod there {
-    extern "C" {
+    extern "C++" {
         type C = crate::here::C;
     }
 
diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
index 917e991..13c23ae 100644
--- a/tests/ui/unnamed_receiver.rs
+++ b/tests/ui/unnamed_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         type One;
         type Two;
         fn f(&mut self);
diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
index 823bfcf..5b09c56 100644
--- a/tests/ui/unrecognized_receiver.rs
+++ b/tests/ui/unrecognized_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C" {
+    extern "C++" {
         fn f(self: &Unrecognized);
     }
 }
diff --git a/tests/ui/wrong_type_id.rs b/tests/ui/wrong_type_id.rs
index e3d1380..9137e51 100644
--- a/tests/ui/wrong_type_id.rs
+++ b/tests/ui/wrong_type_id.rs
@@ -1,13 +1,13 @@
 #[cxx::bridge(namespace = "folly")]
 mod here {
-    extern "C" {
+    extern "C++" {
         type StringPiece;
     }
 }
 
 #[cxx::bridge(namespace = "folly")]
 mod there {
-    extern "C" {
+    extern "C++" {
         type ByteRange = crate::here::StringPiece;
     }
 }

From ea25ac8df59a608c98c91d3681f921203f71b8c3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:04:08 +0000
Subject: [PATCH 1353/2232] Enforce use of extern "C++" as the ABI string


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index b557584..d62899e 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -285,9 +285,9 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
         }
     };
     match name.value().as_str() {
-        "C" | "C++" => Ok(Lang::Cxx),
+        "C++" => Ok(Lang::Cxx),
         "Rust" => Ok(Lang::Rust),
-        _ => Err(Error::new_spanned(abi, "unrecognized ABI")),
+        _ => Err(Error::new_spanned(abi, "unrecognized ABI, requires either \"C++\" or \"Rust\"")),
     }
 }
 
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 4189507..7c89129 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -4,7 +4,7 @@ error: struct with generic parameters is not supported yet
 3 |     struct Monad<T>;
   |     ^^^^^^^^^^^^^^^
 
-error: unrecognized ABI
+error: unrecognized ABI, requires either "C++" or "Rust"
  --> $DIR/multiple_parse_error.rs:5:5
   |
 5 |     extern "Haskell" {}

From 7be5b1f134433e1dc516c0dfcdd2ea64787a625a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:09:33 +0000
Subject: [PATCH 1354/2232] Enforce unsafe surrounding block on safe-to-call functions


---

diff --git a/README.md b/README.md
index a962b52..28f9ef1 100644
--- a/README.md
+++ b/README.md
@@ -90,7 +90,7 @@ mod ffi {
         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "C++" {
+    unsafe extern "C++" {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
diff --git a/demo/src/main.rs b/demo/src/main.rs
index 10f57e5..dca596a 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -14,7 +14,7 @@ mod ffi {
     }
 
     // C++ types and signatures exposed to Rust.
-    extern "C++" {
+    unsafe extern "C++" {
         include!("demo/include/blobstore.h");
 
         type BlobstoreClient;
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index ebb69a8..d035b52 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -6,7 +6,7 @@ fn test_positive() {
     let rs = quote! {
         #[cxx::bridge]
         mod ffi {
-            extern "C++" {
+            unsafe extern "C++" {
                 fn in_C();
             }
             extern "Rust" {
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 008fdc1..d7634c4 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -30,7 +30,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// # mod file1 {
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         type Demo;
 ///
 ///         fn create_demo() -> UniquePtr<Demo>;
@@ -41,7 +41,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// // file2.rs
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         type Demo = crate::file1::ffi::Demo;
 ///
 ///         fn take_ref_demo(demo: &Demo);
@@ -80,7 +80,7 @@ use self::kind::{Kind, Opaque, Trivial};
 ///
 /// #[cxx::bridge(namespace = "folly")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         include!("rust_cxx_bindings.h");
 ///
 ///         type StringPiece = crate::folly_sys::StringPiece;
diff --git a/src/lib.rs b/src/lib.rs
index c72e362..091c7cc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,7 +86,7 @@
 //!         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
 //!     }
 //!
-//!     extern "C++" {
+//!     unsafe extern "C++" {
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b557584..9509bd8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -204,7 +204,7 @@ fn parse_foreign_mod(
         Lang::Rust => {
             if foreign_mod.unsafety.is_some() {
                 let unsafety = foreign_mod.unsafety;
-                let abi = foreign_mod.abi;
+                let abi = &foreign_mod.abi;
                 let span = quote!(#unsafety #abi);
                 cx.error(span, "extern \"Rust\" block does not need to be unsafe");
             }
@@ -253,6 +253,18 @@ fn parse_foreign_mod(
         }
     }
 
+    if !trusted
+        && items.iter().any(|api| match api {
+            Api::CxxFunction(efn) => efn.unsafety.is_none(),
+            _ => false,
+        })
+    {
+        cx.error(
+            foreign_mod.abi,
+            "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
+        );
+    }
+
     let mut types = items.iter().filter_map(|item| match item {
         Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
         Api::TypeAlias(alias) => Some(&alias.name),
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 340e2d7..a0c9ff4 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -6,7 +6,7 @@ use std::str;
 const BRIDGE0: &str = r#"
     #[cxx::bridge]
     mod ffi {
-        extern "C++" {
+        unsafe extern "C++" {
             pub fn do_cpp_thing(foo: &str);
         }
     }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index b5ed579..8ca5e57 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -15,7 +15,7 @@ pub mod ffi2 {
     impl UniquePtr<F> {}
     impl UniquePtr<G> {}
 
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 6ece294..ed6740d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -116,7 +116,7 @@ pub mod ffi {
         i: i32,
     }
 
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C;
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index cf53cde..aff1b1c 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -3,7 +3,7 @@
 #[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
index b07697a..a4a7b51 100644
--- a/tests/ui/disallow_lifetime.rs
+++ b/tests/ui/disallow_lifetime.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type C;
         fn f(&'static self);
     }
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
index 2318533..91fe160 100644
--- a/tests/ui/reference_to_reference.rs
+++ b/tests/ui/reference_to_reference.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type ThingC;
         fn repro_c(t: &&ThingC);
     }
diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
index 13c23ae..5f53a0a 100644
--- a/tests/ui/unnamed_receiver.rs
+++ b/tests/ui/unnamed_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type One;
         type Two;
         fn f(&mut self);
diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
index 5b09c56..eee8259 100644
--- a/tests/ui/unrecognized_receiver.rs
+++ b/tests/ui/unrecognized_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         fn f(self: &Unrecognized);
     }
 }

From 727ea000da773a77477fde8d4995aa7cb25f3047 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:15:38 +0000
Subject: [PATCH 1355/2232] Update to rust 1.48 toolchain to support unsafe extern block


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 26b2722..be15d31 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
         include:
           - rust: nightly
           - rust: beta
-          - rust: stable
-          - rust: 1.43.0
+          #- rust: stable
+          #- rust: 1.48.0
           - name: macOS
             rust: nightly
             os: macos
@@ -51,7 +51,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@stable
+      - uses: dtolnay/rust-toolchain@beta
       - uses: actions/setup-java@v1
         with:
           java-version: 11
diff --git a/README.md b/README.md
index 28f9ef1..0ae6686 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ cxx = "0.5"
 cxx-build = "0.5"
 ```
 
-*Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
+*Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
 *[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
diff --git a/WORKSPACE b/WORKSPACE
index 6093eee..3fc2f90 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -25,15 +25,17 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_47_linux",
+    name = "rust_1_48_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.47.0",
+    iso_date = "2020-11-08",
+    version = "beta",
 )
 
 rust_repository_set(
-    name = "rust_1_47_darwin",
+    name = "rust_1_48_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.47.0",
+    iso_date = "2020-11-08",
+    version = "beta",
 )
 
 vendor(
diff --git a/src/lib.rs b/src/lib.rs
index 091c7cc..04266fb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
+//! *Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
 //! *[Release notes](https://github.com/dtolnay/cxx/releases)*
 //!
 //! <br>

From 6bd29d526b87e901d4d7ab5b5e6304eb74fe8adf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:33:02 +0000
Subject: [PATCH 1356/2232] Merge pull request #453 from dtolnay/sliceconst


Rename rust::Slice<T> to rust::Slice<const T>
---

diff --git a/README.md b/README.md
index a962b52..26a8ba7 100644
--- a/README.md
+++ b/README.md
@@ -315,7 +315,7 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5fe8ee3..5708b49 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -432,7 +432,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         }
         Some(Type::SliceRefU8(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(")
+            write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
         }
         _ => {}
     }
@@ -471,7 +471,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         } else if let Type::SliceRefU8(_) = arg.ty {
             write!(
                 out,
-                "::rust::Slice<uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
+                "::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
                 arg.ident,
             );
         } else if out.types.needs_indirect_abi(&arg.ty) {
@@ -688,7 +688,7 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::slice(");
+                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::slice(");
             }
             _ => {}
         }
@@ -714,7 +714,7 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(");
+                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
             }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -885,7 +885,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, "::rust::Str");
         }
         Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<uint8_t>");
+            write!(out, "::rust::Slice<const uint8_t>");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 7dfbbca..83a0ccd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -90,13 +90,16 @@ private:
 #ifndef CXXBRIDGE05_RUST_SLICE
 template <typename T>
 class Slice final {
+  static_assert(std::is_const<T>::value,
+                "&[T] needs to be written as rust::Slice<const T> in C++");
+
 public:
   Slice() noexcept;
-  Slice(const T *, size_t count) noexcept;
+  Slice(T *, size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
 
-  const T *data() const noexcept;
+  T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
 
@@ -108,7 +111,7 @@ private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
-  const T *ptr;
+  T *ptr;
   size_t len;
 };
 #endif // CXXBRIDGE05_RUST_SLICE
@@ -358,13 +361,13 @@ inline size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE05_RUST_SLICE
 #define CXXBRIDGE05_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : ptr(reinterpret_cast<const T *>(this)), len(0) {}
+Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(this)), len(0) {}
 
 template <typename T>
-Slice<T>::Slice(const T *s, size_t count) noexcept : ptr(s), len(count) {}
+Slice<T>::Slice(T *s, size_t count) noexcept : ptr(s), len(count) {}
 
 template <typename T>
-const T *Slice<T>::data() const noexcept {
+T *Slice<T>::data() const noexcept {
   return this->ptr;
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index c72e362..9a3e04e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -324,7 +324,7 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2305766..fdf7a14 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -76,10 +76,10 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
-rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared) {
+rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
   (void)shared;
-  return rust::Slice<uint8_t>(reinterpret_cast<const uint8_t *>(SLICE_DATA),
-                              sizeof(SLICE_DATA));
+  return rust::Slice<const uint8_t>(
+      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
 }
 
 rust::String c_return_rust_string() { return "2020"; }
@@ -240,7 +240,7 @@ void c_take_str(rust::Str s) {
   }
 }
 
-void c_take_sliceu8(rust::Slice<uint8_t> s) {
+void c_take_sliceu8(rust::Slice<const uint8_t> s) {
   if (std::string(reinterpret_cast<const char *>(s.data()), s.size()) ==
       "2020") {
     cxx_test_suite_set_correct();
@@ -436,7 +436,9 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; }
 
 rust::Str c_try_return_str(rust::Str s) { return s; }
 
-rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t> s) { return s; }
+rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
+  return s;
+}
 
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
@@ -608,7 +610,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<uint8_t>(
+  r_take_sliceu8(rust::Slice<const uint8_t>(
       reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA)));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 2217c36..d231939 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -84,7 +84,7 @@ const size_t &c_return_ns_ref(const ::A::AShared &shared);
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
-rust::Slice<uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -114,7 +114,7 @@ void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
-void c_take_sliceu8(rust::Slice<uint8_t> s);
+void c_take_sliceu8(rust::Slice<const uint8_t> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
@@ -148,7 +148,7 @@ size_t c_fail_return_primitive();
 rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
-rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
+rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();

From 1126426ab7ae56d46f4f8a30da1073f10d789e1f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 19:33:37 +0000
Subject: [PATCH 1357/2232] Merge pull request #454 from dtolnay/externcxx


Enforce use of extern "C++" as the ABI string
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index b557584..d62899e 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -285,9 +285,9 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
         }
     };
     match name.value().as_str() {
-        "C" | "C++" => Ok(Lang::Cxx),
+        "C++" => Ok(Lang::Cxx),
         "Rust" => Ok(Lang::Rust),
-        _ => Err(Error::new_spanned(abi, "unrecognized ABI")),
+        _ => Err(Error::new_spanned(abi, "unrecognized ABI, requires either \"C++\" or \"Rust\"")),
     }
 }
 
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 4189507..7c89129 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -4,7 +4,7 @@ error: struct with generic parameters is not supported yet
 3 |     struct Monad<T>;
   |     ^^^^^^^^^^^^^^^
 
-error: unrecognized ABI
+error: unrecognized ABI, requires either "C++" or "Rust"
  --> $DIR/multiple_parse_error.rs:5:5
   |
 5 |     extern "Haskell" {}

From 1d0266aaa3161838a5a7ad23fd661eca792f4484 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 20:00:32 +0000
Subject: [PATCH 1358/2232] Warn on unsupported rust toolchain version


---

diff --git a/build.rs b/build.rs
index 57b3e52..73c6228 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,6 @@
 use std::env;
 use std::path::Path;
+use std::process::Command;
 
 fn main() {
     cc::Build::new()
@@ -8,11 +9,40 @@ fn main() {
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge05");
+
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
+
     if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
         let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
         println!("cargo:HEADER={}", cxx_h.to_string_lossy());
     }
+
+    if let Some(rustc) = rustc_version() {
+        if rustc.minor < 43 {
+            println!("cargo:warning=The cxx crate requires a rustc version 1.43.0 or newer.");
+            println!(
+                "cargo:warning=You appear to be building with: {}",
+                rustc.version,
+            );
+        }
+    }
+}
+
+struct RustVersion {
+    version: String,
+    minor: u32,
+}
+
+fn rustc_version() -> Option<RustVersion> {
+    let rustc = env::var_os("RUSTC")?;
+    let output = Command::new(rustc).arg("--version").output().ok()?;
+    let version = String::from_utf8(output.stdout).ok()?;
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    let minor = pieces.next()?.parse().ok()?;
+    Some(RustVersion { version, minor })
 }

From a23053bd26e1486d35794f156967dbc230a8f31e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 20:11:21 +0000
Subject: [PATCH 1359/2232] Merge pull request #457 from dtolnay/versioncheck


Warn on unsupported rust toolchain version
---

diff --git a/build.rs b/build.rs
index 57b3e52..73c6228 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,6 @@
 use std::env;
 use std::path::Path;
+use std::process::Command;
 
 fn main() {
     cc::Build::new()
@@ -8,11 +9,40 @@ fn main() {
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge05");
+
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
+
     if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
         let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
         println!("cargo:HEADER={}", cxx_h.to_string_lossy());
     }
+
+    if let Some(rustc) = rustc_version() {
+        if rustc.minor < 43 {
+            println!("cargo:warning=The cxx crate requires a rustc version 1.43.0 or newer.");
+            println!(
+                "cargo:warning=You appear to be building with: {}",
+                rustc.version,
+            );
+        }
+    }
+}
+
+struct RustVersion {
+    version: String,
+    minor: u32,
+}
+
+fn rustc_version() -> Option<RustVersion> {
+    let rustc = env::var_os("RUSTC")?;
+    let output = Command::new(rustc).arg("--version").output().ok()?;
+    let version = String::from_utf8(output.stdout).ok()?;
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    let minor = pieces.next()?.parse().ok()?;
+    Some(RustVersion { version, minor })
 }

From 7bb26a76f516daf60c2c343a2b009332507ef723 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 20:12:27 +0000
Subject: [PATCH 1360/2232] Merge pr/457 into pr/456


---

diff --git a/build.rs b/build.rs
index 57b3e52..73c6228 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,6 @@
 use std::env;
 use std::path::Path;
+use std::process::Command;
 
 fn main() {
     cc::Build::new()
@@ -8,11 +9,40 @@ fn main() {
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
         .compile("cxxbridge05");
+
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
     println!("cargo:rustc-cfg=built_with_cargo");
+
     if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
         let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h");
         println!("cargo:HEADER={}", cxx_h.to_string_lossy());
     }
+
+    if let Some(rustc) = rustc_version() {
+        if rustc.minor < 43 {
+            println!("cargo:warning=The cxx crate requires a rustc version 1.43.0 or newer.");
+            println!(
+                "cargo:warning=You appear to be building with: {}",
+                rustc.version,
+            );
+        }
+    }
+}
+
+struct RustVersion {
+    version: String,
+    minor: u32,
+}
+
+fn rustc_version() -> Option<RustVersion> {
+    let rustc = env::var_os("RUSTC")?;
+    let output = Command::new(rustc).arg("--version").output().ok()?;
+    let version = String::from_utf8(output.stdout).ok()?;
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    let minor = pieces.next()?.parse().ok()?;
+    Some(RustVersion { version, minor })
 }

From bc413be957a675ceb60e34049534238bcc08bdd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 20:13:49 +0000
Subject: [PATCH 1361/2232] Raise rustc checked in build script to 1.48


---

diff --git a/build.rs b/build.rs
index 73c6228..ae3ef67 100644
--- a/build.rs
+++ b/build.rs
@@ -20,8 +20,8 @@ fn main() {
     }
 
     if let Some(rustc) = rustc_version() {
-        if rustc.minor < 43 {
-            println!("cargo:warning=The cxx crate requires a rustc version 1.43.0 or newer.");
+        if rustc.minor < 48 {
+            println!("cargo:warning=The cxx crate requires a rustc version 1.48.0 or newer.");
             println!(
                 "cargo:warning=You appear to be building with: {}",
                 rustc.version,

From cbc2a1040d31b1ab58f2fa7b88ec3e7283caf825 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 23:53:23 +0000
Subject: [PATCH 1362/2232] Revert "Fix blobstore compilation on macOS and MSVC"


This reverts commit ced948046e121392735f42faad8cf304d9ddfd98.

---

diff --git a/demo/include/blobstore.h b/demo/include/blobstore.h
index 68a7fc2..d89583a 100644
--- a/demo/include/blobstore.h
+++ b/demo/include/blobstore.h
@@ -16,8 +16,8 @@ public:
   BlobMetadata metadata(uint64_t blobid) const;
 
 private:
-  class Impl;
-  std::shared_ptr<Impl> impl;
+  class impl;
+  std::shared_ptr<impl> impl;
 };
 
 std::unique_ptr<BlobstoreClient> new_blobstore_client();
diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
index 0036a32..a75affc 100644
--- a/demo/src/blobstore.cc
+++ b/demo/src/blobstore.cc
@@ -13,7 +13,7 @@ namespace blobstore {
 //
 // In reality the implementation of BlobstoreClient could be a large complex C++
 // library.
-class BlobstoreClient::Impl {
+class BlobstoreClient::impl {
   friend BlobstoreClient;
   using Blob = struct {
     std::string data;
@@ -22,7 +22,7 @@ class BlobstoreClient::Impl {
   std::unordered_map<uint64_t, Blob> blobs;
 };
 
-BlobstoreClient::BlobstoreClient() : impl(new BlobstoreClient::Impl) {}
+BlobstoreClient::BlobstoreClient() : impl(new typename BlobstoreClient::impl) {}
 
 // Upload a new blob and return a blobid that serves as a handle to the blob.
 uint64_t BlobstoreClient::put(MultiBuf &buf) const {

From e0d261ba2b031c9a8339f4561d6781519173b405 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 23:53:23 +0000
Subject: [PATCH 1363/2232] typename -> class to fix macOS and MSVC


---

diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
index a75affc..3b56d86 100644
--- a/demo/src/blobstore.cc
+++ b/demo/src/blobstore.cc
@@ -22,7 +22,7 @@ class BlobstoreClient::impl {
   std::unordered_map<uint64_t, Blob> blobs;
 };
 
-BlobstoreClient::BlobstoreClient() : impl(new typename BlobstoreClient::impl) {}
+BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {}
 
 // Upload a new blob and return a blobid that serves as a handle to the blob.
 uint64_t BlobstoreClient::put(MultiBuf &buf) const {

From 4e8c49ada4c758bc179defebc1022c386c367e7f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 23:53:23 +0000
Subject: [PATCH 1364/2232] Prefer typename consistently where supported by c++11


---

diff --git a/include/cxx.h b/include/cxx.h
index 7dfbbca..aaafc3b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,7 +180,7 @@ public:
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
-  template <class... Args>
+  template <typename... Args>
   void emplace_back(Args &&... args);
 
   class const_iterator final {
@@ -299,11 +299,11 @@ struct IsRelocatable;
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;
-template <class T>
+template <typename T>
 using slice = Slice<T>;
-template <class T>
+template <typename T>
 using box = Box<T>;
-template <class T>
+template <typename T>
 using vec = Vec<T>;
 using error = Error;
 template <typename Signature, bool Throws = false>

From 4bf55ef3aae827e179eae814ca1b078e4f490050 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 11 2020 23:53:24 +0000
Subject: [PATCH 1365/2232] cbegin/cend to iterate over const tags


---

diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
index 3b56d86..7cf40df 100644
--- a/demo/src/blobstore.cc
+++ b/demo/src/blobstore.cc
@@ -57,7 +57,7 @@ BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
   auto blob = impl->blobs.find(blobid);
   if (blob != impl->blobs.end()) {
     metadata.size = blob->second.data.size();
-    std::for_each(blob->second.tags.begin(), blob->second.tags.end(),
+    std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
                   [&](auto &t) { metadata.tags.emplace_back(t); });
   }
   return metadata;

From 48e98d8995c0bcbb7aafd2726393e6b3f7526845 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 12 2020 23:28:26 +0000
Subject: [PATCH 1366/2232] Update readme Details section to refer to new code example


---

diff --git a/README.md b/README.md
index a962b52..3cff4a6 100644
--- a/README.md
+++ b/README.md
@@ -151,19 +151,19 @@ items:
 - **Functions** &mdash; implemented in either language, callable from the other
   language.
 
-Within the `extern "C++"` part of the CXX bridge we list the types and functions
-for which C++ is the source of truth, as well as the header(s) that declare
-those APIs. In the future it's possible that this section could be generated
-bindgen-style from the headers but for now we need the signatures written out;
-static assertions will verify that they are accurate.
-
-Within the `extern "Rust"` part, we list types and functions for which Rust is
-the source of truth. These all implicitly refer to the `super` module, the
-parent module of the CXX bridge. You can think of the two items listed in the
-example above as being like `use super::ThingR` and `use super::print_r` except
-re-exported to C++. The parent module will either contain the definitions
-directly for simple things, or contain the relevant `use` statements to bring
-them into scope from elsewhere.
+Within the `extern "Rust"` part of the CXX bridge we list the types and
+functions for which Rust is the source of truth. These all implicitly refer to
+the `super` module, the parent module of the CXX bridge. You can think of the
+two items listed in the example above as being like `use super::MultiBuf` and
+`use super::next_chunk` except re-exported to C++. The parent module will either
+contain the definitions directly for simple things, or contain the relevant
+`use` statements to bring them into scope from elsewhere.
+
+Within the `extern "C++"` part, we list types and functions for which C++ is the
+source of truth, as well as the header(s) that declare those APIs. In the future
+it's possible that this section could be generated bindgen-style from the
+headers but for now we need the signatures written out; static assertions will
+verify that they are accurate.
 
 Your function implementations themselves, whether in C++ or Rust, *do not* need
 to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the right shims
diff --git a/src/lib.rs b/src/lib.rs
index c72e362..6ac5309 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -156,20 +156,20 @@
 //! - **Functions** &mdash; implemented in either language, callable from the
 //!   other language.
 //!
-//! Within the `extern "C++"` part of the CXX bridge we list the types and
-//! functions for which C++ is the source of truth, as well as the header(s)
-//! that declare those APIs. In the future it's possible that this section could
-//! be generated bindgen-style from the headers but for now we need the
-//! signatures written out; static assertions will verify that they are
-//! accurate.
-//!
-//! Within the `extern "Rust"` part, we list types and functions for which Rust
-//! is the source of truth. These all implicitly refer to the `super` module,
-//! the parent module of the CXX bridge. You can think of the two items listed
-//! in the example above as being like `use super::ThingR` and `use
-//! super::print_r` except re-exported to C++. The parent module will either
-//! contain the definitions directly for simple things, or contain the relevant
-//! `use` statements to bring them into scope from elsewhere.
+//! Within the `extern "Rust"` part of the CXX bridge we list the types and
+//! functions for which Rust is the source of truth. These all implicitly refer
+//! to the `super` module, the parent module of the CXX bridge. You can think of
+//! the two items listed in the example above as being like `use
+//! super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The
+//! parent module will either contain the definitions directly for simple
+//! things, or contain the relevant `use` statements to bring them into scope
+//! from elsewhere.
+//!
+//! Within the `extern "C++"` part, we list types and functions for which C++ is
+//! the source of truth, as well as the header(s) that declare those APIs. In
+//! the future it's possible that this section could be generated bindgen-style
+//! from the headers but for now we need the signatures written out; static
+//! assertions will verify that they are accurate.
 //!
 //! Your function implementations themselves, whether in C++ or Rust, *do not*
 //! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the

From d9deed1186489da11bd4799d0711910978b07333 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 12 2020 23:28:42 +0000
Subject: [PATCH 1367/2232] Merge demo tweaks into master


---

diff --git a/README.md b/README.md
index 26a8ba7..e27f9e7 100644
--- a/README.md
+++ b/README.md
@@ -151,19 +151,19 @@ items:
 - **Functions** &mdash; implemented in either language, callable from the other
   language.
 
-Within the `extern "C++"` part of the CXX bridge we list the types and functions
-for which C++ is the source of truth, as well as the header(s) that declare
-those APIs. In the future it's possible that this section could be generated
-bindgen-style from the headers but for now we need the signatures written out;
-static assertions will verify that they are accurate.
-
-Within the `extern "Rust"` part, we list types and functions for which Rust is
-the source of truth. These all implicitly refer to the `super` module, the
-parent module of the CXX bridge. You can think of the two items listed in the
-example above as being like `use super::ThingR` and `use super::print_r` except
-re-exported to C++. The parent module will either contain the definitions
-directly for simple things, or contain the relevant `use` statements to bring
-them into scope from elsewhere.
+Within the `extern "Rust"` part of the CXX bridge we list the types and
+functions for which Rust is the source of truth. These all implicitly refer to
+the `super` module, the parent module of the CXX bridge. You can think of the
+two items listed in the example above as being like `use super::MultiBuf` and
+`use super::next_chunk` except re-exported to C++. The parent module will either
+contain the definitions directly for simple things, or contain the relevant
+`use` statements to bring them into scope from elsewhere.
+
+Within the `extern "C++"` part, we list types and functions for which C++ is the
+source of truth, as well as the header(s) that declare those APIs. In the future
+it's possible that this section could be generated bindgen-style from the
+headers but for now we need the signatures written out; static assertions will
+verify that they are accurate.
 
 Your function implementations themselves, whether in C++ or Rust, *do not* need
 to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the right shims
diff --git a/demo/include/blobstore.h b/demo/include/blobstore.h
index 68a7fc2..d89583a 100644
--- a/demo/include/blobstore.h
+++ b/demo/include/blobstore.h
@@ -16,8 +16,8 @@ public:
   BlobMetadata metadata(uint64_t blobid) const;
 
 private:
-  class Impl;
-  std::shared_ptr<Impl> impl;
+  class impl;
+  std::shared_ptr<impl> impl;
 };
 
 std::unique_ptr<BlobstoreClient> new_blobstore_client();
diff --git a/demo/src/blobstore.cc b/demo/src/blobstore.cc
index 0036a32..7cf40df 100644
--- a/demo/src/blobstore.cc
+++ b/demo/src/blobstore.cc
@@ -13,7 +13,7 @@ namespace blobstore {
 //
 // In reality the implementation of BlobstoreClient could be a large complex C++
 // library.
-class BlobstoreClient::Impl {
+class BlobstoreClient::impl {
   friend BlobstoreClient;
   using Blob = struct {
     std::string data;
@@ -22,7 +22,7 @@ class BlobstoreClient::Impl {
   std::unordered_map<uint64_t, Blob> blobs;
 };
 
-BlobstoreClient::BlobstoreClient() : impl(new BlobstoreClient::Impl) {}
+BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {}
 
 // Upload a new blob and return a blobid that serves as a handle to the blob.
 uint64_t BlobstoreClient::put(MultiBuf &buf) const {
@@ -57,7 +57,7 @@ BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
   auto blob = impl->blobs.find(blobid);
   if (blob != impl->blobs.end()) {
     metadata.size = blob->second.data.size();
-    std::for_each(blob->second.tags.begin(), blob->second.tags.end(),
+    std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
                   [&](auto &t) { metadata.tags.emplace_back(t); });
   }
   return metadata;
diff --git a/include/cxx.h b/include/cxx.h
index 83a0ccd..3c84330 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -183,7 +183,7 @@ public:
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
-  template <class... Args>
+  template <typename... Args>
   void emplace_back(Args &&... args);
 
   class const_iterator final {
@@ -302,11 +302,11 @@ struct IsRelocatable;
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;
-template <class T>
+template <typename T>
 using slice = Slice<T>;
-template <class T>
+template <typename T>
 using box = Box<T>;
-template <class T>
+template <typename T>
 using vec = Vec<T>;
 using error = Error;
 template <typename Signature, bool Throws = false>
diff --git a/src/lib.rs b/src/lib.rs
index 9a3e04e..594ee73 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -156,20 +156,20 @@
 //! - **Functions** &mdash; implemented in either language, callable from the
 //!   other language.
 //!
-//! Within the `extern "C++"` part of the CXX bridge we list the types and
-//! functions for which C++ is the source of truth, as well as the header(s)
-//! that declare those APIs. In the future it's possible that this section could
-//! be generated bindgen-style from the headers but for now we need the
-//! signatures written out; static assertions will verify that they are
-//! accurate.
-//!
-//! Within the `extern "Rust"` part, we list types and functions for which Rust
-//! is the source of truth. These all implicitly refer to the `super` module,
-//! the parent module of the CXX bridge. You can think of the two items listed
-//! in the example above as being like `use super::ThingR` and `use
-//! super::print_r` except re-exported to C++. The parent module will either
-//! contain the definitions directly for simple things, or contain the relevant
-//! `use` statements to bring them into scope from elsewhere.
+//! Within the `extern "Rust"` part of the CXX bridge we list the types and
+//! functions for which Rust is the source of truth. These all implicitly refer
+//! to the `super` module, the parent module of the CXX bridge. You can think of
+//! the two items listed in the example above as being like `use
+//! super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The
+//! parent module will either contain the definitions directly for simple
+//! things, or contain the relevant `use` statements to bring them into scope
+//! from elsewhere.
+//!
+//! Within the `extern "C++"` part, we list types and functions for which C++ is
+//! the source of truth, as well as the header(s) that declare those APIs. In
+//! the future it's possible that this section could be generated bindgen-style
+//! from the headers but for now we need the signatures written out; static
+//! assertions will verify that they are accurate.
 //!
 //! Your function implementations themselves, whether in C++ or Rust, *do not*
 //! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the

From d80e846bd1994ebc26146f55c7f313ff11d7be73 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:24:11 +0000
Subject: [PATCH 1368/2232] Add book build script


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 73b8186..00104c8 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -15,16 +15,14 @@ jobs:
       - uses: actions/checkout@v2
 
       - name: Get mdBook
-        working-directory: book
         run: |
           export MDBOOK_VERSION="v0.4.4"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
           export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
-          curl -Lf "${MDBOOK_URL}" | tar -xz
+          curl -Lf "${MDBOOK_URL}" | tar -xzC book
 
       - name: Build
-        working-directory: book
-        run: ./mdbook build
+        run: book/build.sh
 
       - name: Push to gh-pages
         working-directory: book/build
diff --git a/book/build.sh b/book/build.sh
new file mode 100755
index 0000000..a847139
--- /dev/null
+++ b/book/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+cd "$(dirname "$0")"
+
+if [ -f ./mdbook ]; then
+    ./mdbook build
+else
+    mdbook build
+fi

From 85e64896664feffd929912e67d94049dd7acf53b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:32:17 +0000
Subject: [PATCH 1369/2232] Merge pull request #466 from dtolnay/book


Add book build script
---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 73b8186..00104c8 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -15,16 +15,14 @@ jobs:
       - uses: actions/checkout@v2
 
       - name: Get mdBook
-        working-directory: book
         run: |
           export MDBOOK_VERSION="v0.4.4"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
           export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
-          curl -Lf "${MDBOOK_URL}" | tar -xz
+          curl -Lf "${MDBOOK_URL}" | tar -xzC book
 
       - name: Build
-        working-directory: book
-        run: ./mdbook build
+        run: book/build.sh
 
       - name: Push to gh-pages
         working-directory: book/build
diff --git a/book/build.sh b/book/build.sh
new file mode 100755
index 0000000..a847139
--- /dev/null
+++ b/book/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+set -e
+
+cd "$(dirname "$0")"
+
+if [ -f ./mdbook ]; then
+    ./mdbook build
+else
+    mdbook build
+fi

From 3415e6db3122341662c1e59f01ffd9c8709eff76 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:32:31 +0000
Subject: [PATCH 1370/2232] Add github link to website sidebar


---

diff --git a/book/.gitignore b/book/.gitignore
index 690b5b8..7277507 100644
--- a/book/.gitignore
+++ b/book/.gitignore
@@ -1,2 +1,3 @@
 /build
 /mdbook
+/node_modules
diff --git a/book/build.js b/book/build.js
new file mode 100755
index 0000000..a9278db
--- /dev/null
+++ b/book/build.js
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+
+const fs = require('fs');
+const cheerio = require('cheerio');
+
+const githublink = `\
+<li class="part-title">\
+<a href="https://github.com/dtolnay/cxx">\
+<i class="fa fa-github" style="font-size:20px;padding-right:5px;padding-top:12px;position:relative;top:1px"></i>\
+https://github.com/dtolnay/cxx\
+</a>\
+</li>`;
+
+const dirs = ['build'];
+while (dirs.length) {
+  const dir = dirs.pop();
+  fs.readdirSync(dir).forEach((entry) => {
+    path = dir + '/' + entry;
+    const stat = fs.statSync(path);
+    if (stat.isDirectory()) {
+      dirs.push(path);
+      return;
+    }
+
+    if (!path.endsWith('.html')) {
+      return;
+    }
+
+    const index = fs.readFileSync(path, 'utf8');
+    const $ = cheerio.load(index, { decodeEntities: false });
+
+    $('nav#sidebar ol.chapter').append(githublink);
+
+    const out = $.html();
+    fs.writeFileSync(path, out);
+  });
+}
diff --git a/book/build.sh b/book/build.sh
index a847139..783d304 100755
--- a/book/build.sh
+++ b/book/build.sh
@@ -9,3 +9,9 @@ if [ -f ./mdbook ]; then
 else
     mdbook build
 fi
+
+if [ ! -d node_modules ]; then
+    npm install
+fi
+
+./build.js
diff --git a/book/package.json b/book/package.json
new file mode 100644
index 0000000..9be4018
--- /dev/null
+++ b/book/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "cxx-book-build",
+  "version": "0.0.0",
+  "main": "build.js",
+  "dependencies": {
+    "cheerio": "^1.0.0-rc.3"
+  },
+  "prettier": {
+    "singleQuote": true
+  }
+}

From 0c710159a197e2c311422913948b6613ac142275 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:37:54 +0000
Subject: [PATCH 1371/2232] Check in package-lock.json


---

diff --git a/book/package-lock.json b/book/package-lock.json
new file mode 100644
index 0000000..c7de795
--- /dev/null
+++ b/book/package-lock.json
@@ -0,0 +1,150 @@
+{
+  "name": "cxx-book-build",
+  "version": "0.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@types/node": {
+      "version": "14.14.7",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
+      "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg=="
+    },
+    "boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+    },
+    "cheerio": {
+      "version": "1.0.0-rc.3",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "requires": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.1",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      }
+    },
+    "css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+      "requires": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
+    },
+    "dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "requires": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+    },
+    "domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+    },
+    "htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "requires": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "lodash": {
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+    },
+    "nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "requires": {
+        "boolbase": "~1.0.0"
+      }
+    },
+    "parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    }
+  }
+}

From fa6952a11dd73c6a4126e32a530566fb6c60dd8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:44:12 +0000
Subject: [PATCH 1372/2232] Merge pull request #467 from dtolnay/book


Add github link to website sidebar
---

diff --git a/book/.gitignore b/book/.gitignore
index 690b5b8..7277507 100644
--- a/book/.gitignore
+++ b/book/.gitignore
@@ -1,2 +1,3 @@
 /build
 /mdbook
+/node_modules
diff --git a/book/build.js b/book/build.js
new file mode 100755
index 0000000..a9278db
--- /dev/null
+++ b/book/build.js
@@ -0,0 +1,37 @@
+#!/usr/bin/env node
+
+const fs = require('fs');
+const cheerio = require('cheerio');
+
+const githublink = `\
+<li class="part-title">\
+<a href="https://github.com/dtolnay/cxx">\
+<i class="fa fa-github" style="font-size:20px;padding-right:5px;padding-top:12px;position:relative;top:1px"></i>\
+https://github.com/dtolnay/cxx\
+</a>\
+</li>`;
+
+const dirs = ['build'];
+while (dirs.length) {
+  const dir = dirs.pop();
+  fs.readdirSync(dir).forEach((entry) => {
+    path = dir + '/' + entry;
+    const stat = fs.statSync(path);
+    if (stat.isDirectory()) {
+      dirs.push(path);
+      return;
+    }
+
+    if (!path.endsWith('.html')) {
+      return;
+    }
+
+    const index = fs.readFileSync(path, 'utf8');
+    const $ = cheerio.load(index, { decodeEntities: false });
+
+    $('nav#sidebar ol.chapter').append(githublink);
+
+    const out = $.html();
+    fs.writeFileSync(path, out);
+  });
+}
diff --git a/book/build.sh b/book/build.sh
index a847139..783d304 100755
--- a/book/build.sh
+++ b/book/build.sh
@@ -9,3 +9,9 @@ if [ -f ./mdbook ]; then
 else
     mdbook build
 fi
+
+if [ ! -d node_modules ]; then
+    npm install
+fi
+
+./build.js
diff --git a/book/package-lock.json b/book/package-lock.json
new file mode 100644
index 0000000..c7de795
--- /dev/null
+++ b/book/package-lock.json
@@ -0,0 +1,150 @@
+{
+  "name": "cxx-book-build",
+  "version": "0.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@types/node": {
+      "version": "14.14.7",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
+      "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg=="
+    },
+    "boolbase": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+    },
+    "cheerio": {
+      "version": "1.0.0-rc.3",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
+      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "requires": {
+        "css-select": "~1.2.0",
+        "dom-serializer": "~0.1.1",
+        "entities": "~1.1.1",
+        "htmlparser2": "^3.9.1",
+        "lodash": "^4.15.0",
+        "parse5": "^3.0.1"
+      }
+    },
+    "css-select": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+      "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+      "requires": {
+        "boolbase": "~1.0.0",
+        "css-what": "2.1",
+        "domutils": "1.5.1",
+        "nth-check": "~1.0.1"
+      }
+    },
+    "css-what": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+      "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
+    },
+    "dom-serializer": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+      "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+      "requires": {
+        "domelementtype": "^1.3.0",
+        "entities": "^1.1.1"
+      }
+    },
+    "domelementtype": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+    },
+    "domhandler": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+      "requires": {
+        "domelementtype": "1"
+      }
+    },
+    "domutils": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+      "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+      "requires": {
+        "dom-serializer": "0",
+        "domelementtype": "1"
+      }
+    },
+    "entities": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+    },
+    "htmlparser2": {
+      "version": "3.10.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+      "requires": {
+        "domelementtype": "^1.3.1",
+        "domhandler": "^2.3.0",
+        "domutils": "^1.5.1",
+        "entities": "^1.1.1",
+        "inherits": "^2.0.1",
+        "readable-stream": "^3.1.1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "lodash": {
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+    },
+    "nth-check": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+      "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+      "requires": {
+        "boolbase": "~1.0.0"
+      }
+    },
+    "parse5": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
+      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "readable-stream": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    }
+  }
+}
diff --git a/book/package.json b/book/package.json
new file mode 100644
index 0000000..9be4018
--- /dev/null
+++ b/book/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "cxx-book-build",
+  "version": "0.0.0",
+  "main": "build.js",
+  "dependencies": {
+    "cheerio": "^1.0.0-rc.3"
+  },
+  "prettier": {
+    "singleQuote": true
+  }
+}

From 78d9692dbbd8cda9321dc4bd9e947385c0a5db17 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:47:47 +0000
Subject: [PATCH 1373/2232] Preapply hljs to provide highlighting for browsers with JS off


---

diff --git a/book/book.toml b/book/book.toml
index d3187e0..fe8b5fc 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -10,5 +10,6 @@ edition = "2018"
 build-dir = "build"
 
 [output.html]
+additional-css = ["css/cxx.css"]
 cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"
diff --git a/book/build.js b/book/build.js
index a9278db..d4396fe 100755
--- a/book/build.js
+++ b/book/build.js
@@ -2,6 +2,9 @@
 
 const fs = require('fs');
 const cheerio = require('cheerio');
+const hljs = require('./build/highlight.js');
+const Entities = require('html-entities').AllHtmlEntities;
+const entities = new Entities();
 
 const githublink = `\
 <li class="part-title">\
@@ -30,6 +33,36 @@ while (dirs.length) {
     const $ = cheerio.load(index, { decodeEntities: false });
 
     $('nav#sidebar ol.chapter').append(githublink);
+    $('pre code').each(function () {
+      const node = $(this);
+      const langClass = node.attr('class').split(' ', 2)[0];
+      if (!langClass.startsWith('language-')) {
+        return;
+      }
+      const lang = langClass.replace('language-', '');
+      const lines = node.html().split('\n');
+      const boring = lines.map((line) =>
+        line.includes('<span class="boring">')
+      );
+      const target = entities.decode(node.text());
+      const highlighted = hljs.highlight(lang, target).value;
+      const result = highlighted
+        .split('\n')
+        .map(function (line, i) {
+          if (boring[i]) {
+            line = '<span class="boring">' + line;
+          }
+          if (i > 0 && boring[i - 1]) {
+            line = '</span>' + line;
+          }
+          return line;
+        })
+        .join('\n');
+      node.text(result).removeClass(langClass).addClass('hidelines');
+    });
+    $('code').each(function () {
+      $(this).addClass('hljs');
+    });
 
     const out = $.html();
     fs.writeFileSync(path, out);
diff --git a/book/css/cxx.css b/book/css/cxx.css
new file mode 100644
index 0000000..1556283
--- /dev/null
+++ b/book/css/cxx.css
@@ -0,0 +1,3 @@
+.no-js .boring {
+    display: none;
+}
diff --git a/book/package-lock.json b/book/package-lock.json
index c7de795..dc58dbe 100644
--- a/book/package-lock.json
+++ b/book/package-lock.json
@@ -79,6 +79,11 @@
       "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
       "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
     },
+    "html-entities": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
+      "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
+    },
     "htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
diff --git a/book/package.json b/book/package.json
index 9be4018..8474066 100644
--- a/book/package.json
+++ b/book/package.json
@@ -3,7 +3,8 @@
   "version": "0.0.0",
   "main": "build.js",
   "dependencies": {
-    "cheerio": "^1.0.0-rc.3"
+    "cheerio": "^1.0.0-rc.3",
+    "html-entities": "^1.3.1"
   },
   "prettier": {
     "singleQuote": true

From d7dfa262de1bd6c04ab2dfefef8ddb1631dce1a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 00:54:50 +0000
Subject: [PATCH 1374/2232] Merge pull request #468 from dtolnay/book


Preapply hljs to provide highlighting for browsers with JS off
---

diff --git a/book/book.toml b/book/book.toml
index d3187e0..fe8b5fc 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -10,5 +10,6 @@ edition = "2018"
 build-dir = "build"
 
 [output.html]
+additional-css = ["css/cxx.css"]
 cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"
diff --git a/book/build.js b/book/build.js
index a9278db..d4396fe 100755
--- a/book/build.js
+++ b/book/build.js
@@ -2,6 +2,9 @@
 
 const fs = require('fs');
 const cheerio = require('cheerio');
+const hljs = require('./build/highlight.js');
+const Entities = require('html-entities').AllHtmlEntities;
+const entities = new Entities();
 
 const githublink = `\
 <li class="part-title">\
@@ -30,6 +33,36 @@ while (dirs.length) {
     const $ = cheerio.load(index, { decodeEntities: false });
 
     $('nav#sidebar ol.chapter').append(githublink);
+    $('pre code').each(function () {
+      const node = $(this);
+      const langClass = node.attr('class').split(' ', 2)[0];
+      if (!langClass.startsWith('language-')) {
+        return;
+      }
+      const lang = langClass.replace('language-', '');
+      const lines = node.html().split('\n');
+      const boring = lines.map((line) =>
+        line.includes('<span class="boring">')
+      );
+      const target = entities.decode(node.text());
+      const highlighted = hljs.highlight(lang, target).value;
+      const result = highlighted
+        .split('\n')
+        .map(function (line, i) {
+          if (boring[i]) {
+            line = '<span class="boring">' + line;
+          }
+          if (i > 0 && boring[i - 1]) {
+            line = '</span>' + line;
+          }
+          return line;
+        })
+        .join('\n');
+      node.text(result).removeClass(langClass).addClass('hidelines');
+    });
+    $('code').each(function () {
+      $(this).addClass('hljs');
+    });
 
     const out = $.html();
     fs.writeFileSync(path, out);
diff --git a/book/css/cxx.css b/book/css/cxx.css
new file mode 100644
index 0000000..1556283
--- /dev/null
+++ b/book/css/cxx.css
@@ -0,0 +1,3 @@
+.no-js .boring {
+    display: none;
+}
diff --git a/book/package-lock.json b/book/package-lock.json
index c7de795..dc58dbe 100644
--- a/book/package-lock.json
+++ b/book/package-lock.json
@@ -79,6 +79,11 @@
       "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
       "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
     },
+    "html-entities": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
+      "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA=="
+    },
     "htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
diff --git a/book/package.json b/book/package.json
index 9be4018..8474066 100644
--- a/book/package.json
+++ b/book/package.json
@@ -3,7 +3,8 @@
   "version": "0.0.0",
   "main": "build.js",
   "dependencies": {
-    "cheerio": "^1.0.0-rc.3"
+    "cheerio": "^1.0.0-rc.3",
+    "html-entities": "^1.3.1"
   },
   "prettier": {
     "singleQuote": true

From 909bb36da2d4a0b561a49bb022406bc08131e708 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 01:20:17 +0000
Subject: [PATCH 1375/2232] Pull in unreleased mdbook fixes


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 00104c8..b106db9 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -16,9 +16,9 @@ jobs:
 
       - name: Get mdBook
         run: |
-          export MDBOOK_VERSION="v0.4.4"
+          export MDBOOK_VERSION="dtolnay"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
-          export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
+          export MDBOOK_URL="https://github.com/dtolnay/mdBook/releases/download/cxx/${MDBOOK_TARBALL}"
           curl -Lf "${MDBOOK_URL}" | tar -xzC book
 
       - name: Build

From 9ebcb6bfc8b24ffe632b5b7786ff568eeb7c460e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 01:29:20 +0000
Subject: [PATCH 1376/2232] Merge pull request #469 from dtolnay/book


Pull in unreleased mdbook fixes
---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index 00104c8..b106db9 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -16,9 +16,9 @@ jobs:
 
       - name: Get mdBook
         run: |
-          export MDBOOK_VERSION="v0.4.4"
+          export MDBOOK_VERSION="dtolnay"
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
-          export MDBOOK_URL="https://github.com/rust-lang/mdBook/releases/download/${MDBOOK_VERSION}/${MDBOOK_TARBALL}"
+          export MDBOOK_URL="https://github.com/dtolnay/mdBook/releases/download/cxx/${MDBOOK_TARBALL}"
           curl -Lf "${MDBOOK_URL}" | tar -xzC book
 
       - name: Build

From f3bb97e05507af14418b60ab34b98a812c4da3f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 03:35:16 +0000
Subject: [PATCH 1377/2232] Downgrade to cheerio 0.22


---

diff --git a/book/package-lock.json b/book/package-lock.json
index dc58dbe..dec26ad 100644
--- a/book/package-lock.json
+++ b/book/package-lock.json
@@ -4,27 +4,32 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
-    "@types/node": {
-      "version": "14.14.7",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
-      "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg=="
-    },
     "boolbase": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
     },
     "cheerio": {
-      "version": "1.0.0-rc.3",
-      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
-      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "version": "0.22.0",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+      "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
       "requires": {
         "css-select": "~1.2.0",
-        "dom-serializer": "~0.1.1",
+        "dom-serializer": "~0.1.0",
         "entities": "~1.1.1",
         "htmlparser2": "^3.9.1",
-        "lodash": "^4.15.0",
-        "parse5": "^3.0.1"
+        "lodash.assignin": "^4.0.9",
+        "lodash.bind": "^4.1.4",
+        "lodash.defaults": "^4.0.1",
+        "lodash.filter": "^4.4.0",
+        "lodash.flatten": "^4.2.0",
+        "lodash.foreach": "^4.3.0",
+        "lodash.map": "^4.4.0",
+        "lodash.merge": "^4.4.0",
+        "lodash.pick": "^4.2.1",
+        "lodash.reduce": "^4.4.0",
+        "lodash.reject": "^4.4.0",
+        "lodash.some": "^4.4.0"
       }
     },
     "css-select": {
@@ -102,10 +107,65 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
-    "lodash": {
-      "version": "4.17.20",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+    "lodash.assignin": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
+      "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI="
+    },
+    "lodash.bind": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
+      "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
+    },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+    },
+    "lodash.filter": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
+      "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4="
+    },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+    },
+    "lodash.foreach": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+      "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
+    },
+    "lodash.map": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+      "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="
+    },
+    "lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+    },
+    "lodash.pick": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+      "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
+    },
+    "lodash.reduce": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
+      "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
+    },
+    "lodash.reject": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
+      "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU="
+    },
+    "lodash.some": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+      "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
     },
     "nth-check": {
       "version": "1.0.2",
@@ -115,14 +175,6 @@
         "boolbase": "~1.0.0"
       }
     },
-    "parse5": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
-      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
-      "requires": {
-        "@types/node": "*"
-      }
-    },
     "readable-stream": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
diff --git a/book/package.json b/book/package.json
index 8474066..092cea2 100644
--- a/book/package.json
+++ b/book/package.json
@@ -3,7 +3,7 @@
   "version": "0.0.0",
   "main": "build.js",
   "dependencies": {
-    "cheerio": "^1.0.0-rc.3",
+    "cheerio": "^0.22.0",
     "html-entities": "^1.3.1"
   },
   "prettier": {

From 2f606726ba15d336162d778f9c2d6bcc3c034342 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 03:46:09 +0000
Subject: [PATCH 1378/2232] Merge pull request #470 from dtolnay/book


Downgrade to cheerio 0.22
---

diff --git a/book/package-lock.json b/book/package-lock.json
index dc58dbe..dec26ad 100644
--- a/book/package-lock.json
+++ b/book/package-lock.json
@@ -4,27 +4,32 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
-    "@types/node": {
-      "version": "14.14.7",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz",
-      "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg=="
-    },
     "boolbase": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
     },
     "cheerio": {
-      "version": "1.0.0-rc.3",
-      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
-      "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
+      "version": "0.22.0",
+      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+      "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
       "requires": {
         "css-select": "~1.2.0",
-        "dom-serializer": "~0.1.1",
+        "dom-serializer": "~0.1.0",
         "entities": "~1.1.1",
         "htmlparser2": "^3.9.1",
-        "lodash": "^4.15.0",
-        "parse5": "^3.0.1"
+        "lodash.assignin": "^4.0.9",
+        "lodash.bind": "^4.1.4",
+        "lodash.defaults": "^4.0.1",
+        "lodash.filter": "^4.4.0",
+        "lodash.flatten": "^4.2.0",
+        "lodash.foreach": "^4.3.0",
+        "lodash.map": "^4.4.0",
+        "lodash.merge": "^4.4.0",
+        "lodash.pick": "^4.2.1",
+        "lodash.reduce": "^4.4.0",
+        "lodash.reject": "^4.4.0",
+        "lodash.some": "^4.4.0"
       }
     },
     "css-select": {
@@ -102,10 +107,65 @@
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
-    "lodash": {
-      "version": "4.17.20",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
-      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+    "lodash.assignin": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
+      "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI="
+    },
+    "lodash.bind": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
+      "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
+    },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+    },
+    "lodash.filter": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
+      "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4="
+    },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+    },
+    "lodash.foreach": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+      "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
+    },
+    "lodash.map": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
+      "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="
+    },
+    "lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
+    },
+    "lodash.pick": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+      "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
+    },
+    "lodash.reduce": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
+      "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
+    },
+    "lodash.reject": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
+      "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU="
+    },
+    "lodash.some": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
+      "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
     },
     "nth-check": {
       "version": "1.0.2",
@@ -115,14 +175,6 @@
         "boolbase": "~1.0.0"
       }
     },
-    "parse5": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
-      "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
-      "requires": {
-        "@types/node": "*"
-      }
-    },
     "readable-stream": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
diff --git a/book/package.json b/book/package.json
index 8474066..092cea2 100644
--- a/book/package.json
+++ b/book/package.json
@@ -3,7 +3,7 @@
   "version": "0.0.0",
   "main": "build.js",
   "dependencies": {
-    "cheerio": "^1.0.0-rc.3",
+    "cheerio": "^0.22.0",
     "html-entities": "^1.3.1"
   },
   "prettier": {

From 9a306457f5f5181b6bafb2f24b428858c7156b21 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 03:51:58 +0000
Subject: [PATCH 1379/2232] Factor out fa-github icon tweak to css file


---

diff --git a/book/build.js b/book/build.js
index d4396fe..e7ec435 100755
--- a/book/build.js
+++ b/book/build.js
@@ -9,7 +9,7 @@ const entities = new Entities();
 const githublink = `\
 <li class="part-title">\
 <a href="https://github.com/dtolnay/cxx">\
-<i class="fa fa-github" style="font-size:20px;padding-right:5px;padding-top:12px;position:relative;top:1px"></i>\
+<i class="fa fa-github"></i>\
 https://github.com/dtolnay/cxx\
 </a>\
 </li>`;
diff --git a/book/css/cxx.css b/book/css/cxx.css
index 1556283..2a167bc 100644
--- a/book/css/cxx.css
+++ b/book/css/cxx.css
@@ -1,3 +1,11 @@
 .no-js .boring {
     display: none;
 }
+
+nav.sidebar li.part-title i.fa-github {
+    font-size: 20px;
+    padding-right: 5px;
+    padding-top: 12px;
+    position: relative;
+    top: 1px;
+}

From e3cdbd4ccdd4c65d4e7966c26d56c2996526345f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 23:11:52 +0000
Subject: [PATCH 1380/2232] Fix testing for symlink denied on initial builds


---

diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index 6c9d22d..93e9c35 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -61,7 +61,7 @@ fn main() {
         let from_dir = parent_dir.join("from");
         let to_dir = parent_dir.join("to");
         if fs::create_dir_all(&from_dir).is_ok()
-            && fs::remove_dir(&to_dir).is_ok()
+            && (!to_dir.exists() || fs::remove_dir(&to_dir).is_ok())
             && windows::symlink_dir(&from_dir, &to_dir).is_err()
         {
             message = DENIED;

From 2757ca805cee6138c5dab65cc545d4724d953d28 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 23:12:06 +0000
Subject: [PATCH 1381/2232] Format with rustfmt 1.4.22-beta


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d62899e..34b5e1b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -287,7 +287,10 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
     match name.value().as_str() {
         "C++" => Ok(Lang::Cxx),
         "Rust" => Ok(Lang::Rust),
-        _ => Err(Error::new_spanned(abi, "unrecognized ABI, requires either \"C++\" or \"Rust\"")),
+        _ => Err(Error::new_spanned(
+            abi,
+            "unrecognized ABI, requires either \"C++\" or \"Rust\"",
+        )),
     }
 }
 

From 36731f8f5307113d3aac9b86e49b099c48082ded Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 23:19:05 +0000
Subject: [PATCH 1382/2232] Disambiguate symlink argument names


Mirrors https://github.com/rust-lang/rust/pull/79060.

---

diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index b97e992..ac85184 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -28,19 +28,19 @@ pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
     }
 }
 
-pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
-    let src = src.as_ref();
-    let dst = dst.as_ref();
+pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
+    let original = original.as_ref();
+    let link = link.as_ref();
 
     let mut create_dir_error = None;
-    if dst.exists() {
-        let _ = fs::remove_file(dst).unwrap();
+    if link.exists() {
+        let _ = fs::remove_file(link).unwrap();
     } else {
-        let parent = dst.parent().unwrap();
+        let parent = link.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
     }
 
-    match paths::symlink_or_copy(src, dst) {
+    match paths::symlink_or_copy(original, link) {
         // As long as symlink_or_copy succeeded, ignore any create_dir_all error.
         Ok(()) => Ok(()),
         // If create_dir_all and symlink_or_copy both failed, prefer the first error.
@@ -48,19 +48,19 @@ pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Resu
     }
 }
 
-pub(crate) fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
-    let src = src.as_ref();
-    let dst = dst.as_ref();
+pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
+    let original = original.as_ref();
+    let link = link.as_ref();
 
     let mut create_dir_error = None;
-    if dst.exists() {
-        let _ = paths::remove_symlink_dir(dst).unwrap();
+    if link.exists() {
+        let _ = paths::remove_symlink_dir(link).unwrap();
     } else {
-        let parent = dst.parent().unwrap();
+        let parent = link.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
     }
 
-    match paths::symlink_dir(src, dst) {
+    match paths::symlink_dir(original, link) {
         // As long as symlink_dir succeeded, ignore any create_dir_all error.
         Ok(()) => Ok(()),
         // If create_dir_all and symlink_dir both failed, prefer the first error.
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 4459363..f738f7a 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -43,13 +43,16 @@ impl PathExt for Path {
 pub(crate) use self::fs::symlink_file as symlink_or_copy;
 
 #[cfg(windows)]
-pub(crate) fn symlink_or_copy(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> fs::Result<()> {
+pub(crate) fn symlink_or_copy(
+    original: impl AsRef<Path>,
+    link: impl AsRef<Path>,
+) -> fs::Result<()> {
     // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
     // require Developer Mode. If it fails, fall back to copying the file.
-    let src = src.as_ref();
-    let dst = dst.as_ref();
-    if fs::symlink_file(src, dst).is_err() {
-        fs::copy(src, dst)?;
+    let original = original.as_ref();
+    let link = link.as_ref();
+    if fs::symlink_file(original, link).is_err() {
+        fs::copy(original, link)?;
     }
     Ok(())
 }
@@ -61,7 +64,7 @@ pub(crate) use self::fs::copy as symlink_or_copy;
 pub(crate) use self::fs::symlink_dir;
 
 #[cfg(not(any(unix, windows)))]
-pub(crate) fn symlink_dir(_src: impl AsRef<Path>, _dst: impl AsRef<Path>) -> fs::Result<()> {
+pub(crate) fn symlink_dir(_original: impl AsRef<Path>, _link: impl AsRef<Path>) -> fs::Result<()> {
     Ok(())
 }
 
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 8f94f00..7a6858c 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -91,17 +91,17 @@ pub(crate) fn remove_dir(path: impl AsRef<Path>) -> Result<()> {
 }
 
 fn symlink<'a>(
-    src: &'a Path,
-    dst: &'a Path,
+    original: &'a Path,
+    link: &'a Path,
     fun: fn(&'a Path, &'a Path) -> io::Result<()>,
 ) -> Result<()> {
-    match fun(src, dst) {
+    match fun(original, link) {
         Ok(()) => Ok(()),
         Err(e) => err!(
             e,
             "Failed to create symlink `{}` pointing to `{}`",
-            dst,
-            src,
+            link,
+            original,
         ),
     }
 }
@@ -111,24 +111,24 @@ fn symlink<'a>(
 pub(crate) use self::symlink_file as symlink_dir;
 
 #[cfg(unix)]
-pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
-    symlink(src.as_ref(), dst.as_ref(), std::os::unix::fs::symlink)
+pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
+    symlink(original.as_ref(), link.as_ref(), std::os::unix::fs::symlink)
 }
 
 #[cfg(windows)]
-pub(crate) fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
     symlink(
-        src.as_ref(),
-        dst.as_ref(),
+        original.as_ref(),
+        link.as_ref(),
         std::os::windows::fs::symlink_file,
     )
 }
 
 #[cfg(windows)]
-pub(crate) fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
+pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
     symlink(
-        src.as_ref(),
-        dst.as_ref(),
+        original.as_ref(),
+        link.as_ref(),
         std::os::windows::fs::symlink_dir,
     )
 }
diff --git a/tools/cargo/build.rs b/tools/cargo/build.rs
index 93e9c35..401c741 100644
--- a/tools/cargo/build.rs
+++ b/tools/cargo/build.rs
@@ -58,11 +58,11 @@ fn main() {
     #[cfg(windows)]
     if let Some(out_dir) = env::var_os("OUT_DIR") {
         let parent_dir = Path::new(&out_dir).join("symlink");
-        let from_dir = parent_dir.join("from");
-        let to_dir = parent_dir.join("to");
-        if fs::create_dir_all(&from_dir).is_ok()
-            && (!to_dir.exists() || fs::remove_dir(&to_dir).is_ok())
-            && windows::symlink_dir(&from_dir, &to_dir).is_err()
+        let original_dir = parent_dir.join("original");
+        let link_dir = parent_dir.join("link");
+        if fs::create_dir_all(&original_dir).is_ok()
+            && (!link_dir.exists() || fs::remove_dir(&link_dir).is_ok())
+            && windows::symlink_dir(&original_dir, &link_dir).is_err()
         {
             message = DENIED;
         }

From 21749dfc4e1b51c6c8cd1d49cb233a2afbec765f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 14 2020 23:50:15 +0000
Subject: [PATCH 1383/2232] Fix symlink_or_copy signature on non-unix non-windows


Our other implementations of symlink_or_copy return Result<()> to match
std::os::unix::fs::symlink, but fs::copy returns Result<u64>.

Before:

    $ cargo check --target wasm32-wasi

    error[E0308]: mismatched types
      --> gen/build/src/out.rs:45:12
       |
    43 |     match paths::symlink_or_copy(original, link) {
       |           -------------------------------------- this expression has type `std::result::Result<u64, gen::fs::Error>`
    44 |         // As long as symlink_or_copy succeeded, ignore any create_dir_all error.
    45 |         Ok(()) => Ok(()),
       |            ^^ expected `u64`, found `()`

---

diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index f738f7a..6a8d352 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -58,7 +58,13 @@ pub(crate) fn symlink_or_copy(
 }
 
 #[cfg(not(any(unix, windows)))]
-pub(crate) use self::fs::copy as symlink_or_copy;
+pub(crate) fn symlink_or_copy(
+    original: impl AsRef<Path>,
+    copy: impl AsRef<Path>,
+) -> fs::Result<()> {
+    fs::copy(original, copy)?;
+    Ok(())
+}
 
 #[cfg(any(unix, windows))]
 pub(crate) use self::fs::symlink_dir;

From ff21d91276c7e6a682610dd8b64507ada091683e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 00:01:32 +0000
Subject: [PATCH 1384/2232] Treat crate_dir creation as unsuccessful on non-unix non-windows


---

diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index ac85184..157b316 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -60,7 +60,7 @@ pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) ->
         create_dir_error = fs::create_dir_all(parent).err();
     }
 
-    match paths::symlink_dir(original, link) {
+    match fs::symlink_dir(original, link) {
         // As long as symlink_dir succeeded, ignore any create_dir_all error.
         Ok(()) => Ok(()),
         // If create_dir_all and symlink_dir both failed, prefer the first error.
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index 6a8d352..effeec2 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -66,14 +66,6 @@ pub(crate) fn symlink_or_copy(
     Ok(())
 }
 
-#[cfg(any(unix, windows))]
-pub(crate) use self::fs::symlink_dir;
-
-#[cfg(not(any(unix, windows)))]
-pub(crate) fn symlink_dir(_original: impl AsRef<Path>, _link: impl AsRef<Path>) -> fs::Result<()> {
-    Ok(())
-}
-
 #[cfg(not(windows))]
 pub(crate) use self::fs::remove_file as remove_symlink_dir;
 
diff --git a/gen/src/fs.rs b/gen/src/fs.rs
index 7a6858c..7053cc4 100644
--- a/gen/src/fs.rs
+++ b/gen/src/fs.rs
@@ -9,7 +9,7 @@ pub(crate) type Result<T> = std::result::Result<T, Error>;
 
 #[derive(Debug)]
 pub(crate) struct Error {
-    source: io::Error,
+    source: Option<io::Error>,
     message: String,
 }
 
@@ -21,14 +21,15 @@ impl Display for Error {
 
 impl StdError for Error {
     fn source(&self) -> Option<&(dyn StdError + 'static)> {
-        Some(&self.source)
+        let source = self.source.as_ref()?;
+        Some(source)
     }
 }
 
 macro_rules! err {
     ($io_error:expr, $fmt:expr $(, $path:expr)* $(,)?) => {
         Err(Error {
-            source: $io_error,
+            source: Option::from($io_error),
             message: format!($fmt $(, $path.display())*),
         })
     }
@@ -106,10 +107,23 @@ fn symlink<'a>(
     }
 }
 
+pub(crate) fn symlink_fail(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
+    err!(
+        None,
+        "Failed to create symlink `{}` pointing to `{}`",
+        link.as_ref(),
+        original.as_ref(),
+    )
+}
+
 #[cfg(unix)]
 #[allow(unused_imports)]
 pub(crate) use self::symlink_file as symlink_dir;
 
+#[cfg(not(any(unix, windows)))]
+#[allow(unused_imports)]
+pub(crate) use self::symlink_fail as symlink_dir;
+
 #[cfg(unix)]
 pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> Result<()> {
     symlink(original.as_ref(), link.as_ref(), std::os::unix::fs::symlink)

From 5b259c994833c454807d80794bd45c4f057042e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 01:09:39 +0000
Subject: [PATCH 1385/2232] Add fallback codepath for crate_dir creation


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index db15335..5c6297a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -256,12 +256,10 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         path: include_dir,
     });
 
-    if let Some(crate_dir) = crate_dir {
-        this_crate.header_dirs.push(HeaderDir {
-            exported: true,
-            path: crate_dir,
-        });
-    }
+    this_crate.header_dirs.push(HeaderDir {
+        exported: true,
+        path: crate_dir,
+    });
 
     for exported_dir in &CFG.exported_header_dirs {
         this_crate.header_dirs.push(HeaderDir {
@@ -335,17 +333,23 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     Ok(this_crate)
 }
 
-fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+fn make_crate_dir(prj: &Project) -> PathBuf {
     if prj.include_prefix.as_os_str().is_empty() {
-        return Some(prj.manifest_dir.clone());
+        return prj.manifest_dir.clone();
     }
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
-    let link = crate_dir.join(&prj.include_prefix);
-    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
-        Some(crate_dir)
-    } else {
-        None
+    let ref link = crate_dir.join(&prj.include_prefix);
+    let ref manifest_dir = prj.manifest_dir;
+    if out::symlink_dir(manifest_dir, link).is_err() && cfg!(not(unix)) {
+        let cachedir_tag = "\
+        Signature: 8a477f597d28d172789f06886806bc55\n\
+        # This file is a cache directory tag created by cxx.\n\
+        # For information about cache directory tags see https://bford.info/cachedir/\n";
+        let _ = out::write(crate_dir.join("CACHEDIR.TAG"), cachedir_tag.as_bytes());
+        let max_depth = 6;
+        best_effort_copy_headers(manifest_dir, link, max_depth);
     }
+    crate_dir
 }
 
 fn make_include_dir(prj: &Project) -> Result<PathBuf> {
@@ -393,6 +397,48 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     Ok(())
 }
 
+fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
+    // Not using crate::gen::fs because we aren't reporting the errors.
+    use std::fs;
+
+    let mut dst_created = false;
+    let mut entries = match fs::read_dir(src) {
+        Ok(entries) => entries,
+        Err(_) => return,
+    };
+
+    while let Some(Ok(entry)) = entries.next() {
+        let file_name = entry.file_name();
+        if file_name.to_string_lossy().starts_with('.') {
+            continue;
+        }
+        match entry.file_type() {
+            Ok(file_type) if file_type.is_dir() && max_depth > 0 => {
+                let src = entry.path();
+                if src.join("Cargo.toml").exists() || src.join("CACHEDIR.TAG").exists() {
+                    continue;
+                }
+                let dst = dst.join(file_name);
+                best_effort_copy_headers(&src, &dst, max_depth - 1);
+            }
+            Ok(file_type) if file_type.is_file() => {
+                let src = entry.path();
+                if src.extension() != Some(OsStr::new("h")) {
+                    continue;
+                }
+                if !dst_created && fs::create_dir_all(dst).is_err() {
+                    return;
+                }
+                dst_created = true;
+                let dst = dst.join(file_name);
+                let _ = fs::remove_file(&dst);
+                let _ = fs::copy(src, dst);
+            }
+            _ => {}
+        }
+    }
+}
+
 fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
     let key = key.as_ref();
     env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))

From 75793a8d7ad75ba64312901bfdfb08564d04df4e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 01:36:33 +0000
Subject: [PATCH 1386/2232] Merge pull request #472 from dtolnay/cratedir


Add fallback codepath for crate_dir creation
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index db15335..5c6297a 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -256,12 +256,10 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         path: include_dir,
     });
 
-    if let Some(crate_dir) = crate_dir {
-        this_crate.header_dirs.push(HeaderDir {
-            exported: true,
-            path: crate_dir,
-        });
-    }
+    this_crate.header_dirs.push(HeaderDir {
+        exported: true,
+        path: crate_dir,
+    });
 
     for exported_dir in &CFG.exported_header_dirs {
         this_crate.header_dirs.push(HeaderDir {
@@ -335,17 +333,23 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
     Ok(this_crate)
 }
 
-fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
+fn make_crate_dir(prj: &Project) -> PathBuf {
     if prj.include_prefix.as_os_str().is_empty() {
-        return Some(prj.manifest_dir.clone());
+        return prj.manifest_dir.clone();
     }
     let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
-    let link = crate_dir.join(&prj.include_prefix);
-    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
-        Some(crate_dir)
-    } else {
-        None
+    let ref link = crate_dir.join(&prj.include_prefix);
+    let ref manifest_dir = prj.manifest_dir;
+    if out::symlink_dir(manifest_dir, link).is_err() && cfg!(not(unix)) {
+        let cachedir_tag = "\
+        Signature: 8a477f597d28d172789f06886806bc55\n\
+        # This file is a cache directory tag created by cxx.\n\
+        # For information about cache directory tags see https://bford.info/cachedir/\n";
+        let _ = out::write(crate_dir.join("CACHEDIR.TAG"), cachedir_tag.as_bytes());
+        let max_depth = 6;
+        best_effort_copy_headers(manifest_dir, link, max_depth);
     }
+    crate_dir
 }
 
 fn make_include_dir(prj: &Project) -> Result<PathBuf> {
@@ -393,6 +397,48 @@ fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) ->
     Ok(())
 }
 
+fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
+    // Not using crate::gen::fs because we aren't reporting the errors.
+    use std::fs;
+
+    let mut dst_created = false;
+    let mut entries = match fs::read_dir(src) {
+        Ok(entries) => entries,
+        Err(_) => return,
+    };
+
+    while let Some(Ok(entry)) = entries.next() {
+        let file_name = entry.file_name();
+        if file_name.to_string_lossy().starts_with('.') {
+            continue;
+        }
+        match entry.file_type() {
+            Ok(file_type) if file_type.is_dir() && max_depth > 0 => {
+                let src = entry.path();
+                if src.join("Cargo.toml").exists() || src.join("CACHEDIR.TAG").exists() {
+                    continue;
+                }
+                let dst = dst.join(file_name);
+                best_effort_copy_headers(&src, &dst, max_depth - 1);
+            }
+            Ok(file_type) if file_type.is_file() => {
+                let src = entry.path();
+                if src.extension() != Some(OsStr::new("h")) {
+                    continue;
+                }
+                if !dst_created && fs::create_dir_all(dst).is_err() {
+                    return;
+                }
+                dst_created = true;
+                let dst = dst.join(file_name);
+                let _ = fs::remove_file(&dst);
+                let _ = fs::copy(src, dst);
+            }
+            _ => {}
+        }
+    }
+}
+
 fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
     let key = key.as_ref();
     env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))

From bb1dfdec467af6ca497874496b33c875509f6d3c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 03:58:42 +0000
Subject: [PATCH 1387/2232] Improve resilience to changes in filetype from dir to file


---

diff --git a/gen/build/src/out.rs b/gen/build/src/out.rs
index 157b316..e275049 100644
--- a/gen/build/src/out.rs
+++ b/gen/build/src/out.rs
@@ -14,7 +14,7 @@ pub(crate) fn write(path: impl AsRef<Path>, content: &[u8]) -> Result<()> {
                 return Ok(());
             }
         }
-        let _ = fs::remove_file(path);
+        best_effort_remove(path);
     } else {
         let parent = path.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
@@ -34,7 +34,7 @@ pub(crate) fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -
 
     let mut create_dir_error = None;
     if link.exists() {
-        let _ = fs::remove_file(link).unwrap();
+        best_effort_remove(link);
     } else {
         let parent = link.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
@@ -54,7 +54,7 @@ pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) ->
 
     let mut create_dir_error = None;
     if link.exists() {
-        let _ = paths::remove_symlink_dir(link).unwrap();
+        best_effort_remove(link);
     } else {
         let parent = link.parent().unwrap();
         create_dir_error = fs::create_dir_all(parent).err();
@@ -67,3 +67,28 @@ pub(crate) fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) ->
         Err(err) => Err(Error::Fs(create_dir_error.unwrap_or(err))),
     }
 }
+
+fn best_effort_remove(path: &Path) {
+    use std::fs;
+
+    let file_type = match if cfg!(windows) {
+        // On Windows, the correct choice of remove_file vs remove_dir needs to
+        // be used according to what the symlink *points to*. Trying to use
+        // remove_file to remove a symlink which points to a directory fails
+        // with "Access is denied".
+        fs::metadata(path)
+    } else {
+        // On non-Windows, we check metadata not following symlinks. All
+        // symlinks are removed using remove_file.
+        fs::symlink_metadata(path)
+    } {
+        Ok(metadata) => metadata.file_type(),
+        Err(_) => return,
+    };
+
+    if file_type.is_dir() {
+        let _ = fs::remove_dir_all(path);
+    } else {
+        let _ = fs::remove_file(path);
+    }
+}
diff --git a/gen/build/src/paths.rs b/gen/build/src/paths.rs
index effeec2..c514a57 100644
--- a/gen/build/src/paths.rs
+++ b/gen/build/src/paths.rs
@@ -65,11 +65,3 @@ pub(crate) fn symlink_or_copy(
     fs::copy(original, copy)?;
     Ok(())
 }
-
-#[cfg(not(windows))]
-pub(crate) use self::fs::remove_file as remove_symlink_dir;
-
-// On Windows, trying to use remove_file to remove a symlink which points to a
-// directory fails with "Access is denied".
-#[cfg(windows)]
-pub(crate) use self::fs::remove_dir as remove_symlink_dir;

From 90691f4ef2dc6e9b876bf8159023702b5938cc6d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 04:03:29 +0000
Subject: [PATCH 1388/2232] Add binding to append to CxxString


---

diff --git a/src/cxx.cc b/src/cxx.cc
index cbaecbf..1295d04 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -17,6 +17,11 @@ size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
+void cxxbridge05$cxx_string$push(std::string &s, const uint8_t *ptr,
+                                 size_t len) noexcept {
+  s.append(reinterpret_cast<const char *>(ptr), len);
+}
+
 // rust::String
 void cxxbridge05$string$new(rust::String *self) noexcept;
 void cxxbridge05$string$clone(rust::String *self,
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 7b47feb..dd53adc 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -6,9 +6,11 @@ use core::str::{self, Utf8Error};
 
 extern "C" {
     #[link_name = "cxxbridge05$cxx_string$data"]
-    fn string_data(_: &CxxString) -> *const u8;
+    fn string_data(this: &CxxString) -> *const u8;
     #[link_name = "cxxbridge05$cxx_string$length"]
-    fn string_length(_: &CxxString) -> usize;
+    fn string_length(this: &CxxString) -> usize;
+    #[link_name = "cxxbridge05$cxx_string$push"]
+    fn string_push(this: &mut CxxString, ptr: *const u8, len: usize);
 }
 
 /// Binding to C++ `std::string`.
@@ -82,6 +84,11 @@ impl CxxString {
     pub fn to_string_lossy(&self) -> Cow<str> {
         String::from_utf8_lossy(self.as_bytes())
     }
+
+    /// Appends a given string slice onto the end of this C++ string.
+    pub fn push_str(&mut self, s: &str) {
+        unsafe { string_push(self, s.as_ptr(), s.len()) }
+    }
 }
 
 impl Display for CxxString {

From 95e74b38c98ab2ab5c9296e441b2c0a7ab325a5b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 04:16:22 +0000
Subject: [PATCH 1389/2232] Allow pushing arbitrary bytes to CxxString


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index dd53adc..5010175 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -87,7 +87,12 @@ impl CxxString {
 
     /// Appends a given string slice onto the end of this C++ string.
     pub fn push_str(&mut self, s: &str) {
-        unsafe { string_push(self, s.as_ptr(), s.len()) }
+        self.push_bytes(s.as_bytes());
+    }
+
+    /// Appends arbitrary bytes onto the end of this C++ string.
+    pub fn push_bytes(&mut self, bytes: &[u8]) {
+        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
     }
 }
 

From 5ecaea985ba5922a58236800970d0ac954e69735 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 07:38:41 +0000
Subject: [PATCH 1390/2232] Exhaustive matching of types and apis in typechecker


---

diff --git a/syntax/check.rs b/syntax/check.rs
index e8a6448..9249d49 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -35,7 +35,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
-            _ => {}
+            Type::Str(_) | Type::Fn(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
         }
     }
 
@@ -46,7 +46,7 @@ fn do_typecheck(cx: &mut Check) {
             Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
             Api::Impl(imp) => check_api_impl(cx, imp),
-            _ => {}
+            Api::Include(_) | Api::TypeAlias(_) => {}
         }
     }
 }

From 1db70c4549ae605f7a90181dce9b0593f4c52871 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 07:38:42 +0000
Subject: [PATCH 1391/2232] Reject fallible function pointer which doesn't work yet


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 9249d49..b95123d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,8 +2,8 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Slice, Struct, Ty1,
-    Type, Types,
+    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
+    Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -35,7 +35,8 @@ fn do_typecheck(cx: &mut Check) {
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
-            Type::Str(_) | Type::Fn(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
+            Type::Fn(ty) => check_type_fn(cx, ty),
+            Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
         }
     }
 
@@ -166,6 +167,12 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
     cx.error(ty, "only &[u8] is supported so far, not other slice types");
 }
 
+fn check_type_fn(cx: &mut Check, ty: &Signature) {
+    if ty.throws {
+        cx.error(ty, "function pointer returning Result is not supported yet");
+    }
+}
+
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
     let name = &strct.name;
     check_reserved_name(cx, &name.rust);

From 579cfbe82cbe06c0455167ce07196eb452d00afb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 07:40:18 +0000
Subject: [PATCH 1392/2232] Add fallible function pointer ui test


---

diff --git a/tests/ui/fallible_fnptr.rs b/tests/ui/fallible_fnptr.rs
new file mode 100644
index 0000000..623de0a
--- /dev/null
+++ b/tests/ui/fallible_fnptr.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        fn f(callback: fn() -> Result<()>);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/fallible_fnptr.stderr b/tests/ui/fallible_fnptr.stderr
new file mode 100644
index 0000000..cf56c16
--- /dev/null
+++ b/tests/ui/fallible_fnptr.stderr
@@ -0,0 +1,5 @@
+error: function pointer returning Result is not supported yet
+ --> $DIR/fallible_fnptr.rs:4:24
+  |
+4 |         fn f(callback: fn() -> Result<()>);
+  |                        ^^^^

From 57c166d775a4171c4e86b8394197048ccf2b7a9a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 07:40:43 +0000
Subject: [PATCH 1393/2232] Improve error message spanning for fallible fn ptr


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 500ea0b..0d6c066 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -5,7 +5,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
-use syn::Token;
+use syn::{token, Token};
 
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
@@ -145,6 +145,12 @@ impl ToTokens for Signature {
             } else {
                 ret.to_tokens(tokens);
             }
+        } else if let Some((result, langle, rangle)) = self.throws_tokens {
+            Token![->](self.paren_token.span).to_tokens(tokens);
+            result.to_tokens(tokens);
+            langle.to_tokens(tokens);
+            token::Paren(langle.span).surround(tokens, |_| ());
+            rangle.to_tokens(tokens);
         }
     }
 }
diff --git a/tests/ui/fallible_fnptr.stderr b/tests/ui/fallible_fnptr.stderr
index cf56c16..1d3fbe4 100644
--- a/tests/ui/fallible_fnptr.stderr
+++ b/tests/ui/fallible_fnptr.stderr
@@ -2,4 +2,4 @@ error: function pointer returning Result is not supported yet
  --> $DIR/fallible_fnptr.rs:4:24
   |
 4 |         fn f(callback: fn() -> Result<()>);
-  |                        ^^^^
+  |                        ^^^^^^^^^^^^^^^^^^

From 091b6d4715874cd1b5e78b6a579917679be191e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 08:24:29 +0000
Subject: [PATCH 1394/2232] Replace set-env workflow command with GITHUB_ENV


Closes #351.

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 26b2722..b862cf4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,8 @@ jobs:
         # still ensure the test is kept passing on the basis of the scheduled
         # builds.
         if: matrix.os && github.event_name != 'schedule'
-        run: echo '::set-env name=RUSTFLAGS::--cfg skip_ui_tests'
+        run: echo 'RUSTFLAGS=--cfg skip_ui_tests' >> $GITHUB_ENV
+        shell: bash
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
 

From 556738d8fe96f6d3c985a40d7df1f3e8bcada220 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:22:17 +0000
Subject: [PATCH 1395/2232] Allow multiple arg refs if C++ function is unsafe extern


---

diff --git a/syntax/check.rs b/syntax/check.rs
index b95123d..73ce885 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -325,6 +325,10 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
 }
 
 fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
+    if efn.lang == Lang::Cxx && efn.trusted {
+        return;
+    }
+
     match &efn.ret {
         Some(Type::Ref(_)) => {}
         _ => return,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 33ed31c..94c2cc8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -98,6 +98,7 @@ pub struct ExternFn {
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
+    pub trusted: bool,
 }
 
 pub struct TypeAlias {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 34b5e1b..662b099 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -233,10 +233,12 @@ fn parse_foreign_mod(
                     Err(err) => cx.push(err),
                 }
             }
-            ForeignItem::Fn(foreign) => match parse_extern_fn(cx, foreign, lang, &namespace) {
-                Ok(efn) => items.push(efn),
-                Err(err) => cx.push(err),
-            },
+            ForeignItem::Fn(foreign) => {
+                match parse_extern_fn(cx, foreign, lang, trusted, &namespace) {
+                    Ok(efn) => items.push(efn),
+                    Err(err) => cx.push(err),
+                }
+            }
             ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
                 match foreign.mac.parse_body_with(parse_include) {
                     Ok(include) => items.push(Api::Include(include)),
@@ -332,6 +334,7 @@ fn parse_extern_fn(
     cx: &mut Errors,
     foreign_fn: &ForeignItemFn,
     lang: Lang,
+    trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
@@ -449,6 +452,7 @@ fn parse_extern_fn(
             throws_tokens,
         },
         semi_token,
+        trusted,
     }))
 }
 

From 77cb5c17ef87307f63b41ab0b9d939b33c7d1f56 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:26:27 +0000
Subject: [PATCH 1396/2232] Add ui test of opaque type autotraits


---

diff --git a/tests/ui/opaque_autotraits.rs b/tests/ui/opaque_autotraits.rs
new file mode 100644
index 0000000..4417717
--- /dev/null
+++ b/tests/ui/opaque_autotraits.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque;
+    }
+}
+
+fn assert_send<T: Send>() {}
+fn assert_sync<T: Sync>() {}
+
+fn main() {
+    assert_send::<ffi::Opaque>();
+    assert_sync::<ffi::Opaque>();
+}
diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr
new file mode 100644
index 0000000..7a1e226
--- /dev/null
+++ b/tests/ui/opaque_autotraits.stderr
@@ -0,0 +1,27 @@
+error[E0277]: `*const u8` cannot be sent between threads safely
+  --> $DIR/opaque_autotraits.rs:12:5
+   |
+8  | fn assert_send<T: Send>() {}
+   |                   ---- required by this bound in `assert_send`
+...
+12 |     assert_send::<ffi::Opaque>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
+   |
+   = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const u8`
+   = note: required because it appears within the type `[*const u8; 0]`
+   = note: required because it appears within the type `cxx::private::Opaque`
+   = note: required because it appears within the type `ffi::Opaque`
+
+error[E0277]: `*const u8` cannot be shared between threads safely
+  --> $DIR/opaque_autotraits.rs:13:5
+   |
+9  | fn assert_sync<T: Sync>() {}
+   |                   ---- required by this bound in `assert_sync`
+...
+13 |     assert_sync::<ffi::Opaque>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be shared between threads safely
+   |
+   = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const u8`
+   = note: required because it appears within the type `[*const u8; 0]`
+   = note: required because it appears within the type `cxx::private::Opaque`
+   = note: required because it appears within the type `ffi::Opaque`

From 5e0d82f59d12c83b13744cac9e8a3c9818d96ef5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:45:05 +0000
Subject: [PATCH 1397/2232] Merge pull request #456 from dtolnay/unsafe


Enforce unsafe surrounding block on safe-to-call functions
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b862cf4..a633fd8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
         include:
           - rust: nightly
           - rust: beta
-          - rust: stable
-          - rust: 1.43.0
+          #- rust: stable
+          #- rust: 1.48.0
           - name: macOS
             rust: nightly
             os: macos
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@stable
+      - uses: dtolnay/rust-toolchain@beta
       - uses: actions/setup-java@v1
         with:
           java-version: 11
diff --git a/README.md b/README.md
index e27f9e7..0263f6e 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ cxx = "0.5"
 cxx-build = "0.5"
 ```
 
-*Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
+*Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
 *[Release notes](https://github.com/dtolnay/cxx/releases)*
 
 <br>
@@ -90,7 +90,7 @@ mod ffi {
         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
     }
 
-    extern "C++" {
+    unsafe extern "C++" {
         // One or more headers with the matching C++ declarations. Our code
         // generators don't read it but it gets #include'd and used in static
         // assertions to ensure our picture of the FFI boundary is accurate.
diff --git a/WORKSPACE b/WORKSPACE
index 6093eee..3fc2f90 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -25,15 +25,17 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_47_linux",
+    name = "rust_1_48_beta_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.47.0",
+    iso_date = "2020-11-08",
+    version = "beta",
 )
 
 rust_repository_set(
-    name = "rust_1_47_darwin",
+    name = "rust_1_48_beta_darwin",
     exec_triple = "x86_64-apple-darwin",
-    version = "1.47.0",
+    iso_date = "2020-11-08",
+    version = "beta",
 )
 
 vendor(
diff --git a/build.rs b/build.rs
index 73c6228..ae3ef67 100644
--- a/build.rs
+++ b/build.rs
@@ -20,8 +20,8 @@ fn main() {
     }
 
     if let Some(rustc) = rustc_version() {
-        if rustc.minor < 43 {
-            println!("cargo:warning=The cxx crate requires a rustc version 1.43.0 or newer.");
+        if rustc.minor < 48 {
+            println!("cargo:warning=The cxx crate requires a rustc version 1.48.0 or newer.");
             println!(
                 "cargo:warning=You appear to be building with: {}",
                 rustc.version,
diff --git a/demo/src/main.rs b/demo/src/main.rs
index 10f57e5..dca596a 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -14,7 +14,7 @@ mod ffi {
     }
 
     // C++ types and signatures exposed to Rust.
-    extern "C++" {
+    unsafe extern "C++" {
         include!("demo/include/blobstore.h");
 
         type BlobstoreClient;
diff --git a/gen/lib/tests/test.rs b/gen/lib/tests/test.rs
index ebb69a8..d035b52 100644
--- a/gen/lib/tests/test.rs
+++ b/gen/lib/tests/test.rs
@@ -6,7 +6,7 @@ fn test_positive() {
     let rs = quote! {
         #[cxx::bridge]
         mod ffi {
-            extern "C++" {
+            unsafe extern "C++" {
                 fn in_C();
             }
             extern "Rust" {
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 008fdc1..d7634c4 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -30,7 +30,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// # mod file1 {
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         type Demo;
 ///
 ///         fn create_demo() -> UniquePtr<Demo>;
@@ -41,7 +41,7 @@ use self::kind::{Kind, Opaque, Trivial};
 /// // file2.rs
 /// #[cxx::bridge(namespace = "example")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         type Demo = crate::file1::ffi::Demo;
 ///
 ///         fn take_ref_demo(demo: &Demo);
@@ -80,7 +80,7 @@ use self::kind::{Kind, Opaque, Trivial};
 ///
 /// #[cxx::bridge(namespace = "folly")]
 /// pub mod ffi {
-///     extern "C++" {
+///     unsafe extern "C++" {
 ///         include!("rust_cxx_bindings.h");
 ///
 ///         type StringPiece = crate::folly_sys::StringPiece;
diff --git a/src/lib.rs b/src/lib.rs
index 594ee73..5a03ebf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,7 @@
 //!
 //! <br>
 //!
-//! *Compiler support: requires rustc 1.43+ and c++11 or newer*<br>
+//! *Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
 //! *[Release notes](https://github.com/dtolnay/cxx/releases)*
 //!
 //! <br>
@@ -86,7 +86,7 @@
 //!         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
 //!     }
 //!
-//!     extern "C++" {
+//!     unsafe extern "C++" {
 //!         // One or more headers with the matching C++ declarations. Our code
 //!         // generators don't read it but it gets #include'd and used in static
 //!         // assertions to ensure our picture of the FFI boundary is accurate.
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 662b099..a8a76d0 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -204,7 +204,7 @@ fn parse_foreign_mod(
         Lang::Rust => {
             if foreign_mod.unsafety.is_some() {
                 let unsafety = foreign_mod.unsafety;
-                let abi = foreign_mod.abi;
+                let abi = &foreign_mod.abi;
                 let span = quote!(#unsafety #abi);
                 cx.error(span, "extern \"Rust\" block does not need to be unsafe");
             }
@@ -255,6 +255,18 @@ fn parse_foreign_mod(
         }
     }
 
+    if !trusted
+        && items.iter().any(|api| match api {
+            Api::CxxFunction(efn) => efn.unsafety.is_none(),
+            _ => false,
+        })
+    {
+        cx.error(
+            foreign_mod.abi,
+            "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
+        );
+    }
+
     let mut types = items.iter().filter_map(|item| match item {
         Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
         Api::TypeAlias(alias) => Some(&alias.name),
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index 340e2d7..a0c9ff4 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -6,7 +6,7 @@ use std::str;
 const BRIDGE0: &str = r#"
     #[cxx::bridge]
     mod ffi {
-        extern "C++" {
+        unsafe extern "C++" {
             pub fn do_cpp_thing(foo: &str);
         }
     }
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index b5ed579..8ca5e57 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -15,7 +15,7 @@ pub mod ffi2 {
     impl UniquePtr<F> {}
     impl UniquePtr<G> {}
 
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type D = crate::other::D;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 6ece294..ed6740d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -116,7 +116,7 @@ pub mod ffi {
         i: i32,
     }
 
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C;
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index cf53cde..aff1b1c 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -3,7 +3,7 @@
 #[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
         type C = crate::ffi::C;
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
index b07697a..a4a7b51 100644
--- a/tests/ui/disallow_lifetime.rs
+++ b/tests/ui/disallow_lifetime.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type C;
         fn f(&'static self);
     }
diff --git a/tests/ui/reference_to_reference.rs b/tests/ui/reference_to_reference.rs
index 2318533..91fe160 100644
--- a/tests/ui/reference_to_reference.rs
+++ b/tests/ui/reference_to_reference.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type ThingC;
         fn repro_c(t: &&ThingC);
     }
diff --git a/tests/ui/unnamed_receiver.rs b/tests/ui/unnamed_receiver.rs
index 13c23ae..5f53a0a 100644
--- a/tests/ui/unnamed_receiver.rs
+++ b/tests/ui/unnamed_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         type One;
         type Two;
         fn f(&mut self);
diff --git a/tests/ui/unrecognized_receiver.rs b/tests/ui/unrecognized_receiver.rs
index 5b09c56..eee8259 100644
--- a/tests/ui/unrecognized_receiver.rs
+++ b/tests/ui/unrecognized_receiver.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         fn f(self: &Unrecognized);
     }
 }

From 836341a6435cbfd518f614b41fd91d787ba245d4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:49:05 +0000
Subject: [PATCH 1398/2232] Fix conflict between pr 456 and fallible fn ui test


---

diff --git a/tests/ui/fallible_fnptr.rs b/tests/ui/fallible_fnptr.rs
index 623de0a..c45813d 100644
--- a/tests/ui/fallible_fnptr.rs
+++ b/tests/ui/fallible_fnptr.rs
@@ -1,6 +1,6 @@
 #[cxx::bridge]
 mod ffi {
-    extern "C++" {
+    unsafe extern "C++" {
         fn f(callback: fn() -> Result<()>);
     }
 }

From cf9aed6fd90c5197a61f4e3c135302a963b7252e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:50:49 +0000
Subject: [PATCH 1399/2232] Add Unpin to autotraits test


---

diff --git a/tests/ui/opaque_autotraits.rs b/tests/ui/opaque_autotraits.rs
index 4417717..322a000 100644
--- a/tests/ui/opaque_autotraits.rs
+++ b/tests/ui/opaque_autotraits.rs
@@ -1,3 +1,5 @@
+use std::marker::Unpin;
+
 #[cxx::bridge]
 mod ffi {
     extern "C++" {
@@ -7,8 +9,10 @@ mod ffi {
 
 fn assert_send<T: Send>() {}
 fn assert_sync<T: Sync>() {}
+fn assert_unpin<T: Unpin>() {}
 
 fn main() {
     assert_send::<ffi::Opaque>();
     assert_sync::<ffi::Opaque>();
+    assert_unpin::<ffi::Opaque>();
 }
diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr
index 7a1e226..7ce8ae4 100644
--- a/tests/ui/opaque_autotraits.stderr
+++ b/tests/ui/opaque_autotraits.stderr
@@ -1,10 +1,10 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
-  --> $DIR/opaque_autotraits.rs:12:5
+  --> $DIR/opaque_autotraits.rs:15:5
    |
-8  | fn assert_send<T: Send>() {}
+10 | fn assert_send<T: Send>() {}
    |                   ---- required by this bound in `assert_send`
 ...
-12 |     assert_send::<ffi::Opaque>();
+15 |     assert_send::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const u8`
@@ -13,12 +13,12 @@ error[E0277]: `*const u8` cannot be sent between threads safely
    = note: required because it appears within the type `ffi::Opaque`
 
 error[E0277]: `*const u8` cannot be shared between threads safely
-  --> $DIR/opaque_autotraits.rs:13:5
+  --> $DIR/opaque_autotraits.rs:16:5
    |
-9  | fn assert_sync<T: Sync>() {}
+11 | fn assert_sync<T: Sync>() {}
    |                   ---- required by this bound in `assert_sync`
 ...
-13 |     assert_sync::<ffi::Opaque>();
+16 |     assert_sync::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be shared between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const u8`

From 95dab1db60d5ace5803f2132255d575d233ae8a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:50:58 +0000
Subject: [PATCH 1400/2232] Ensure opaque types are !Unpin


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 5010175..7ee8987 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,6 +1,7 @@
 use alloc::borrow::Cow;
 use alloc::string::String;
 use core::fmt::{self, Debug, Display};
+use core::marker::{PhantomData, PhantomPinned};
 use core::slice;
 use core::str::{self, Utf8Error};
 
@@ -26,6 +27,7 @@ extern "C" {
 #[repr(C)]
 pub struct CxxString {
     _private: [u8; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 impl CxxString {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 5fb0807..d25ea91 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,7 +1,7 @@
 use crate::cxx_string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Display};
-use core::marker::PhantomData;
+use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
 use core::slice;
@@ -17,6 +17,7 @@ use core::slice;
 #[repr(C, packed)]
 pub struct CxxVector<T> {
     _private: [T; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 impl<T> CxxVector<T>
diff --git a/src/opaque.rs b/src/opaque.rs
index bad57e7..3c8f536 100644
--- a/src/opaque.rs
+++ b/src/opaque.rs
@@ -1,3 +1,4 @@
+use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 
 // . size = 0
@@ -5,9 +6,11 @@ use core::mem;
 // . ffi-safe
 // . !Send
 // . !Sync
+// . !Unpin
 #[repr(C, packed)]
 pub struct Opaque {
     _private: [*const u8; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 const_assert_eq!(0, mem::size_of::<Opaque>());
diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr
index 7ce8ae4..61e9179 100644
--- a/tests/ui/opaque_autotraits.stderr
+++ b/tests/ui/opaque_autotraits.stderr
@@ -25,3 +25,16 @@ error[E0277]: `*const u8` cannot be shared between threads safely
    = note: required because it appears within the type `[*const u8; 0]`
    = note: required because it appears within the type `cxx::private::Opaque`
    = note: required because it appears within the type `ffi::Opaque`
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> $DIR/opaque_autotraits.rs:17:5
+   |
+12 | fn assert_unpin<T: Unpin>() {}
+   |                    ----- required by this bound in `assert_unpin`
+...
+17 |     assert_unpin::<ffi::Opaque>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: required because it appears within the type `PhantomData<PhantomPinned>`
+   = note: required because it appears within the type `cxx::private::Opaque`
+   = note: required because it appears within the type `ffi::Opaque`

From ed2c6bfc98bd697690652ae28639434efeed4461 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 22:57:18 +0000
Subject: [PATCH 1401/2232] Merge pull request #473 from dtolnay/pinned


Ensure opaque types are !Unpin
---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 5010175..7ee8987 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,6 +1,7 @@
 use alloc::borrow::Cow;
 use alloc::string::String;
 use core::fmt::{self, Debug, Display};
+use core::marker::{PhantomData, PhantomPinned};
 use core::slice;
 use core::str::{self, Utf8Error};
 
@@ -26,6 +27,7 @@ extern "C" {
 #[repr(C)]
 pub struct CxxString {
     _private: [u8; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 impl CxxString {
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 5fb0807..d25ea91 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,7 +1,7 @@
 use crate::cxx_string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Display};
-use core::marker::PhantomData;
+use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
 use core::slice;
@@ -17,6 +17,7 @@ use core::slice;
 #[repr(C, packed)]
 pub struct CxxVector<T> {
     _private: [T; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 impl<T> CxxVector<T>
diff --git a/src/opaque.rs b/src/opaque.rs
index bad57e7..3c8f536 100644
--- a/src/opaque.rs
+++ b/src/opaque.rs
@@ -1,3 +1,4 @@
+use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 
 // . size = 0
@@ -5,9 +6,11 @@ use core::mem;
 // . ffi-safe
 // . !Send
 // . !Sync
+// . !Unpin
 #[repr(C, packed)]
 pub struct Opaque {
     _private: [*const u8; 0],
+    _pinned: PhantomData<PhantomPinned>,
 }
 
 const_assert_eq!(0, mem::size_of::<Opaque>());
diff --git a/tests/ui/opaque_autotraits.rs b/tests/ui/opaque_autotraits.rs
index 4417717..322a000 100644
--- a/tests/ui/opaque_autotraits.rs
+++ b/tests/ui/opaque_autotraits.rs
@@ -1,3 +1,5 @@
+use std::marker::Unpin;
+
 #[cxx::bridge]
 mod ffi {
     extern "C++" {
@@ -7,8 +9,10 @@ mod ffi {
 
 fn assert_send<T: Send>() {}
 fn assert_sync<T: Sync>() {}
+fn assert_unpin<T: Unpin>() {}
 
 fn main() {
     assert_send::<ffi::Opaque>();
     assert_sync::<ffi::Opaque>();
+    assert_unpin::<ffi::Opaque>();
 }
diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr
index 7a1e226..61e9179 100644
--- a/tests/ui/opaque_autotraits.stderr
+++ b/tests/ui/opaque_autotraits.stderr
@@ -1,10 +1,10 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
-  --> $DIR/opaque_autotraits.rs:12:5
+  --> $DIR/opaque_autotraits.rs:15:5
    |
-8  | fn assert_send<T: Send>() {}
+10 | fn assert_send<T: Send>() {}
    |                   ---- required by this bound in `assert_send`
 ...
-12 |     assert_send::<ffi::Opaque>();
+15 |     assert_send::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const u8`
@@ -13,15 +13,28 @@ error[E0277]: `*const u8` cannot be sent between threads safely
    = note: required because it appears within the type `ffi::Opaque`
 
 error[E0277]: `*const u8` cannot be shared between threads safely
-  --> $DIR/opaque_autotraits.rs:13:5
+  --> $DIR/opaque_autotraits.rs:16:5
    |
-9  | fn assert_sync<T: Sync>() {}
+11 | fn assert_sync<T: Sync>() {}
    |                   ---- required by this bound in `assert_sync`
 ...
-13 |     assert_sync::<ffi::Opaque>();
+16 |     assert_sync::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be shared between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const u8`
    = note: required because it appears within the type `[*const u8; 0]`
    = note: required because it appears within the type `cxx::private::Opaque`
    = note: required because it appears within the type `ffi::Opaque`
+
+error[E0277]: `PhantomPinned` cannot be unpinned
+  --> $DIR/opaque_autotraits.rs:17:5
+   |
+12 | fn assert_unpin<T: Unpin>() {}
+   |                    ----- required by this bound in `assert_unpin`
+...
+17 |     assert_unpin::<ffi::Opaque>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned`
+   |
+   = note: required because it appears within the type `PhantomData<PhantomPinned>`
+   = note: required because it appears within the type `cxx::private::Opaque`
+   = note: required because it appears within the type `ffi::Opaque`

From b27f7877030968414af4eb49c4b97d1a3b283bce Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 23:11:21 +0000
Subject: [PATCH 1402/2232] Represent Pin<P> in syntax tree


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index a4b393a..7efbc55 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -114,29 +114,39 @@ impl Eq for Ref {}
 impl PartialEq for Ref {
     fn eq(&self, other: &Ref) -> bool {
         let Ref {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             inner,
+            pin_tokens: _,
         } = self;
         let Ref {
+            pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
             mutability: mutability2,
             inner: inner2,
+            pin_tokens: _,
         } = other;
-        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && inner == inner2
+        pinned == pinned2
+            && lifetime == lifetime2
+            && mutability.is_some() == mutability2.is_some()
+            && inner == inner2
     }
 }
 
 impl Hash for Ref {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ref {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             inner,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         lifetime.hash(state);
         mutability.is_some().hash(state);
         inner.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 94c2cc8..72e815b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -170,10 +170,12 @@ pub struct Ty1 {
 }
 
 pub struct Ref {
+    pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub inner: Type,
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Slice {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a8a76d0..b275b5d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -18,6 +18,7 @@ use syn::{
 };
 
 pub mod kw {
+    syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
 }
 
@@ -625,10 +626,12 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
+        pinned: false,
         ampersand: ty.and_token,
         lifetime: ty.lifetime.clone(),
         mutability: ty.mutability,
         inner,
+        pin_tokens: None,
     })))
 }
 

From cbc2a4b257b2d9a18ea610e1c00ada8d7f0e4b45 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 23:11:58 +0000
Subject: [PATCH 1403/2232] Parse Pin<P> type


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index b275b5d..23fadff 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -683,6 +683,17 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "Pin" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg, namespace)?;
+                        if let Type::Ref(mut inner) = inner {
+                            let pin_token = kw::Pin(ident.span());
+                            inner.pinned = true;
+                            inner.pin_tokens =
+                                Some((pin_token, generic.lt_token, generic.gt_token));
+                            return Ok(Type::Ref(inner));
+                        }
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}

From db42cfd587a75288212bb2a0cc66b6ff383ce960 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 15 2020 23:44:26 +0000
Subject: [PATCH 1404/2232] Enforce pinning on mut opaque C++ types


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 73ce885..5876cf7 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -151,6 +151,24 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
         cx.error(ty, "references with explicit lifetimes are not supported");
     }
 
+    if ty.mutability.is_some() && !ty.pinned {
+        if let Some(requires_pin) = match &ty.inner {
+            Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => {
+                Some(ident.rust.to_string())
+            }
+            Type::CxxVector(_) => Some("CxxVector<...>".to_owned()),
+            _ => None,
+        } {
+            cx.error(
+                ty,
+                format!(
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
+                    requires_pin,
+                ),
+            );
+        }
+    }
+
     match ty.inner {
         Type::Fn(_) | Type::Void(_) => {}
         Type::Ref(_) => {
@@ -370,13 +388,14 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
-    ident == CxxString
-        || cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
-            && !(cx.types.aliases.contains_key(ident)
-                && cx.types.required_trivial.contains_key(ident))
-        || cx.types.rust.contains(ident)
+    ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+}
+
+fn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool {
+    cx.types.cxx.contains(ty)
+        && !cx.types.structs.contains_key(ty)
+        && !cx.types.enums.contains_key(ty)
+        && !(cx.types.aliases.contains_key(ty) && cx.types.required_trivial.contains_key(ty))
 }
 
 fn span_for_struct_error(strct: &Struct) -> TokenStream {

From 9c76c3979f0cf3c86ccf963b70a76c94d8544f71 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 00:07:14 +0000
Subject: [PATCH 1405/2232] Parse pinned method receivers


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 7efbc55..c345822 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -233,35 +233,45 @@ impl Eq for Receiver {}
 impl PartialEq for Receiver {
     fn eq(&self, other: &Receiver) -> bool {
         let Receiver {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             var: _,
             ty,
             shorthand: _,
+            pin_tokens: _,
         } = self;
         let Receiver {
+            pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
             mutability: mutability2,
             var: _,
             ty: ty2,
             shorthand: _,
+            pin_tokens: _,
         } = other;
-        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
+        pinned == pinned2
+            && lifetime == lifetime2
+            && mutability.is_some() == mutability2.is_some()
+            && ty == ty2
     }
 }
 
 impl Hash for Receiver {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Receiver {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             var: _,
             ty,
             shorthand: _,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         lifetime.hash(state);
         mutability.is_some().hash(state);
         ty.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 72e815b..51068c9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -134,12 +134,14 @@ pub struct Var {
 }
 
 pub struct Receiver {
+    pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
     pub ty: ResolvableName,
     pub shorthand: bool,
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Variant {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 23fadff..bbddaa7 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -388,12 +388,14 @@ fn parse_extern_fn(
             FnArg::Receiver(arg) => {
                 if let Some((ampersand, lifetime)) = &arg.reference {
                     receiver = Some(Receiver {
+                        pinned: false,
                         ampersand: *ampersand,
                         lifetime: lifetime.clone(),
                         mutability: arg.mutability,
                         var: arg.self_token,
                         ty: ResolvableName::make_self(arg.self_token.span),
                         shorthand: true,
+                        pin_tokens: None,
                     });
                     continue;
                 }
@@ -418,12 +420,14 @@ fn parse_extern_fn(
                 if let Type::Ref(reference) = ty {
                     if let Type::Ident(ident) = reference.inner {
                         receiver = Some(Receiver {
+                            pinned: reference.pinned,
                             ampersand: reference.ampersand,
                             lifetime: reference.lifetime,
                             mutability: reference.mutability,
                             var: Token![self](ident.rust.span()),
                             ty: ident,
                             shorthand: false,
+                            pin_tokens: reference.pin_tokens,
                         });
                         continue;
                     }

From 75aea9ab732b6d6377502b51378077bbd634ccdf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 00:10:08 +0000
Subject: [PATCH 1406/2232] Enforce receiver pinning


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 5876cf7..7e368f4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -269,6 +269,17 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             && !cx.types.rust.contains(&receiver.ty.rust)
         {
             cx.error(span, "unrecognized receiver type");
+        } else if receiver.mutability.is_some()
+            && !receiver.pinned
+            && is_opaque_cxx(cx, &receiver.ty.rust)
+        {
+            cx.error(
+                span,
+                format!(
+                    "mutable reference to C++ type requires a pin -- use `self: Pin<&mut {}>`",
+                    receiver.ty.rust,
+                ),
+            );
         }
 
         if receiver.lifetime.is_some() {

From 1346ca319d357f3021cf423bb49f4379385a5cd7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 00:13:15 +0000
Subject: [PATCH 1407/2232] Introduce pins in test suite


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ed6740d..ba9383a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -137,10 +137,10 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
-        fn c_return_mut_vector(c: &mut C) -> &mut CxxVector<u8>;
+        fn c_return_mut_vector(c: Pin<&mut C>) -> Pin<&mut CxxVector<u8>>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
-        fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
+        fn c_return_mut_rust_vec(c: Pin<&mut C>) -> &mut Vec<u8>;
         fn c_return_rust_vec_string() -> Vec<String>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
@@ -199,11 +199,10 @@ pub mod ffi {
         fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
-        fn set(self: &mut C, n: usize) -> usize;
+        fn set(self: Pin<&mut C>, n: usize) -> usize;
         fn get2(&self) -> usize;
-        fn set2(&mut self, n: usize) -> usize;
-        fn set_succeed(&mut self, n: usize) -> Result<usize>;
-        fn get_fail(&mut self) -> Result<usize>;
+        fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
+        fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
 
         #[rust_name = "i32_overloaded_method"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index fdf7a14..61ef701 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -26,12 +26,7 @@ size_t C::set(size_t n) {
   return this->n;
 }
 
-size_t C::set2(size_t n) {
-  this->n = n;
-  return this->n;
-}
-
-size_t C::set_succeed(size_t n) { return this->set2(n); }
+size_t C::set_succeed(size_t n) { return this->set(n); }
 
 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index d231939..5acf469 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -45,7 +45,6 @@ public:
   size_t get() const;
   size_t set(size_t n);
   size_t get2() const;
-  size_t set2(size_t n);
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
diff --git a/tests/test.rs b/tests/test.rs
index 2bae4d8..66ef7b4 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -190,8 +190,7 @@ fn test_c_method_calls() {
     assert_eq!(2020, old_value);
     assert_eq!(2021, unique_ptr.set(2021));
     assert_eq!(2021, unique_ptr.get());
-    assert_eq!(old_value, unique_ptr.set2(old_value));
-    assert_eq!(old_value, unique_ptr.get2());
+    assert_eq!(2021, unique_ptr.get2());
     assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
     assert!(unique_ptr.get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());

From c967384fcfd9f6288a0d3ef31b68d53156c3285a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 00:38:22 +0000
Subject: [PATCH 1408/2232] Emit pins in macro expansion


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 903585e..eaa7928 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -244,10 +244,15 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
-        let ampersand = receiver.ampersand;
-        let mutability = receiver.mutability;
         let var = receiver.var;
-        quote!(#ampersand #mutability #var)
+        if receiver.pinned {
+            let ty = receiver.ty();
+            quote!(#var: #ty)
+        } else {
+            let ampersand = receiver.ampersand;
+            let mutability = receiver.mutability;
+            quote!(#ampersand #mutability #var)
+        }
     });
     let args = efn.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 0d6c066..40ab723 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -54,10 +54,17 @@ impl ToTokens for Ty1 {
 
 impl ToTokens for Ref {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some((pin, langle, _rangle)) = self.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         self.ampersand.to_tokens(tokens);
         self.lifetime.to_tokens(tokens);
         self.mutability.to_tokens(tokens);
         self.inner.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }
 
@@ -172,9 +179,16 @@ impl Receiver {
 
 impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some((pin, langle, _rangle)) = self.0.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         self.0.ampersand.to_tokens(tokens);
         self.0.lifetime.to_tokens(tokens);
         self.0.mutability.to_tokens(tokens);
         self.0.ty.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.0.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }

From c94035a685db444be112b18e2e3cd47d309340bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 00:57:18 +0000
Subject: [PATCH 1409/2232] Parse pinned UniquePtr


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index eaa7928..3c9054c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -9,6 +9,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
+use std::collections::BTreeSet as Set;
 use std::mem;
 use syn::{parse_quote, Result, Token};
 
@@ -59,6 +60,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         }
     }
 
+    let mut expanded_unique_ptr = Set::new();
     for ty in types {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
@@ -77,6 +79,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
                     && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                    && expanded_unique_ptr.insert(&ident.rust)
                 {
                     expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index c345822..58d8fd3 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -81,29 +81,36 @@ impl Eq for Ty1 {}
 impl PartialEq for Ty1 {
     fn eq(&self, other: &Ty1) -> bool {
         let Ty1 {
+            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
+            pin_tokens: _,
         } = self;
         let Ty1 {
+            pinned: pinned2,
             name: name2,
             langle: _,
             inner: inner2,
             rangle: _,
+            pin_tokens: _,
         } = other;
-        name == name2 && inner == inner2
+        pinned == pinned2 && name == name2 && inner == inner2
     }
 }
 
 impl Hash for Ty1 {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ty1 {
+            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         name.hash(state);
         inner.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 51068c9..853db90 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -165,10 +165,12 @@ pub enum Type {
 }
 
 pub struct Ty1 {
+    pub pinned: bool,
     pub name: Ident,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Ref {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index bbddaa7..6010492 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -651,51 +651,64 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Pin" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
+                        let pin_token = kw::Pin(ident.span());
                         if let Type::Ref(mut inner) = inner {
-                            let pin_token = kw::Pin(ident.span());
                             inner.pinned = true;
                             inner.pin_tokens =
                                 Some((pin_token, generic.lt_token, generic.gt_token));
                             return Ok(Type::Ref(inner));
+                        } else if let Type::UniquePtr(mut inner) = inner {
+                            inner.pinned = true;
+                            inner.pin_tokens =
+                                Some((pin_token, generic.lt_token, generic.gt_token));
+                            return Ok(Type::UniquePtr(inner));
                         }
                     }
                 }

From a417065651f6ccfcfa68ad146832f2d08f38f027 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:12:39 +0000
Subject: [PATCH 1410/2232] Emit pinned unique ptrs


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3c9054c..bb93589 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -280,7 +280,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
-            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
+            Type::UniquePtr(ptr) => match ptr.pinned {
+                false => quote!(::cxx::UniquePtr::into_raw(#var)),
+                true => quote!(::cxx::UniquePtr::__pin_into_raw(#var)),
+            },
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
@@ -374,7 +377,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                         quote!(#call.into_vec())
                     }
                 }
-                Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#call)),
+                Type::UniquePtr(ptr) => match ptr.pinned {
+                    false => quote!(::cxx::UniquePtr::from_raw(#call)),
+                    true => quote!(::cxx::UniquePtr::__pin_from_raw(#call)),
+                },
                 Type::Ref(ty) => match &ty.inner {
                     Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                         None => quote!(#call.as_string()),
@@ -547,7 +553,10 @@ fn expand_rust_function_shim_impl(
                     quote!(::std::mem::take((*#ident).as_mut_vec()))
                 }
             }
-            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
+            Type::UniquePtr(ptr) => match ptr.pinned {
+                false => quote!(::cxx::UniquePtr::from_raw(#ident)),
+                true => quote!(::cxx::UniquePtr::__pin_from_raw(#ident)),
+            },
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i.rust == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
@@ -591,7 +600,10 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustVec::from))
             }
         }
-        Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
+        Type::UniquePtr(ptr) => match ptr.pinned {
+            false => Some(quote!(::cxx::UniquePtr::into_raw)),
+            true => Some(quote!(::cxx::UniquePtr::__pin_into_raw)),
+        },
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                 None => Some(quote!(::cxx::private::RustString::from_ref)),
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 3a5fc66..283c2f1 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -7,6 +7,7 @@ use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
 use core::ops::{Deref, DerefMut};
+use core::pin::Pin;
 use core::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
@@ -87,6 +88,16 @@ where
             ty: PhantomData,
         }
     }
+
+    #[doc(hidden)]
+    pub unsafe fn __pin_into_raw(ptr: Pin<UniquePtr<T>>) -> *mut T {
+        Self::into_raw(Pin::into_inner_unchecked(ptr))
+    }
+
+    #[doc(hidden)]
+    pub unsafe fn __pin_from_raw(raw: *mut T) -> Pin<Self> {
+        Pin::new_unchecked(Self::from_raw(raw))
+    }
 }
 
 unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 40ab723..af8088d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -40,6 +40,10 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
+        if let Some((pin, langle, _rangle)) = self.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
@@ -49,6 +53,9 @@ impl ToTokens for Ty1 {
         self.langle.to_tokens(tokens);
         self.inner.to_tokens(tokens);
         self.rangle.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }
 

From 14a49435f8708dfb75558642e751e4ec85e17f07 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:15:48 +0000
Subject: [PATCH 1411/2232] More test suite pins


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ba9383a..825b13b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -124,7 +124,7 @@ pub mod ffi {
         fn c_return_primitive() -> usize;
         fn c_return_shared() -> Shared;
         fn c_return_box() -> Box<R>;
-        fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_unique_ptr() -> Pin<UniquePtr<C>>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index aff1b1c..c8363b6 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -8,6 +8,6 @@ pub mod ffi {
 
         type C = crate::ffi::C;
 
-        fn c_take_unique_ptr(c: UniquePtr<C>);
+        fn c_take_unique_ptr(c: Pin<UniquePtr<C>>);
     }
 }
diff --git a/tests/test.rs b/tests/test.rs
index 66ef7b4..ff6abd9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -188,11 +188,11 @@ fn test_c_method_calls() {
 
     let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.set(2021));
+    assert_eq!(2021, unique_ptr.as_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
-    assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
-    assert!(unique_ptr.get_fail().is_err());
+    assert_eq!(2022, unique_ptr.as_mut().set_succeed(2022).unwrap());
+    assert!(unique_ptr.as_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 

From dbc86ead14f3defd8479f2a0ea8762994a7c3f55 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:22:21 +0000
Subject: [PATCH 1412/2232] Add mut opaque ui test


---

diff --git a/tests/ui/pin_mut_opaque.rs b/tests/ui/pin_mut_opaque.rs
new file mode 100644
index 0000000..ac1ca43
--- /dev/null
+++ b/tests/ui/pin_mut_opaque.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Opaque;
+        fn f(arg: &mut Opaque);
+        fn g(&mut self);
+        fn h(self: &mut Opaque);
+        fn s(s: &mut CxxString);
+        fn v(v: &mut CxxVector<u8>);
+    }
+
+}
+
+fn main() {}
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
new file mode 100644
index 0000000..32d5cfc
--- /dev/null
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -0,0 +1,29 @@
+error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque>
+ --> $DIR/pin_mut_opaque.rs:5:19
+  |
+5 |         fn f(arg: &mut Opaque);
+  |                   ^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString>
+ --> $DIR/pin_mut_opaque.rs:8:17
+  |
+8 |         fn s(s: &mut CxxString);
+  |                 ^^^^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>>
+ --> $DIR/pin_mut_opaque.rs:9:17
+  |
+9 |         fn v(v: &mut CxxVector<u8>);
+  |                 ^^^^^^^^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+ --> $DIR/pin_mut_opaque.rs:6:14
+  |
+6 |         fn g(&mut self);
+  |              ^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+ --> $DIR/pin_mut_opaque.rs:7:20
+  |
+7 |         fn h(self: &mut Opaque);
+  |                    ^^^^^^^^^^^

From ef665fde78cc7c17ad58680ec188da418908ebec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:25:31 +0000
Subject: [PATCH 1413/2232] Suppress clippy nonminimal_bool lint


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 5c6297a..d2a0458 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -50,6 +50,7 @@
     clippy::inherent_to_string,
     clippy::needless_doctest_main,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index c723039..e607030 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -3,6 +3,7 @@
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 963e870..506b007 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -11,6 +11,7 @@
 #![allow(
     clippy::inherent_to_string,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 852aacc..1de7e6c 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -2,6 +2,7 @@
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg,
     clippy::useless_let_if_seq

From 3717f7add090531b0af0bf42151662c04e99fdea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:30:07 +0000
Subject: [PATCH 1414/2232] Merge pull request #474 from dtolnay/pin


Enforce mutable references to opaque extern C++ types are pinned
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 5c6297a..d2a0458 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -50,6 +50,7 @@
     clippy::inherent_to_string,
     clippy::needless_doctest_main,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index c723039..e607030 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -3,6 +3,7 @@
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 963e870..506b007 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -11,6 +11,7 @@
 #![allow(
     clippy::inherent_to_string,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg
 )]
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 903585e..bb93589 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -9,6 +9,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
+use std::collections::BTreeSet as Set;
 use std::mem;
 use syn::{parse_quote, Result, Token};
 
@@ -59,6 +60,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         }
     }
 
+    let mut expanded_unique_ptr = Set::new();
     for ty in types {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
@@ -77,6 +79,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
                     && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                    && expanded_unique_ptr.insert(&ident.rust)
                 {
                     expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
@@ -244,10 +247,15 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
     let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
-        let ampersand = receiver.ampersand;
-        let mutability = receiver.mutability;
         let var = receiver.var;
-        quote!(#ampersand #mutability #var)
+        if receiver.pinned {
+            let ty = receiver.ty();
+            quote!(#var: #ty)
+        } else {
+            let ampersand = receiver.ampersand;
+            let mutability = receiver.mutability;
+            quote!(#ampersand #mutability #var)
+        }
     });
     let args = efn.args.iter().map(|arg| quote!(#arg));
     let all_args = receiver.chain(args);
@@ -272,7 +280,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
-            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
+            Type::UniquePtr(ptr) => match ptr.pinned {
+                false => quote!(::cxx::UniquePtr::into_raw(#var)),
+                true => quote!(::cxx::UniquePtr::__pin_into_raw(#var)),
+            },
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
@@ -366,7 +377,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                         quote!(#call.into_vec())
                     }
                 }
-                Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#call)),
+                Type::UniquePtr(ptr) => match ptr.pinned {
+                    false => quote!(::cxx::UniquePtr::from_raw(#call)),
+                    true => quote!(::cxx::UniquePtr::__pin_from_raw(#call)),
+                },
                 Type::Ref(ty) => match &ty.inner {
                     Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                         None => quote!(#call.as_string()),
@@ -539,7 +553,10 @@ fn expand_rust_function_shim_impl(
                     quote!(::std::mem::take((*#ident).as_mut_vec()))
                 }
             }
-            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
+            Type::UniquePtr(ptr) => match ptr.pinned {
+                false => quote!(::cxx::UniquePtr::from_raw(#ident)),
+                true => quote!(::cxx::UniquePtr::__pin_from_raw(#ident)),
+            },
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i.rust == RustString => match ty.mutability {
                     None => quote!(#ident.as_string()),
@@ -583,7 +600,10 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustVec::from))
             }
         }
-        Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
+        Type::UniquePtr(ptr) => match ptr.pinned {
+            false => Some(quote!(::cxx::UniquePtr::into_raw)),
+            true => Some(quote!(::cxx::UniquePtr::__pin_into_raw)),
+        },
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
                 None => Some(quote!(::cxx::private::RustString::from_ref)),
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 852aacc..1de7e6c 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -2,6 +2,7 @@
     clippy::inherent_to_string,
     clippy::large_enum_variant,
     clippy::new_without_default,
+    clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::toplevel_ref_arg,
     clippy::useless_let_if_seq
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 3a5fc66..283c2f1 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -7,6 +7,7 @@ use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
 use core::ops::{Deref, DerefMut};
+use core::pin::Pin;
 use core::ptr;
 
 /// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`.
@@ -87,6 +88,16 @@ where
             ty: PhantomData,
         }
     }
+
+    #[doc(hidden)]
+    pub unsafe fn __pin_into_raw(ptr: Pin<UniquePtr<T>>) -> *mut T {
+        Self::into_raw(Pin::into_inner_unchecked(ptr))
+    }
+
+    #[doc(hidden)]
+    pub unsafe fn __pin_from_raw(raw: *mut T) -> Pin<Self> {
+        Pin::new_unchecked(Self::from_raw(raw))
+    }
 }
 
 unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
diff --git a/syntax/check.rs b/syntax/check.rs
index 73ce885..7e368f4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -151,6 +151,24 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
         cx.error(ty, "references with explicit lifetimes are not supported");
     }
 
+    if ty.mutability.is_some() && !ty.pinned {
+        if let Some(requires_pin) = match &ty.inner {
+            Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => {
+                Some(ident.rust.to_string())
+            }
+            Type::CxxVector(_) => Some("CxxVector<...>".to_owned()),
+            _ => None,
+        } {
+            cx.error(
+                ty,
+                format!(
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
+                    requires_pin,
+                ),
+            );
+        }
+    }
+
     match ty.inner {
         Type::Fn(_) | Type::Void(_) => {}
         Type::Ref(_) => {
@@ -251,6 +269,17 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             && !cx.types.rust.contains(&receiver.ty.rust)
         {
             cx.error(span, "unrecognized receiver type");
+        } else if receiver.mutability.is_some()
+            && !receiver.pinned
+            && is_opaque_cxx(cx, &receiver.ty.rust)
+        {
+            cx.error(
+                span,
+                format!(
+                    "mutable reference to C++ type requires a pin -- use `self: Pin<&mut {}>`",
+                    receiver.ty.rust,
+                ),
+            );
         }
 
         if receiver.lifetime.is_some() {
@@ -370,13 +399,14 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
         _ => return false,
     };
-    ident == CxxString
-        || cx.types.cxx.contains(ident)
-            && !cx.types.structs.contains_key(ident)
-            && !cx.types.enums.contains_key(ident)
-            && !(cx.types.aliases.contains_key(ident)
-                && cx.types.required_trivial.contains_key(ident))
-        || cx.types.rust.contains(ident)
+    ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+}
+
+fn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool {
+    cx.types.cxx.contains(ty)
+        && !cx.types.structs.contains_key(ty)
+        && !cx.types.enums.contains_key(ty)
+        && !(cx.types.aliases.contains_key(ty) && cx.types.required_trivial.contains_key(ty))
 }
 
 fn span_for_struct_error(strct: &Struct) -> TokenStream {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a4b393a..58d8fd3 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -81,29 +81,36 @@ impl Eq for Ty1 {}
 impl PartialEq for Ty1 {
     fn eq(&self, other: &Ty1) -> bool {
         let Ty1 {
+            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
+            pin_tokens: _,
         } = self;
         let Ty1 {
+            pinned: pinned2,
             name: name2,
             langle: _,
             inner: inner2,
             rangle: _,
+            pin_tokens: _,
         } = other;
-        name == name2 && inner == inner2
+        pinned == pinned2 && name == name2 && inner == inner2
     }
 }
 
 impl Hash for Ty1 {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ty1 {
+            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         name.hash(state);
         inner.hash(state);
     }
@@ -114,29 +121,39 @@ impl Eq for Ref {}
 impl PartialEq for Ref {
     fn eq(&self, other: &Ref) -> bool {
         let Ref {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             inner,
+            pin_tokens: _,
         } = self;
         let Ref {
+            pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
             mutability: mutability2,
             inner: inner2,
+            pin_tokens: _,
         } = other;
-        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && inner == inner2
+        pinned == pinned2
+            && lifetime == lifetime2
+            && mutability.is_some() == mutability2.is_some()
+            && inner == inner2
     }
 }
 
 impl Hash for Ref {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ref {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             inner,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         lifetime.hash(state);
         mutability.is_some().hash(state);
         inner.hash(state);
@@ -223,35 +240,45 @@ impl Eq for Receiver {}
 impl PartialEq for Receiver {
     fn eq(&self, other: &Receiver) -> bool {
         let Receiver {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             var: _,
             ty,
             shorthand: _,
+            pin_tokens: _,
         } = self;
         let Receiver {
+            pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
             mutability: mutability2,
             var: _,
             ty: ty2,
             shorthand: _,
+            pin_tokens: _,
         } = other;
-        lifetime == lifetime2 && mutability.is_some() == mutability2.is_some() && ty == ty2
+        pinned == pinned2
+            && lifetime == lifetime2
+            && mutability.is_some() == mutability2.is_some()
+            && ty == ty2
     }
 }
 
 impl Hash for Receiver {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Receiver {
+            pinned,
             ampersand: _,
             lifetime,
             mutability,
             var: _,
             ty,
             shorthand: _,
+            pin_tokens: _,
         } = self;
+        pinned.hash(state);
         lifetime.hash(state);
         mutability.is_some().hash(state);
         ty.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 94c2cc8..853db90 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -134,12 +134,14 @@ pub struct Var {
 }
 
 pub struct Receiver {
+    pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub var: Token![self],
     pub ty: ResolvableName,
     pub shorthand: bool,
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Variant {
@@ -163,17 +165,21 @@ pub enum Type {
 }
 
 pub struct Ty1 {
+    pub pinned: bool,
     pub name: Ident,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Ref {
+    pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
     pub mutability: Option<Token![mut]>,
     pub inner: Type,
+    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Slice {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a8a76d0..6010492 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -18,6 +18,7 @@ use syn::{
 };
 
 pub mod kw {
+    syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
 }
 
@@ -387,12 +388,14 @@ fn parse_extern_fn(
             FnArg::Receiver(arg) => {
                 if let Some((ampersand, lifetime)) = &arg.reference {
                     receiver = Some(Receiver {
+                        pinned: false,
                         ampersand: *ampersand,
                         lifetime: lifetime.clone(),
                         mutability: arg.mutability,
                         var: arg.self_token,
                         ty: ResolvableName::make_self(arg.self_token.span),
                         shorthand: true,
+                        pin_tokens: None,
                     });
                     continue;
                 }
@@ -417,12 +420,14 @@ fn parse_extern_fn(
                 if let Type::Ref(reference) = ty {
                     if let Type::Ident(ident) = reference.inner {
                         receiver = Some(Receiver {
+                            pinned: reference.pinned,
                             ampersand: reference.ampersand,
                             lifetime: reference.lifetime,
                             mutability: reference.mutability,
                             var: Token![self](ident.rust.span()),
                             ty: ident,
                             shorthand: false,
+                            pin_tokens: reference.pin_tokens,
                         });
                         continue;
                     }
@@ -625,10 +630,12 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
+        pinned: false,
         ampersand: ty.and_token,
         lifetime: ty.lifetime.clone(),
         mutability: ty.mutability,
         inner,
+        pin_tokens: None,
     })))
 }
 
@@ -644,42 +651,66 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
+                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
+                            pin_tokens: None,
                         })));
                     }
+                } else if ident == "Pin" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg, namespace)?;
+                        let pin_token = kw::Pin(ident.span());
+                        if let Type::Ref(mut inner) = inner {
+                            inner.pinned = true;
+                            inner.pin_tokens =
+                                Some((pin_token, generic.lt_token, generic.gt_token));
+                            return Ok(Type::Ref(inner));
+                        } else if let Type::UniquePtr(mut inner) = inner {
+                            inner.pinned = true;
+                            inner.pin_tokens =
+                                Some((pin_token, generic.lt_token, generic.gt_token));
+                            return Ok(Type::UniquePtr(inner));
+                        }
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 0d6c066..af8088d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -40,6 +40,10 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
+        if let Some((pin, langle, _rangle)) = self.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
@@ -49,15 +53,25 @@ impl ToTokens for Ty1 {
         self.langle.to_tokens(tokens);
         self.inner.to_tokens(tokens);
         self.rangle.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }
 
 impl ToTokens for Ref {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some((pin, langle, _rangle)) = self.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         self.ampersand.to_tokens(tokens);
         self.lifetime.to_tokens(tokens);
         self.mutability.to_tokens(tokens);
         self.inner.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }
 
@@ -172,9 +186,16 @@ impl Receiver {
 
 impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some((pin, langle, _rangle)) = self.0.pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
         self.0.ampersand.to_tokens(tokens);
         self.0.lifetime.to_tokens(tokens);
         self.0.mutability.to_tokens(tokens);
         self.0.ty.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = self.0.pin_tokens {
+            rangle.to_tokens(tokens);
+        }
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ed6740d..825b13b 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -124,7 +124,7 @@ pub mod ffi {
         fn c_return_primitive() -> usize;
         fn c_return_shared() -> Shared;
         fn c_return_box() -> Box<R>;
-        fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_unique_ptr() -> Pin<UniquePtr<C>>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
@@ -137,10 +137,10 @@ pub mod ffi {
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
-        fn c_return_mut_vector(c: &mut C) -> &mut CxxVector<u8>;
+        fn c_return_mut_vector(c: Pin<&mut C>) -> Pin<&mut CxxVector<u8>>;
         fn c_return_rust_vec() -> Vec<u8>;
         fn c_return_ref_rust_vec(c: &C) -> &Vec<u8>;
-        fn c_return_mut_rust_vec(c: &mut C) -> &mut Vec<u8>;
+        fn c_return_mut_rust_vec(c: Pin<&mut C>) -> &mut Vec<u8>;
         fn c_return_rust_vec_string() -> Vec<String>;
         fn c_return_identity(_: usize) -> usize;
         fn c_return_sum(_: usize, _: usize) -> usize;
@@ -199,11 +199,10 @@ pub mod ffi {
         fn c_try_return_ref_rust_vec(c: &C) -> Result<&Vec<u8>>;
 
         fn get(self: &C) -> usize;
-        fn set(self: &mut C, n: usize) -> usize;
+        fn set(self: Pin<&mut C>, n: usize) -> usize;
         fn get2(&self) -> usize;
-        fn set2(&mut self, n: usize) -> usize;
-        fn set_succeed(&mut self, n: usize) -> Result<usize>;
-        fn get_fail(&mut self) -> Result<usize>;
+        fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
+        fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
 
         #[rust_name = "i32_overloaded_method"]
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index aff1b1c..c8363b6 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -8,6 +8,6 @@ pub mod ffi {
 
         type C = crate::ffi::C;
 
-        fn c_take_unique_ptr(c: UniquePtr<C>);
+        fn c_take_unique_ptr(c: Pin<UniquePtr<C>>);
     }
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index fdf7a14..61ef701 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -26,12 +26,7 @@ size_t C::set(size_t n) {
   return this->n;
 }
 
-size_t C::set2(size_t n) {
-  this->n = n;
-  return this->n;
-}
-
-size_t C::set_succeed(size_t n) { return this->set2(n); }
+size_t C::set_succeed(size_t n) { return this->set(n); }
 
 size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index d231939..5acf469 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -45,7 +45,6 @@ public:
   size_t get() const;
   size_t set(size_t n);
   size_t get2() const;
-  size_t set2(size_t n);
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
diff --git a/tests/test.rs b/tests/test.rs
index 2bae4d8..ff6abd9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -188,12 +188,11 @@ fn test_c_method_calls() {
 
     let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.set(2021));
+    assert_eq!(2021, unique_ptr.as_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
-    assert_eq!(old_value, unique_ptr.set2(old_value));
-    assert_eq!(old_value, unique_ptr.get2());
-    assert_eq!(2022, unique_ptr.set_succeed(2022).unwrap());
-    assert!(unique_ptr.get_fail().is_err());
+    assert_eq!(2021, unique_ptr.get2());
+    assert_eq!(2022, unique_ptr.as_mut().set_succeed(2022).unwrap());
+    assert!(unique_ptr.as_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 
diff --git a/tests/ui/pin_mut_opaque.rs b/tests/ui/pin_mut_opaque.rs
new file mode 100644
index 0000000..ac1ca43
--- /dev/null
+++ b/tests/ui/pin_mut_opaque.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Opaque;
+        fn f(arg: &mut Opaque);
+        fn g(&mut self);
+        fn h(self: &mut Opaque);
+        fn s(s: &mut CxxString);
+        fn v(v: &mut CxxVector<u8>);
+    }
+
+}
+
+fn main() {}
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
new file mode 100644
index 0000000..32d5cfc
--- /dev/null
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -0,0 +1,29 @@
+error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque>
+ --> $DIR/pin_mut_opaque.rs:5:19
+  |
+5 |         fn f(arg: &mut Opaque);
+  |                   ^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString>
+ --> $DIR/pin_mut_opaque.rs:8:17
+  |
+8 |         fn s(s: &mut CxxString);
+  |                 ^^^^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>>
+ --> $DIR/pin_mut_opaque.rs:9:17
+  |
+9 |         fn v(v: &mut CxxVector<u8>);
+  |                 ^^^^^^^^^^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+ --> $DIR/pin_mut_opaque.rs:6:14
+  |
+6 |         fn g(&mut self);
+  |              ^^^^^^^^^
+
+error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+ --> $DIR/pin_mut_opaque.rs:7:20
+  |
+7 |         fn h(self: &mut Opaque);
+  |                    ^^^^^^^^^^^

From c90897fb2f8a716f6e75ac2c1b14b740f0d48d5e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:30:20 +0000
Subject: [PATCH 1415/2232] Add ui test with pinned extern Rust type


---

diff --git a/tests/ui/rust_pinned.rs b/tests/ui/rust_pinned.rs
new file mode 100644
index 0000000..34ca7e3
--- /dev/null
+++ b/tests/ui/rust_pinned.rs
@@ -0,0 +1,14 @@
+use std::marker::PhantomPinned;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type Pinned;
+    }
+}
+
+pub struct Pinned {
+    _pinned: PhantomPinned,
+}
+
+fn main() {}

From 20fa62bf715d0915622525660266b3d8edc7e07e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:34:05 +0000
Subject: [PATCH 1416/2232] Enforce opaque Rust types are unpin for now


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index bb93589..94c5696 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -489,10 +489,14 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     let sized = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Sized
     };
+    let unpin = quote_spanned! {ety.semi_token.span=>
+        #begin_span std::marker::Unpin
+    };
     quote_spanned! {ident.span()=>
         let _ = {
             fn __AssertSized<T: ?#sized + #sized>() {}
-            __AssertSized::<#ident>
+            fn __AssertUnpin<T: #unpin>() {}
+            (__AssertSized::<#ident>, __AssertUnpin::<#ident>)
         };
     }
 }
diff --git a/tests/ui/rust_pinned.stderr b/tests/ui/rust_pinned.stderr
new file mode 100644
index 0000000..f16f9d5
--- /dev/null
+++ b/tests/ui/rust_pinned.stderr
@@ -0,0 +1,10 @@
+error[E0277]: `PhantomPinned` cannot be unpinned
+ --> $DIR/rust_pinned.rs:6:14
+  |
+6 |         type Pinned;
+  |         -----^^^^^^-
+  |         |    |
+  |         |    within `Pinned`, the trait `Unpin` is not implemented for `PhantomPinned`
+  |         required by this bound in `__AssertUnpin`
+  |
+  = note: required because it appears within the type `Pinned`

From 0fe6ca2c444c4134d76382e8315173d0d001d83d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 01:34:30 +0000
Subject: [PATCH 1417/2232] Add ui test with explicit Unpin impl


---

diff --git a/tests/ui/unpin_impl.rs b/tests/ui/unpin_impl.rs
new file mode 100644
index 0000000..e10cc72
--- /dev/null
+++ b/tests/ui/unpin_impl.rs
@@ -0,0 +1,12 @@
+use std::marker::Unpin;
+
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque;
+    }
+}
+
+impl Unpin for ffi::Opaque {}
+
+fn main() {}

From 9eef609c190b35996f4df6a21b0ee64930c7f888 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 02:02:32 +0000
Subject: [PATCH 1418/2232] Enforce no explicit Unpin impls


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 94c5696..beb5e62 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -47,6 +47,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                 let ident = &ety.name.rust;
                 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
                     expanded.extend(expand_cxx_type(ety));
+                    hidden.extend(expand_cxx_type_assert_pinned(ety));
                 }
             }
             Api::CxxFunction(efn) => {
@@ -204,6 +205,33 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream {
+    let ident = &ety.name.rust;
+    let infer = Token![_](ident.span());
+
+    quote! {
+        let _ = {
+            // Derived from https://github.com/nvzqz/static-assertions-rs.
+            trait __AmbiguousIfImpl<A> {
+                fn infer() {}
+            }
+
+            impl<T: ?Sized> __AmbiguousIfImpl<()> for T {}
+
+            #[allow(dead_code)]
+            struct __Invalid;
+
+            impl<T: ?Sized + Unpin> __AmbiguousIfImpl<__Invalid> for T {}
+
+            // If there is only one specialized trait impl, type inference with
+            // `_` can be resolved and this can compile. Fails to compile if
+            // user has added a manual Unpin impl for their opaque C++ type as
+            // then `__AmbiguousIfImpl<__Invalid>` also exists.
+            <#ident as __AmbiguousIfImpl<#infer>>::infer
+        };
+    }
+}
+
 fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
diff --git a/tests/ui/unpin_impl.stderr b/tests/ui/unpin_impl.stderr
new file mode 100644
index 0000000..37e4f9d
--- /dev/null
+++ b/tests/ui/unpin_impl.stderr
@@ -0,0 +1,8 @@
+error[E0282]: type annotations needed for `fn()`
+ --> $DIR/unpin_impl.rs:6:14
+  |
+3 | #[cxx::bridge]
+  | -------------- consider giving this pattern the explicit type `fn()`, with the type parameters specified
+...
+6 |         type Opaque;
+  |              ^^^^^^ cannot infer type

From 2306550ad20971f389cc6f10c353cc8f1ae68662 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 02:08:10 +0000
Subject: [PATCH 1419/2232] Merge pull request #475 from dtolnay/unpin


Enforce no explicit Unpin impl on an opaque C++ type
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 94c5696..beb5e62 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -47,6 +47,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                 let ident = &ety.name.rust;
                 if !types.structs.contains_key(ident) && !types.enums.contains_key(ident) {
                     expanded.extend(expand_cxx_type(ety));
+                    hidden.extend(expand_cxx_type_assert_pinned(ety));
                 }
             }
             Api::CxxFunction(efn) => {
@@ -204,6 +205,33 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream {
+    let ident = &ety.name.rust;
+    let infer = Token![_](ident.span());
+
+    quote! {
+        let _ = {
+            // Derived from https://github.com/nvzqz/static-assertions-rs.
+            trait __AmbiguousIfImpl<A> {
+                fn infer() {}
+            }
+
+            impl<T: ?Sized> __AmbiguousIfImpl<()> for T {}
+
+            #[allow(dead_code)]
+            struct __Invalid;
+
+            impl<T: ?Sized + Unpin> __AmbiguousIfImpl<__Invalid> for T {}
+
+            // If there is only one specialized trait impl, type inference with
+            // `_` can be resolved and this can compile. Fails to compile if
+            // user has added a manual Unpin impl for their opaque C++ type as
+            // then `__AmbiguousIfImpl<__Invalid>` also exists.
+            <#ident as __AmbiguousIfImpl<#infer>>::infer
+        };
+    }
+}
+
 fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
diff --git a/tests/ui/unpin_impl.rs b/tests/ui/unpin_impl.rs
new file mode 100644
index 0000000..e10cc72
--- /dev/null
+++ b/tests/ui/unpin_impl.rs
@@ -0,0 +1,12 @@
+use std::marker::Unpin;
+
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque;
+    }
+}
+
+impl Unpin for ffi::Opaque {}
+
+fn main() {}
diff --git a/tests/ui/unpin_impl.stderr b/tests/ui/unpin_impl.stderr
new file mode 100644
index 0000000..37e4f9d
--- /dev/null
+++ b/tests/ui/unpin_impl.stderr
@@ -0,0 +1,8 @@
+error[E0282]: type annotations needed for `fn()`
+ --> $DIR/unpin_impl.rs:6:14
+  |
+3 | #[cxx::bridge]
+  | -------------- consider giving this pattern the explicit type `fn()`, with the type parameters specified
+...
+6 |         type Opaque;
+  |              ^^^^^^ cannot infer type

From 9938b6449d04e1551f6280aa47f1b89bc1b1924a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 03:09:01 +0000
Subject: [PATCH 1420/2232] Allow lifetime in extern fn signature


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index beb5e62..fd2ea32 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -233,6 +233,7 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream {
 }
 
 fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
+    let generics = &efn.generics;
     let receiver = efn.receiver.iter().map(|receiver| {
         let receiver_type = receiver.ty();
         quote!(_: #receiver_type)
@@ -267,7 +268,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
     let local_name = format_ident!("__{}", efn.name.rust);
     quote! {
         #[link_name = #link_name]
-        fn #local_name(#(#all_args,)* #outparam) #ret;
+        fn #local_name #generics(#(#all_args,)* #outparam) #ret;
     }
 }
 
@@ -281,8 +282,9 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             quote!(#var: #ty)
         } else {
             let ampersand = receiver.ampersand;
+            let lifetime = &receiver.lifetime;
             let mutability = receiver.mutability;
-            quote!(#ampersand #mutability #var)
+            quote!(#ampersand #lifetime #mutability #var)
         }
     });
     let args = efn.args.iter().map(|arg| quote!(#arg));
@@ -443,9 +445,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         dispatch = quote!(unsafe { #dispatch });
     }
     let ident = &efn.name.rust;
+    let generics = &efn.generics;
     let function_shim = quote! {
         #doc
-        pub #unsafety fn #ident(#(#all_args,)*) #ret {
+        pub #unsafety fn #ident #generics(#(#all_args,)*) #ret {
             extern "C" {
                 #decl
             }
@@ -552,6 +555,7 @@ fn expand_rust_function_shim_impl(
     catch_unwind_label: String,
     invoke: Option<&Ident>,
 ) -> TokenStream {
+    let generics = &sig.generics;
     let receiver_var = sig
         .receiver
         .as_ref()
@@ -694,7 +698,7 @@ fn expand_rust_function_shim_impl(
     quote! {
         #[doc(hidden)]
         #[export_name = #link_name]
-        unsafe extern "C" fn #local_name(#(#all_args,)* #outparam #pointer) #ret {
+        unsafe extern "C" fn #local_name #generics(#(#all_args,)* #outparam #pointer) #ret {
             let __fn = concat!(module_path!(), #catch_unwind_label);
             #wrap_super
             #expr
@@ -710,6 +714,7 @@ fn expand_rust_function_shim_super(
     invoke: &Ident,
 ) -> TokenStream {
     let unsafety = sig.unsafety;
+    let generics = &sig.generics;
 
     let receiver_var = sig
         .receiver
@@ -747,7 +752,7 @@ fn expand_rust_function_shim_super(
     };
 
     quote_spanned! {span=>
-        #unsafety fn #local_name(#(#all_args,)*) #ret {
+        #unsafety fn #local_name #generics(#(#all_args,)*) #ret {
             #call(#(#vars,)*)
         }
     }
diff --git a/syntax/check.rs b/syntax/check.rs
index 7e368f4..9aaf738 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -147,10 +147,6 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
-    if ty.lifetime.is_some() {
-        cx.error(ty, "references with explicit lifetimes are not supported");
-    }
-
     if ty.mutability.is_some() && !ty.pinned {
         if let Some(requires_pin) = match &ty.inner {
             Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => {
@@ -249,6 +245,25 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
 }
 
 fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
+    match efn.lang {
+        Lang::Cxx => {
+            if !efn.generics.params.is_empty() && !efn.trusted {
+                let ref span = span_for_generics_error(efn);
+                cx.error(span, "extern C++ function with lifetimes must be declared in `unsafe extern \"C++\"` block");
+            }
+        }
+        Lang::Rust => {
+            if !efn.generics.params.is_empty() && efn.unsafety.is_none() {
+                let ref span = span_for_generics_error(efn);
+                let message = format!(
+                    "must be `unsafe fn {}` in order to expose explicit lifetimes to C++",
+                    efn.name.rust,
+                );
+                cx.error(span, message);
+            }
+        }
+    }
+
     if let Some(receiver) = &efn.receiver {
         let ref span = span_for_receiver_error(receiver);
 
@@ -281,10 +296,6 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 ),
             );
         }
-
-        if receiver.lifetime.is_some() {
-            cx.error(span, "references with explicit lifetimes are not supported");
-        }
     }
 
     for arg in &efn.args {
@@ -436,6 +447,13 @@ fn span_for_receiver_error(receiver: &Receiver) -> TokenStream {
     }
 }
 
+fn span_for_generics_error(efn: &ExternFn) -> TokenStream {
+    let unsafety = efn.unsafety;
+    let fn_token = efn.fn_token;
+    let generics = &efn.generics;
+    quote!(#unsafety #fn_token #generics)
+}
+
 fn describe(cx: &mut Check, ty: &Type) -> String {
     match ty {
         Type::Ident(ident) => {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 58d8fd3..318cfae 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -187,6 +187,7 @@ impl PartialEq for Signature {
         let Signature {
             unsafety,
             fn_token: _,
+            generics: _,
             receiver,
             args,
             ret,
@@ -197,6 +198,7 @@ impl PartialEq for Signature {
         let Signature {
             unsafety: unsafety2,
             fn_token: _,
+            generics: _,
             receiver: receiver2,
             args: args2,
             ret: ret2,
@@ -218,6 +220,7 @@ impl Hash for Signature {
         let Signature {
             unsafety,
             fn_token: _,
+            generics: _,
             receiver,
             args,
             ret,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 853db90..9d0f829 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -30,7 +30,7 @@ use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Lifetime, Token, Type as RustType};
+use syn::{Expr, Generics, Lifetime, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -119,6 +119,7 @@ pub struct Impl {
 pub struct Signature {
     pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
+    pub generics: Generics,
     pub receiver: Option<Receiver>,
     pub args: Punctuated<Var, Token![,]>,
     pub ret: Option<Type>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 6010492..fcc44d2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -13,8 +13,9 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat, PathArguments, Result,
-    ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat,
+    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
+    TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -351,7 +352,12 @@ fn parse_extern_fn(
     namespace: &Namespace,
 ) -> Result<Api> {
     let generics = &foreign_fn.sig.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
+    if generics.where_clause.is_some()
+        || generics.params.iter().any(|param| match param {
+            GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(),
+            GenericParam::Type(_) | GenericParam::Const(_) => true,
+        })
+    {
         return Err(Error::new_spanned(
             foreign_fn,
             "extern function with generic parameters is not supported yet",
@@ -447,6 +453,7 @@ fn parse_extern_fn(
         cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
         rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
     );
+    let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
     let api_function = match lang {
@@ -461,6 +468,7 @@ fn parse_extern_fn(
         sig: Signature {
             unsafety,
             fn_token,
+            generics,
             receiver,
             args,
             ret,
@@ -759,6 +767,7 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
         fn_token: ty.fn_token,
+        generics: Generics::default(),
         receiver: None,
         args,
         ret,
diff --git a/tests/ui/disallow_lifetime.rs b/tests/ui/disallow_lifetime.rs
deleted file mode 100644
index a4a7b51..0000000
--- a/tests/ui/disallow_lifetime.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-        type C;
-        fn f(&'static self);
-    }
-
-    extern "Rust" {
-        fn f(string: &'a String);
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/disallow_lifetime.stderr b/tests/ui/disallow_lifetime.stderr
deleted file mode 100644
index d7c42e4..0000000
--- a/tests/ui/disallow_lifetime.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: references with explicit lifetimes are not supported
- --> $DIR/disallow_lifetime.rs:9:22
-  |
-9 |         fn f(string: &'a String);
-  |                      ^^^^^^^^^^
-
-error: references with explicit lifetimes are not supported
- --> $DIR/disallow_lifetime.rs:5:14
-  |
-5 |         fn f(&'static self);
-  |              ^^^^^^^^^^^^^
diff --git a/tests/ui/lifetime_extern_cxx.rs b/tests/ui/lifetime_extern_cxx.rs
new file mode 100644
index 0000000..e85b339
--- /dev/null
+++ b/tests/ui/lifetime_extern_cxx.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque;
+        unsafe fn f<'a>(&'a self, arg: &str) -> &'a str;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetime_extern_cxx.stderr b/tests/ui/lifetime_extern_cxx.stderr
new file mode 100644
index 0000000..099c6ce
--- /dev/null
+++ b/tests/ui/lifetime_extern_cxx.stderr
@@ -0,0 +1,5 @@
+error: extern C++ function with lifetimes must be declared in `unsafe extern "C++"` block
+ --> $DIR/lifetime_extern_cxx.rs:5:9
+  |
+5 |         unsafe fn f<'a>(&'a self, arg: &str) -> &'a str;
+  |         ^^^^^^^^^^^^^^^
diff --git a/tests/ui/lifetime_extern_rust.rs b/tests/ui/lifetime_extern_rust.rs
new file mode 100644
index 0000000..72c37cb
--- /dev/null
+++ b/tests/ui/lifetime_extern_rust.rs
@@ -0,0 +1,17 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type Opaque;
+        fn f<'a>(&'a self, arg: &str) -> &'a str;
+    }
+}
+
+pub struct Opaque;
+
+impl Opaque {
+    fn f(&self, _arg: &str) -> &str {
+        ""
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/lifetime_extern_rust.stderr b/tests/ui/lifetime_extern_rust.stderr
new file mode 100644
index 0000000..0fc806a
--- /dev/null
+++ b/tests/ui/lifetime_extern_rust.stderr
@@ -0,0 +1,5 @@
+error: must be `unsafe fn f` in order to expose explicit lifetimes to C++
+ --> $DIR/lifetime_extern_rust.rs:5:9
+  |
+5 |         fn f<'a>(&'a self, arg: &str) -> &'a str;
+  |         ^^^^^^^^

From a7525d3f129fda641797f768bbac2eefdaf1d81d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 03:13:26 +0000
Subject: [PATCH 1421/2232] Require Pin<&mut CxxString> for push


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 7ee8987..1295e88 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -2,6 +2,7 @@ use alloc::borrow::Cow;
 use alloc::string::String;
 use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
+use core::pin::Pin;
 use core::slice;
 use core::str::{self, Utf8Error};
 
@@ -88,13 +89,16 @@ impl CxxString {
     }
 
     /// Appends a given string slice onto the end of this C++ string.
-    pub fn push_str(&mut self, s: &str) {
+    pub fn push_str(self: Pin<&mut Self>, s: &str) {
         self.push_bytes(s.as_bytes());
     }
 
     /// Appends arbitrary bytes onto the end of this C++ string.
-    pub fn push_bytes(&mut self, bytes: &[u8]) {
-        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
+    pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
+        unsafe {
+            let this = Pin::into_inner_unchecked(self);
+            string_push(this, bytes.as_ptr(), bytes.len())
+        }
     }
 }
 

From de1335fa3dc094ccf3b9322827c640f64c7c34b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 03:47:02 +0000
Subject: [PATCH 1422/2232] Simplify CxxString push_bytes implementation


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 1295e88..273905e 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -12,7 +12,7 @@ extern "C" {
     #[link_name = "cxxbridge05$cxx_string$length"]
     fn string_length(this: &CxxString) -> usize;
     #[link_name = "cxxbridge05$cxx_string$push"]
-    fn string_push(this: &mut CxxString, ptr: *const u8, len: usize);
+    fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
 }
 
 /// Binding to C++ `std::string`.
@@ -95,10 +95,7 @@ impl CxxString {
 
     /// Appends arbitrary bytes onto the end of this C++ string.
     pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) {
-        unsafe {
-            let this = Pin::into_inner_unchecked(self);
-            string_push(this, bytes.as_ptr(), bytes.len())
-        }
+        unsafe { string_push(self, bytes.as_ptr(), bytes.len()) }
     }
 }
 

From bb3ff5d34e064311d5d97c33b516655012421d4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 04:38:24 +0000
Subject: [PATCH 1423/2232] Add Rust constructor for pinned CxxString on stack


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 1295d04..423f72e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -9,6 +9,16 @@
 #include <vector>
 
 extern "C" {
+void cxxbridge05$cxx_string$init(std::string *s, const uint8_t *ptr,
+                                 size_t len) noexcept {
+  new (s) std::string(reinterpret_cast<const char *>(ptr), len);
+}
+
+void cxxbridge05$cxx_string$destroy(std::string *s) noexcept {
+  using std::string;
+  s->~string();
+}
+
 const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
@@ -230,6 +240,11 @@ void cxxbridge05$unique_ptr$std$string$drop(
 }
 } // extern "C"
 
+static_assert(alignof(std::string) <= alignof(void *),
+              "unexpectedly large std::string alignment");
+static_assert(sizeof(std::string) <= 8 * sizeof(void *),
+              "unexpectedly large std::string size");
+
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 273905e..7a66b47 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,12 +1,18 @@
+use crate::actually_private::Private;
 use alloc::borrow::Cow;
 use alloc::string::String;
 use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
+use core::mem::MaybeUninit;
 use core::pin::Pin;
 use core::slice;
 use core::str::{self, Utf8Error};
 
 extern "C" {
+    #[link_name = "cxxbridge05$cxx_string$init"]
+    fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
+    #[link_name = "cxxbridge05$cxx_string$destroy"]
+    fn string_destroy(this: &mut MaybeUninit<CxxString>);
     #[link_name = "cxxbridge05$cxx_string$data"]
     fn string_data(this: &CxxString) -> *const u8;
     #[link_name = "cxxbridge05$cxx_string$length"]
@@ -31,7 +37,53 @@ pub struct CxxString {
     _pinned: PhantomData<PhantomPinned>,
 }
 
+/// Construct a C++ std::string on the Rust stack.
+///
+/// # Syntax
+///
+/// In statement position:
+///
+/// ```
+/// # use cxx::let_cxx_string;
+/// # let expression = "";
+/// let_cxx_string!(var = expression);
+/// ```
+///
+/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
+/// it will be a string literal, but for example `&[u8]` and `String` would work
+/// as well.
+///
+/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
+/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
+///
+/// # Example
+///
+/// ```
+/// use cxx::{let_cxx_string, CxxString};
+///
+/// fn f(s: &CxxString) {/* ... */}
+///
+/// fn main() {
+///     let_cxx_string!(s = "example");
+///     f(&s);
+/// }
+/// ```
+#[macro_export]
+macro_rules! let_cxx_string {
+    ($var:ident = $value:expr $(,)?) => {
+        let mut $var = $crate::private::StackString::new();
+        #[allow(unused_mut, unused_unsafe)]
+        let mut $var = unsafe { $var.init($value) };
+    };
+}
+
 impl CxxString {
+    /// `CxxString` is not constructible via `new`. Instead, use the
+    /// [`let_cxx_string!`] macro.
+    pub fn new<T: Private>() -> Self {
+        unreachable!()
+    }
+
     /// Returns the length of the string in bytes.
     ///
     /// Matches the behavior of C++ [std::string::size][size].
@@ -128,3 +180,35 @@ impl PartialEq<str> for CxxString {
         self.as_bytes() == other.as_bytes()
     }
 }
+
+#[doc(hidden)]
+#[repr(C)]
+pub struct StackString {
+    // Static assertions in cxx.cc validate that this is large enough and
+    // aligned enough.
+    space: MaybeUninit<[*const (); 8]>,
+}
+
+impl StackString {
+    pub fn new() -> Self {
+        StackString {
+            space: MaybeUninit::uninit(),
+        }
+    }
+
+    pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
+        let value = value.as_ref();
+        let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
+        string_init(this, value.as_ptr(), value.len());
+        Pin::new_unchecked(&mut *this.as_mut_ptr())
+    }
+}
+
+impl Drop for StackString {
+    fn drop(&mut self) {
+        unsafe {
+            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
+            string_destroy(this);
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 5a03ebf..7a6dcf9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -426,6 +426,7 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_string::StackString;
     pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
@@ -439,6 +440,10 @@ pub mod private {
     pub use crate::unwind::catch_unwind;
 }
 
+mod actually_private {
+    pub trait Private {}
+}
+
 macro_rules! chars {
     ($($ch:ident)*) => {
         $(

From 94bfe982071799d26f99602c9dc374b41bcb1184 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 04:44:26 +0000
Subject: [PATCH 1424/2232] Merge pull request #476 from dtolnay/string


Add Rust constructor for pinned CxxString on the Rust stack
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 1295d04..423f72e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -9,6 +9,16 @@
 #include <vector>
 
 extern "C" {
+void cxxbridge05$cxx_string$init(std::string *s, const uint8_t *ptr,
+                                 size_t len) noexcept {
+  new (s) std::string(reinterpret_cast<const char *>(ptr), len);
+}
+
+void cxxbridge05$cxx_string$destroy(std::string *s) noexcept {
+  using std::string;
+  s->~string();
+}
+
 const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
@@ -230,6 +240,11 @@ void cxxbridge05$unique_ptr$std$string$drop(
 }
 } // extern "C"
 
+static_assert(alignof(std::string) <= alignof(void *),
+              "unexpectedly large std::string alignment");
+static_assert(sizeof(std::string) <= 8 * sizeof(void *),
+              "unexpectedly large std::string size");
+
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 273905e..7a66b47 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,12 +1,18 @@
+use crate::actually_private::Private;
 use alloc::borrow::Cow;
 use alloc::string::String;
 use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
+use core::mem::MaybeUninit;
 use core::pin::Pin;
 use core::slice;
 use core::str::{self, Utf8Error};
 
 extern "C" {
+    #[link_name = "cxxbridge05$cxx_string$init"]
+    fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
+    #[link_name = "cxxbridge05$cxx_string$destroy"]
+    fn string_destroy(this: &mut MaybeUninit<CxxString>);
     #[link_name = "cxxbridge05$cxx_string$data"]
     fn string_data(this: &CxxString) -> *const u8;
     #[link_name = "cxxbridge05$cxx_string$length"]
@@ -31,7 +37,53 @@ pub struct CxxString {
     _pinned: PhantomData<PhantomPinned>,
 }
 
+/// Construct a C++ std::string on the Rust stack.
+///
+/// # Syntax
+///
+/// In statement position:
+///
+/// ```
+/// # use cxx::let_cxx_string;
+/// # let expression = "";
+/// let_cxx_string!(var = expression);
+/// ```
+///
+/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly
+/// it will be a string literal, but for example `&[u8]` and `String` would work
+/// as well.
+///
+/// The macro expands to something resembling `let $var: Pin<&mut CxxString> =
+/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed.
+///
+/// # Example
+///
+/// ```
+/// use cxx::{let_cxx_string, CxxString};
+///
+/// fn f(s: &CxxString) {/* ... */}
+///
+/// fn main() {
+///     let_cxx_string!(s = "example");
+///     f(&s);
+/// }
+/// ```
+#[macro_export]
+macro_rules! let_cxx_string {
+    ($var:ident = $value:expr $(,)?) => {
+        let mut $var = $crate::private::StackString::new();
+        #[allow(unused_mut, unused_unsafe)]
+        let mut $var = unsafe { $var.init($value) };
+    };
+}
+
 impl CxxString {
+    /// `CxxString` is not constructible via `new`. Instead, use the
+    /// [`let_cxx_string!`] macro.
+    pub fn new<T: Private>() -> Self {
+        unreachable!()
+    }
+
     /// Returns the length of the string in bytes.
     ///
     /// Matches the behavior of C++ [std::string::size][size].
@@ -128,3 +180,35 @@ impl PartialEq<str> for CxxString {
         self.as_bytes() == other.as_bytes()
     }
 }
+
+#[doc(hidden)]
+#[repr(C)]
+pub struct StackString {
+    // Static assertions in cxx.cc validate that this is large enough and
+    // aligned enough.
+    space: MaybeUninit<[*const (); 8]>,
+}
+
+impl StackString {
+    pub fn new() -> Self {
+        StackString {
+            space: MaybeUninit::uninit(),
+        }
+    }
+
+    pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> {
+        let value = value.as_ref();
+        let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
+        string_init(this, value.as_ptr(), value.len());
+        Pin::new_unchecked(&mut *this.as_mut_ptr())
+    }
+}
+
+impl Drop for StackString {
+    fn drop(&mut self) {
+        unsafe {
+            let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>();
+            string_destroy(this);
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 5a03ebf..7a6dcf9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -426,6 +426,7 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_string::StackString;
     pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
@@ -439,6 +440,10 @@ pub mod private {
     pub use crate::unwind::catch_unwind;
 }
 
+mod actually_private {
+    pub trait Private {}
+}
+
 macro_rules! chars {
     ($($ch:ident)*) => {
         $(

From 9c4ac2e507ca11d7ea4b883b4fb45dcb858a0ce4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 05:18:03 +0000
Subject: [PATCH 1425/2232] Represent mutability checks more concisely


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5708b49..a014e63 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -344,7 +344,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     let mangled = mangle::extern_fn(efn, out.types);
     write!(out, "{}(", mangled);
     if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
+        if !receiver.mutable {
             write!(out, "const ");
         }
         write!(
@@ -392,7 +392,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     write!(out, ")");
     if let Some(receiver) = &efn.receiver {
-        if receiver.mutability.is_none() {
+        if !receiver.mutable {
             write!(out, " const");
         }
     }
@@ -556,7 +556,7 @@ fn write_rust_function_decl_impl(
     write!(out, "{}(", link_name);
     let mut needs_comma = false;
     if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
+        if !receiver.mutable {
             write!(out, "const ");
         }
         write!(
@@ -627,7 +627,7 @@ fn write_rust_function_shim_decl(
     }
     write!(out, ")");
     if let Some(receiver) = &sig.receiver {
-        if receiver.mutability.is_none() {
+        if !receiver.mutable {
             write!(out, " const");
         }
     }
@@ -785,7 +785,7 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) {
             write!(out, "*");
         }
         Type::Ref(ty) => {
-            if ty.mutability.is_none() {
+            if !ty.mutable {
                 write!(out, "const ");
             }
             write_type(out, &ty.inner);
@@ -811,7 +811,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write!(out, "*");
         }
         Some(Type::Ref(ty)) => {
-            if ty.mutability.is_none() {
+            if !ty.mutable {
                 write!(out, "const ");
             }
             write_type(out, &ty.inner);
@@ -871,7 +871,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Ref(r) => {
-            if r.mutability.is_none() {
+            if !r.mutable {
                 write!(out, "const ");
             }
             write_type(out, &r.inner);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index fd2ea32..908d8bd 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -316,21 +316,21 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             },
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                    None => quote!(::cxx::private::RustString::from_ref(#var)),
-                    Some(_) => quote!(::cxx::private::RustString::from_mut(#var)),
+                Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
+                    false => quote!(::cxx::private::RustString::from_ref(#var)),
+                    true => quote!(::cxx::private::RustString::from_mut(#var)),
                 },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
-                    Some(_) => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
+                    false => quote!(::cxx::private::RustVec::from_ref_vec_string(#var)),
+                    true => quote!(::cxx::private::RustVec::from_mut_vec_string(#var)),
                 },
-                Type::RustVec(_) => match ty.mutability {
-                    None => quote!(::cxx::private::RustVec::from_ref(#var)),
-                    Some(_) => quote!(::cxx::private::RustVec::from_mut(#var)),
+                Type::RustVec(_) => match ty.mutable {
+                    false => quote!(::cxx::private::RustVec::from_ref(#var)),
+                    true => quote!(::cxx::private::RustVec::from_mut(#var)),
                 },
-                inner if types.is_considered_improper_ctype(inner) => match ty.mutability {
-                    None => quote!(#var as *const #inner as *const ::std::ffi::c_void),
-                    Some(_) => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
+                inner if types.is_considered_improper_ctype(inner) => match ty.mutable {
+                    false => quote!(#var as *const #inner as *const ::std::ffi::c_void),
+                    true => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
                 },
                 _ => quote!(#var),
             },
@@ -412,17 +412,17 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     true => quote!(::cxx::UniquePtr::__pin_from_raw(#call)),
                 },
                 Type::Ref(ty) => match &ty.inner {
-                    Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                        None => quote!(#call.as_string()),
-                        Some(_) => quote!(#call.as_mut_string()),
+                    Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
+                        false => quote!(#call.as_string()),
+                        true => quote!(#call.as_mut_string()),
                     },
-                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                        None => quote!(#call.as_vec_string()),
-                        Some(_) => quote!(#call.as_mut_vec_string()),
+                    Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
+                        false => quote!(#call.as_vec_string()),
+                        true => quote!(#call.as_mut_vec_string()),
                     },
-                    Type::RustVec(_) => match ty.mutability {
-                        None => quote!(#call.as_vec()),
-                        Some(_) => quote!(#call.as_mut_vec()),
+                    Type::RustVec(_) => match ty.mutable {
+                        false => quote!(#call.as_vec()),
+                        true => quote!(#call.as_mut_vec()),
                     },
                     inner if types.is_considered_improper_ctype(inner) => {
                         let mutability = ty.mutability;
@@ -594,17 +594,17 @@ fn expand_rust_function_shim_impl(
                 true => quote!(::cxx::UniquePtr::__pin_from_raw(#ident)),
             },
             Type::Ref(ty) => match &ty.inner {
-                Type::Ident(i) if i.rust == RustString => match ty.mutability {
-                    None => quote!(#ident.as_string()),
-                    Some(_) => quote!(#ident.as_mut_string()),
+                Type::Ident(i) if i.rust == RustString => match ty.mutable {
+                    false => quote!(#ident.as_string()),
+                    true => quote!(#ident.as_mut_string()),
                 },
-                Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                    None => quote!(#ident.as_vec_string()),
-                    Some(_) => quote!(#ident.as_mut_vec_string()),
+                Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
+                    false => quote!(#ident.as_vec_string()),
+                    true => quote!(#ident.as_mut_vec_string()),
                 },
-                Type::RustVec(_) => match ty.mutability {
-                    None => quote!(#ident.as_vec()),
-                    Some(_) => quote!(#ident.as_mut_vec()),
+                Type::RustVec(_) => match ty.mutable {
+                    false => quote!(#ident.as_vec()),
+                    true => quote!(#ident.as_mut_vec()),
                 },
                 _ => quote!(#ident),
             },
@@ -641,17 +641,17 @@ fn expand_rust_function_shim_impl(
             true => Some(quote!(::cxx::UniquePtr::__pin_into_raw)),
         },
         Type::Ref(ty) => match &ty.inner {
-            Type::Ident(ident) if ident.rust == RustString => match ty.mutability {
-                None => Some(quote!(::cxx::private::RustString::from_ref)),
-                Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
+            Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
+                false => Some(quote!(::cxx::private::RustString::from_ref)),
+                true => Some(quote!(::cxx::private::RustString::from_mut)),
             },
-            Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
-                None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string)),
-                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string)),
+            Type::RustVec(vec) if vec.inner == RustString => match ty.mutable {
+                false => Some(quote!(::cxx::private::RustVec::from_ref_vec_string)),
+                true => Some(quote!(::cxx::private::RustVec::from_mut_vec_string)),
             },
-            Type::RustVec(_) => match ty.mutability {
-                None => Some(quote!(::cxx::private::RustVec::from_ref)),
-                Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
+            Type::RustVec(_) => match ty.mutable {
+                false => Some(quote!(::cxx::private::RustVec::from_ref)),
+                true => Some(quote!(::cxx::private::RustVec::from_mut)),
             },
             _ => None,
         },
@@ -1087,9 +1087,9 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
                     let inner = expand_extern_type(&ty.inner, types, proper);
                     quote!(&#mutability ::cxx::private::RustVec<#inner>)
                 }
-                inner if proper && types.is_considered_improper_ctype(inner) => match mutability {
-                    None => quote!(*const ::std::ffi::c_void),
-                    Some(_) => quote!(*#mutability ::std::ffi::c_void),
+                inner if proper && types.is_considered_improper_ctype(inner) => match ty.mutable {
+                    false => quote!(*const ::std::ffi::c_void),
+                    true => quote!(*#mutability ::std::ffi::c_void),
                 },
                 _ => quote!(#ty),
             }
diff --git a/syntax/check.rs b/syntax/check.rs
index 9aaf738..53dd843 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -147,7 +147,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
-    if ty.mutability.is_some() && !ty.pinned {
+    if ty.mutable && !ty.pinned {
         if let Some(requires_pin) = match &ty.inner {
             Type::Ident(ident) if ident.rust == CxxString || is_opaque_cxx(cx, &ident.rust) => {
                 Some(ident.rust.to_string())
@@ -268,9 +268,9 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
         let ref span = span_for_receiver_error(receiver);
 
         if receiver.ty.is_self() {
-            let mutability = match receiver.mutability {
-                Some(_) => "mut ",
-                None => "",
+            let mutability = match receiver.mutable {
+                true => "mut ",
+                false => "",
             };
             let msg = format!(
                 "unnamed receiver type is only allowed if the surrounding \
@@ -284,10 +284,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             && !cx.types.rust.contains(&receiver.ty.rust)
         {
             cx.error(span, "unrecognized receiver type");
-        } else if receiver.mutability.is_some()
-            && !receiver.pinned
-            && is_opaque_cxx(cx, &receiver.ty.rust)
-        {
+        } else if receiver.mutable && !receiver.pinned && is_opaque_cxx(cx, &receiver.ty.rust) {
             cx.error(
                 span,
                 format!(
@@ -346,13 +343,13 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
 
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     match &efn.ret {
-        Some(Type::Ref(ty)) if ty.mutability.is_some() => {}
+        Some(Type::Ref(ty)) if ty.mutable => {}
         _ => return,
     }
 
     for arg in &efn.args {
         if let Type::Ref(ty) = &arg.ty {
-            if ty.mutability.is_some() {
+            if ty.mutable {
                 return;
             }
         }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 318cfae..c11c386 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -124,22 +124,21 @@ impl PartialEq for Ref {
             pinned,
             ampersand: _,
             lifetime,
-            mutability,
+            mutable,
             inner,
             pin_tokens: _,
+            mutability: _,
         } = self;
         let Ref {
             pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
-            mutability: mutability2,
+            mutable: mutable2,
             inner: inner2,
             pin_tokens: _,
+            mutability: _,
         } = other;
-        pinned == pinned2
-            && lifetime == lifetime2
-            && mutability.is_some() == mutability2.is_some()
-            && inner == inner2
+        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2
     }
 }
 
@@ -149,13 +148,14 @@ impl Hash for Ref {
             pinned,
             ampersand: _,
             lifetime,
-            mutability,
+            mutable,
             inner,
             pin_tokens: _,
+            mutability: _,
         } = self;
         pinned.hash(state);
         lifetime.hash(state);
-        mutability.is_some().hash(state);
+        mutable.hash(state);
         inner.hash(state);
     }
 }
@@ -246,26 +246,25 @@ impl PartialEq for Receiver {
             pinned,
             ampersand: _,
             lifetime,
-            mutability,
+            mutable,
             var: _,
             ty,
             shorthand: _,
             pin_tokens: _,
+            mutability: _,
         } = self;
         let Receiver {
             pinned: pinned2,
             ampersand: _,
             lifetime: lifetime2,
-            mutability: mutability2,
+            mutable: mutable2,
             var: _,
             ty: ty2,
             shorthand: _,
             pin_tokens: _,
+            mutability: _,
         } = other;
-        pinned == pinned2
-            && lifetime == lifetime2
-            && mutability.is_some() == mutability2.is_some()
-            && ty == ty2
+        pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && ty == ty2
     }
 }
 
@@ -275,15 +274,16 @@ impl Hash for Receiver {
             pinned,
             ampersand: _,
             lifetime,
-            mutability,
+            mutable,
             var: _,
             ty,
             shorthand: _,
             pin_tokens: _,
+            mutability: _,
         } = self;
         pinned.hash(state);
         lifetime.hash(state);
-        mutability.is_some().hash(state);
+        mutable.hash(state);
         ty.hash(state);
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9d0f829..7f9b918 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -138,11 +138,12 @@ pub struct Receiver {
     pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
-    pub mutability: Option<Token![mut]>,
+    pub mutable: bool,
     pub var: Token![self],
     pub ty: ResolvableName,
     pub shorthand: bool,
     pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
+    pub mutability: Option<Token![mut]>,
 }
 
 pub struct Variant {
@@ -178,9 +179,10 @@ pub struct Ref {
     pub pinned: bool,
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
-    pub mutability: Option<Token![mut]>,
+    pub mutable: bool,
     pub inner: Type,
     pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
+    pub mutability: Option<Token![mut]>,
 }
 
 pub struct Slice {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index fcc44d2..c4549ea 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -397,11 +397,12 @@ fn parse_extern_fn(
                         pinned: false,
                         ampersand: *ampersand,
                         lifetime: lifetime.clone(),
-                        mutability: arg.mutability,
+                        mutable: arg.mutability.is_some(),
                         var: arg.self_token,
                         ty: ResolvableName::make_self(arg.self_token.span),
                         shorthand: true,
                         pin_tokens: None,
+                        mutability: arg.mutability,
                     });
                     continue;
                 }
@@ -429,11 +430,12 @@ fn parse_extern_fn(
                             pinned: reference.pinned,
                             ampersand: reference.ampersand,
                             lifetime: reference.lifetime,
-                            mutability: reference.mutability,
+                            mutable: reference.mutable,
                             var: Token![self](ident.rust.span()),
                             ty: ident,
                             shorthand: false,
                             pin_tokens: reference.pin_tokens,
+                            mutability: reference.mutability,
                         });
                         continue;
                     }
@@ -641,9 +643,10 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
         pinned: false,
         ampersand: ty.and_token,
         lifetime: ty.lifetime.clone(),
-        mutability: ty.mutability,
+        mutable: ty.mutability.is_some(),
         inner,
         pin_tokens: None,
+        mutability: ty.mutability,
     })))
 }
 

From 4f71cc5c821f83615cbf55a8e59aa9b3b6d107c3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 07:55:27 +0000
Subject: [PATCH 1426/2232] Add CxxVector::iter


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d25ea91..e495a97 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -82,6 +82,11 @@ where
             unsafe { slice::from_raw_parts(ptr, len) }
         }
     }
+
+    /// Returns an iterator over elements of type `&T`.
+    pub fn iter(&self) -> Iter<T> {
+        Iter { v: self, index: 0 }
+    }
 }
 
 pub struct Iter<'a, T> {
@@ -97,7 +102,7 @@ where
     type IntoIter = Iter<'a, T>;
 
     fn into_iter(self) -> Self::IntoIter {
-        Iter { v: self, index: 0 }
+        self.iter()
     }
 }
 

From 9a69d8ab6af5d6b25ac01c880a55228c9f55e012 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 17:16:44 +0000
Subject: [PATCH 1427/2232] Fix missing cstdint import when generating enums


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 33ed31c..2d527dd 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -90,6 +90,7 @@ pub struct Enum {
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
+    pub repr_type: Type,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b557584..57520d9 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -7,7 +7,7 @@ use crate::syntax::{
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
-use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
@@ -178,6 +178,9 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
+    let ident = Ident::new(repr.as_ref(), Span::call_site());
+    let repr_type = Type::Ident(ResolvableName::new(ident));
+
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
@@ -185,6 +188,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         brace_token,
         variants,
         repr,
+        repr_type,
     }))
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 90a8221..92c9a75 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -94,6 +94,7 @@ impl<'a> Types<'a> {
                     add_resolution(&strct.name);
                 }
                 Api::Enum(enm) => {
+                    all.insert(&enm.repr_type);
                     let ident = &enm.name.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)

From 020ff1e5a6c4265ebe8bcb807e15e5576e98e92f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 17:24:50 +0000
Subject: [PATCH 1428/2232] Merge pull request #478 from dtolnay/enumint


Fix missing cstdint import when generating enums
---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 7f9b918..131639f 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -90,6 +90,7 @@ pub struct Enum {
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
+    pub repr_type: Type,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c4549ea..5e10116 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -7,7 +7,7 @@ use crate::syntax::{
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
-use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
+use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
@@ -180,6 +180,9 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
+    let ident = Ident::new(repr.as_ref(), Span::call_site());
+    let repr_type = Type::Ident(ResolvableName::new(ident));
+
     Ok(Api::Enum(Enum {
         doc,
         enum_token,
@@ -187,6 +190,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         brace_token,
         variants,
         repr,
+        repr_type,
     }))
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 90a8221..92c9a75 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -94,6 +94,7 @@ impl<'a> Types<'a> {
                     add_resolution(&strct.name);
                 }
                 Api::Enum(enm) => {
+                    all.insert(&enm.repr_type);
                     let ident = &enm.name.rust;
                     if !type_names.insert(ident)
                         && (!cxx.contains(ident)

From b675ca30abbb820440ab32eaa29c14ef8b1ea497 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 17:26:08 +0000
Subject: [PATCH 1429/2232] Release 0.5.10


---

diff --git a/Cargo.toml b/Cargo.toml
index f0692ae..1bede61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.9" # remember to update html_root_url
+version = "0.5.10" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.9", path = "macro" }
+cxxbridge-macro = { version = "=0.5.10", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.9", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.10", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.9", path = "gen/build" }
+cxx-build = { version = "=0.5.10", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index cc5f230..cd9072e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3f7b0ea..0fc2004 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index f3bdebf..8fbef1e 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 2de0f28..c1af1c2 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.6"
+version = "0.6.7"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 6b07a07..5ba8478 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 6ac5309..fdbc135 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,7 +354,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.9")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.10")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 76b95f0..b074415 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.6"
+version = "0.6.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.9"
+version = "0.5.10"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cxx",
  "proc-macro2",

From 099adee57b8980926751a31384357ae5b6b8825b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 16 2020 17:28:10 +0000
Subject: [PATCH 1430/2232] Merge 0.5.10 into master


---

diff --git a/Cargo.toml b/Cargo.toml
index f0692ae..1bede61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.9" # remember to update html_root_url
+version = "0.5.10" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge05"
@@ -20,15 +20,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.9", path = "macro" }
+cxxbridge-macro = { version = "=0.5.10", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.9", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=0.5.10", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.9", path = "gen/build" }
+cxx-build = { version = "=0.5.10", path = "gen/build" }
 cxx-gen = { version = "0.6", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index cc5f230..cd9072e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3f7b0ea..0fc2004 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index f3bdebf..8fbef1e 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 2de0f28..c1af1c2 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.6"
+version = "0.6.7"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 6b07a07..5ba8478 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.9"
+version = "0.5.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 7a6dcf9..c92178a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -354,7 +354,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.9")]
+#![doc(html_root_url = "https://docs.rs/cxx/0.5.10")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 76b95f0..b074415 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.6"
+version = "0.6.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.9"
+version = "0.5.10"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.9"
+version = "0.5.10"
 dependencies = [
  "cxx",
  "proc-macro2",

From 6fdeeebee00929bdb67031e2a707388dda6e250c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 07:33:49 +0000
Subject: [PATCH 1431/2232] Remove &mut T access from UniquePtr


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 283c2f1..3bb3ed3 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -6,7 +6,7 @@ use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
-use core::ops::{Deref, DerefMut};
+use core::ops::Deref;
 use core::pin::Pin;
 use core::ptr;
 
@@ -59,10 +59,13 @@ where
         unsafe { T::__get(self.repr).as_ref() }
     }
 
-    /// Returns a mutable reference to the object owned by this UniquePtr if
-    /// any, otherwise None.
-    pub fn as_mut(&mut self) -> Option<&mut T> {
-        unsafe { (T::__get(self.repr) as *mut T).as_mut() }
+    /// Returns a mutable pinned reference to the object owned by this UniquePtr
+    /// if any, otherwise None.
+    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
+        unsafe {
+            let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?;
+            Some(Pin::new_unchecked(mut_reference))
+        }
     }
 
     /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
@@ -126,18 +129,6 @@ where
     }
 }
 
-impl<T> DerefMut for UniquePtr<T>
-where
-    T: UniquePtrTarget,
-{
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        match self.as_mut() {
-            Some(target) => target,
-            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
-        }
-    }
-}
-
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 825b13b..ba9383a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -124,7 +124,7 @@ pub mod ffi {
         fn c_return_primitive() -> usize;
         fn c_return_shared() -> Shared;
         fn c_return_box() -> Box<R>;
-        fn c_return_unique_ptr() -> Pin<UniquePtr<C>>;
+        fn c_return_unique_ptr() -> UniquePtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index c8363b6..aff1b1c 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -8,6 +8,6 @@ pub mod ffi {
 
         type C = crate::ffi::C;
 
-        fn c_take_unique_ptr(c: Pin<UniquePtr<C>>);
+        fn c_take_unique_ptr(c: UniquePtr<C>);
     }
 }
diff --git a/tests/test.rs b/tests/test.rs
index ff6abd9..da858ff 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -188,11 +188,14 @@ fn test_c_method_calls() {
 
     let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.as_mut().set(2021));
+    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
-    assert_eq!(2022, unique_ptr.as_mut().set_succeed(2022).unwrap());
-    assert!(unique_ptr.as_mut().get_fail().is_err());
+    assert_eq!(
+        2022,
+        unique_ptr.as_mut().unwrap().set_succeed(2022).unwrap(),
+    );
+    assert!(unique_ptr.as_mut().unwrap().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 

From bf7ae81229e7e7e361575c4f0af4a7b43644d649 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 07:36:05 +0000
Subject: [PATCH 1432/2232] Remove Pin UniquePtr support


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 908d8bd..4f703b1 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -9,7 +9,6 @@ use crate::syntax::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
-use std::collections::BTreeSet as Set;
 use std::mem;
 use syn::{parse_quote, Result, Token};
 
@@ -61,7 +60,6 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         }
     }
 
-    let mut expanded_unique_ptr = Set::new();
     for ty in types {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
@@ -80,7 +78,6 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
                     && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                    && expanded_unique_ptr.insert(&ident.rust)
                 {
                     expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
@@ -310,10 +307,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 quote!(#var.as_mut_ptr() as *const ::cxx::private::RustString)
             }
             Type::RustBox(_) => quote!(::std::boxed::Box::into_raw(#var)),
-            Type::UniquePtr(ptr) => match ptr.pinned {
-                false => quote!(::cxx::UniquePtr::into_raw(#var)),
-                true => quote!(::cxx::UniquePtr::__pin_into_raw(#var)),
-            },
+            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::into_raw(#var)),
             Type::RustVec(_) => quote!(#var.as_mut_ptr() as *const ::cxx::private::RustVec<_>),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
@@ -407,10 +401,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                         quote!(#call.into_vec())
                     }
                 }
-                Type::UniquePtr(ptr) => match ptr.pinned {
-                    false => quote!(::cxx::UniquePtr::from_raw(#call)),
-                    true => quote!(::cxx::UniquePtr::__pin_from_raw(#call)),
-                },
+                Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#call)),
                 Type::Ref(ty) => match &ty.inner {
                     Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
                         false => quote!(#call.as_string()),
@@ -589,10 +580,7 @@ fn expand_rust_function_shim_impl(
                     quote!(::std::mem::take((*#ident).as_mut_vec()))
                 }
             }
-            Type::UniquePtr(ptr) => match ptr.pinned {
-                false => quote!(::cxx::UniquePtr::from_raw(#ident)),
-                true => quote!(::cxx::UniquePtr::__pin_from_raw(#ident)),
-            },
+            Type::UniquePtr(_) => quote!(::cxx::UniquePtr::from_raw(#ident)),
             Type::Ref(ty) => match &ty.inner {
                 Type::Ident(i) if i.rust == RustString => match ty.mutable {
                     false => quote!(#ident.as_string()),
@@ -636,10 +624,7 @@ fn expand_rust_function_shim_impl(
                 Some(quote!(::cxx::private::RustVec::from))
             }
         }
-        Type::UniquePtr(ptr) => match ptr.pinned {
-            false => Some(quote!(::cxx::UniquePtr::into_raw)),
-            true => Some(quote!(::cxx::UniquePtr::__pin_into_raw)),
-        },
+        Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
         Type::Ref(ty) => match &ty.inner {
             Type::Ident(ident) if ident.rust == RustString => match ty.mutable {
                 false => Some(quote!(::cxx::private::RustString::from_ref)),
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 3bb3ed3..baba32e 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -91,16 +91,6 @@ where
             ty: PhantomData,
         }
     }
-
-    #[doc(hidden)]
-    pub unsafe fn __pin_into_raw(ptr: Pin<UniquePtr<T>>) -> *mut T {
-        Self::into_raw(Pin::into_inner_unchecked(ptr))
-    }
-
-    #[doc(hidden)]
-    pub unsafe fn __pin_from_raw(raw: *mut T) -> Pin<Self> {
-        Pin::new_unchecked(Self::from_raw(raw))
-    }
 }
 
 unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
diff --git a/syntax/impls.rs b/syntax/impls.rs
index c11c386..a9c48c3 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -81,36 +81,29 @@ impl Eq for Ty1 {}
 impl PartialEq for Ty1 {
     fn eq(&self, other: &Ty1) -> bool {
         let Ty1 {
-            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
-            pin_tokens: _,
         } = self;
         let Ty1 {
-            pinned: pinned2,
             name: name2,
             langle: _,
             inner: inner2,
             rangle: _,
-            pin_tokens: _,
         } = other;
-        pinned == pinned2 && name == name2 && inner == inner2
+        name == name2 && inner == inner2
     }
 }
 
 impl Hash for Ty1 {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Ty1 {
-            pinned,
             name,
             langle: _,
             inner,
             rangle: _,
-            pin_tokens: _,
         } = self;
-        pinned.hash(state);
         name.hash(state);
         inner.hash(state);
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 131639f..2a3790c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -168,12 +168,10 @@ pub enum Type {
 }
 
 pub struct Ty1 {
-    pub pinned: bool,
     pub name: Ident,
     pub langle: Token![<],
     pub inner: Type,
     pub rangle: Token![>],
-    pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
 }
 
 pub struct Ref {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 5e10116..ec89cbb 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -666,48 +666,40 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
-                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
-                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
-                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
-                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
-                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
-                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg, namespace)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
-                            pinned: false,
                             name: ident,
                             langle: generic.lt_token,
                             inner,
                             rangle: generic.gt_token,
-                            pin_tokens: None,
                         })));
                     }
                 } else if ident == "Pin" && generic.args.len() == 1 {
@@ -719,11 +711,6 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                             inner.pin_tokens =
                                 Some((pin_token, generic.lt_token, generic.gt_token));
                             return Ok(Type::Ref(inner));
-                        } else if let Type::UniquePtr(mut inner) = inner {
-                            inner.pinned = true;
-                            inner.pin_tokens =
-                                Some((pin_token, generic.lt_token, generic.gt_token));
-                            return Ok(Type::UniquePtr(inner));
                         }
                     }
                 }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index af8088d..40ab723 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -40,10 +40,6 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
-        if let Some((pin, langle, _rangle)) = self.pin_tokens {
-            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
-            langle.to_tokens(tokens);
-        }
         if let "UniquePtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
@@ -53,9 +49,6 @@ impl ToTokens for Ty1 {
         self.langle.to_tokens(tokens);
         self.inner.to_tokens(tokens);
         self.rangle.to_tokens(tokens);
-        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
-            rangle.to_tokens(tokens);
-        }
     }
 }
 

From 62cae8e16c758053d942592d6da095a503f347c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:01:08 +0000
Subject: [PATCH 1433/2232] Restrict extern Rust types to unique local types for now


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4f703b1..36ba6f2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -32,14 +32,14 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 
     for api in apis {
         if let Api::RustType(ety) = api {
-            expanded.extend(expand_rust_type(ety));
+            expanded.extend(expand_rust_type_import(ety));
             hidden.extend(expand_rust_type_assert_sized(ety));
         }
     }
 
     for api in apis {
         match api {
-            Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
+            Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => expanded.extend(expand_struct(strct)),
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -52,6 +52,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(efn, types));
             }
+            Api::RustType(ety) => expanded.extend(expand_rust_type_impl(ety)),
             Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
@@ -490,13 +491,25 @@ fn expand_function_pointer_trampoline(
     }
 }
 
-fn expand_rust_type(ety: &ExternType) -> TokenStream {
+fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
-    quote! {
+    let span = ident.span();
+
+    quote_spanned! {span=>
         use super::#ident;
     }
 }
 
+fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
+    let ident = &ety.name.rust;
+    let span = ident.span();
+    let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
+
+    quote_spanned! {span=>
+        #unsafe_impl ::cxx::private::RustType for #ident {}
+    }
+}
+
 fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     // Rustc will render as follows if not sized:
     //
diff --git a/src/lib.rs b/src/lib.rs
index c92178a..e4431ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -392,6 +392,7 @@ mod result;
 mod rust_sliceu8;
 mod rust_str;
 mod rust_string;
+mod rust_type;
 mod rust_vec;
 mod symbols;
 mod unique_ptr;
@@ -435,6 +436,7 @@ pub mod private {
     pub use crate::rust_sliceu8::RustSliceU8;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
+    pub use crate::rust_type::RustType;
     pub use crate::rust_vec::RustVec;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
diff --git a/src/rust_type.rs b/src/rust_type.rs
new file mode 100644
index 0000000..2f4f089
--- /dev/null
+++ b/src/rust_type.rs
@@ -0,0 +1 @@
+pub unsafe trait RustType {}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ba9383a..5844bd1 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -230,7 +230,6 @@ pub mod ffi {
 
     extern "Rust" {
         type R;
-        type R2;
 
         fn r_return_primitive() -> usize;
         fn r_return_shared() -> Shared;
@@ -272,9 +271,8 @@ pub mod ffi {
         fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
 
-        fn r_return_r2(n: usize) -> Box<R2>;
-        fn get(self: &R2) -> usize;
-        fn set(self: &mut R2, n: usize) -> usize;
+        fn get(self: &R) -> usize;
+        fn set(self: &mut R, n: usize) -> usize;
         fn r_method_on_shared(self: &Shared) -> String;
 
         #[cxx_name = "rAliasedFunction"]
@@ -303,11 +301,10 @@ pub mod ffi {
     }
 }
 
-pub type R = usize;
+#[derive(PartialEq, Debug)]
+pub struct R(pub usize);
 
-pub struct R2(usize);
-
-impl R2 {
+impl R {
     fn get(&self) -> usize {
         self.0
     }
@@ -344,7 +341,7 @@ fn r_return_shared() -> ffi::Shared {
 }
 
 fn r_return_box() -> Box<R> {
-    Box::new(2020)
+    Box::new(R(2020))
 }
 
 fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
@@ -494,17 +491,13 @@ fn r_try_return_primitive() -> Result<usize, Error> {
 }
 
 fn r_try_return_box() -> Result<Box<R>, Error> {
-    Ok(Box::new(2020))
+    Ok(Box::new(R(2020)))
 }
 
 fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }
 
-fn r_return_r2(n: usize) -> Box<R2> {
-    Box::new(R2(n))
-}
-
 fn r_aliased_function(x: i32) -> String {
     x.to_string()
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 61ef701..f1c293d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -625,12 +625,12 @@ extern "C" const char *cxx_run_test() noexcept {
     ASSERT(std::strcmp(e.what(), "rust error") == 0);
   }
 
-  auto r2 = r_return_r2(2020);
-  ASSERT(r2->get() == 2020);
-  ASSERT(r2->set(2021) == 2021);
-  ASSERT(r2->get() == 2021);
-  ASSERT(r2->set(2020) == 2020);
-  ASSERT(r2->get() == 2020);
+  auto r = r_return_box();
+  ASSERT(r->get() == 2020);
+  ASSERT(r->set(2021) == 2021);
+  ASSERT(r->get() == 2021);
+  ASSERT(r->set(2020) == 2020);
+  ASSERT(r->get() == 2020);
   ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
diff --git a/tests/test.rs b/tests/test.rs
index da858ff..e5e1373 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,7 +1,7 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
 use cxx_test_suite::extra::ffi2;
-use cxx_test_suite::ffi;
+use cxx_test_suite::{ffi, R};
 use std::cell::Cell;
 use std::ffi::CStr;
 
@@ -30,7 +30,7 @@ fn test_c_return() {
 
     assert_eq!(2020, ffi::c_return_primitive());
     assert_eq!(2020, ffi::c_return_shared().z);
-    assert_eq!(2020, *ffi::c_return_box());
+    assert_eq!(2020, ffi::c_return_box().0);
     ffi::c_return_unique_ptr();
     ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
@@ -89,7 +89,7 @@ fn test_c_try_return() {
         "logic error",
         ffi::c_fail_return_primitive().unwrap_err().what(),
     );
-    assert_eq!(2020, *ffi::c_try_return_box().unwrap());
+    assert_eq!(2020, ffi::c_try_return_box().unwrap().0);
     assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
     assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
     assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
@@ -107,7 +107,7 @@ fn test_c_take() {
     check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 }));
     check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 }));
     check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 }));
-    check!(ffi::c_take_box(Box::new(2020)));
+    check!(ffi::c_take_box(Box::new(R(2020))));
     check!(ffi::c_take_ref_c(&unique_ptr));
     check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
@@ -215,13 +215,13 @@ fn test_enum_representations() {
 }
 
 #[no_mangle]
-extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
-    Box::into_raw(Box::new(2020usize))
+extern "C" fn cxx_test_suite_get_box() -> *mut R {
+    Box::into_raw(Box::new(R(2020usize)))
 }
 
 #[no_mangle]
-unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
-    *r == 2020
+unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool {
+    (*r).0 == 2020
 }
 
 #[test]
diff --git a/tests/ui/unsupported_elided.stderr b/tests/ui/unsupported_elided.stderr
index 5136390..932076d 100644
--- a/tests/ui/unsupported_elided.stderr
+++ b/tests/ui/unsupported_elided.stderr
@@ -1,3 +1,9 @@
+error[E0726]: implicit elided lifetime not allowed here
+ --> $DIR/unsupported_elided.rs:6:14
+  |
+6 |         type T;
+  |              ^- help: indicate the anonymous lifetime: `<'_>`
+
 error[E0106]: missing lifetime specifier
  --> $DIR/unsupported_elided.rs:8:24
   |

From 1c55802a8109314075a60f490f22792bb2c33cfa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:02:05 +0000
Subject: [PATCH 1434/2232] Add makefile to build svg diagrams using asciitosvg


---

diff --git a/book/diagram/.gitignore b/book/diagram/.gitignore
new file mode 100644
index 0000000..81631c6
--- /dev/null
+++ b/book/diagram/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/build
diff --git a/book/diagram/Makefile b/book/diagram/Makefile
new file mode 100644
index 0000000..956d7e0
--- /dev/null
+++ b/book/diagram/Makefile
@@ -0,0 +1,19 @@
+all:
+
+bin/asciitosvg:
+	rm -rf build
+	mkdir -p bin build/src/github.com/asciitosvg/asciitosvg
+	cd build/src/github.com/asciitosvg/asciitosvg && \
+		git init && \
+	    git remote add asciitosvg https://github.com/asciitosvg/asciitosvg && \
+		git fetch asciitosvg refs/pull/23/head && \
+		git checkout --quiet 29f2ed76b60231da99ac1d4bca26e8ff93125a2e
+	GOPATH=${CURDIR}/build go build -o $@ ./build/src/github.com/asciitosvg/asciitosvg/cmd/a2s
+
+%.svg: %.ascii bin/asciitosvg
+	bin/asciitosvg -i $< -o $@ -b
+
+clean:
+	rm -f *.svg
+
+.PHONY: all clean

From dc4045f79f1ba4312573cb0d661b8625b40b6474 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:02:05 +0000
Subject: [PATCH 1435/2232] Pull fixes from asciitosvg fork


---

diff --git a/book/diagram/Makefile b/book/diagram/Makefile
index 956d7e0..d432bbe 100644
--- a/book/diagram/Makefile
+++ b/book/diagram/Makefile
@@ -2,12 +2,8 @@ all:
 
 bin/asciitosvg:
 	rm -rf build
-	mkdir -p bin build/src/github.com/asciitosvg/asciitosvg
-	cd build/src/github.com/asciitosvg/asciitosvg && \
-		git init && \
-	    git remote add asciitosvg https://github.com/asciitosvg/asciitosvg && \
-		git fetch asciitosvg refs/pull/23/head && \
-		git checkout --quiet 29f2ed76b60231da99ac1d4bca26e8ff93125a2e
+	mkdir -p bin build/src/github.com/asciitosvg
+	git clone https://github.com/dtolnay/asciitosvg build/src/github.com/asciitosvg/asciitosvg
 	GOPATH=${CURDIR}/build go build -o $@ ./build/src/github.com/asciitosvg/asciitosvg/cmd/a2s
 
 %.svg: %.ascii bin/asciitosvg

From 5f597d791968fafedd6bf9cb2312f2df412734e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:02:05 +0000
Subject: [PATCH 1436/2232] Implement overview diagram in ascii


---

diff --git a/book/diagram/Makefile b/book/diagram/Makefile
index d432bbe..11486ee 100644
--- a/book/diagram/Makefile
+++ b/book/diagram/Makefile
@@ -1,4 +1,4 @@
-all:
+all: overview.svg
 
 bin/asciitosvg:
 	rm -rf build
diff --git a/book/diagram/overview.ascii b/book/diagram/overview.ascii
new file mode 100644
index 0000000..c5491e4
--- /dev/null
+++ b/book/diagram/overview.ascii
@@ -0,0 +1,15 @@
+                         .-------------------------------.
+                         |                               |
+                         |      #[cxx::bridge] mod       |
+                         | definitions and declarations  |
+                         '---------------+---------------'
+                                         |
+                                         |
+                        Macro expansion  | Code generation (cxx_build, etc)
+                         +---------------+---------------+
+                         |                               |
+         Safe            |                               |
+    straightforward      v         C ABI (hidden         v      Straightforward
+       Rust APIs  .-------------.    to users)     .------------.  C++ APIs
+Rust <----------->|Rust bindings|<================>|C++ bindings|<-----------> C++
+code              '-------------'                  '------------'              code
diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg
new file mode 100644
index 0000000..3a44802
--- /dev/null
+++ b/book/diagram/overview.svg
@@ -0,0 +1,65 @@
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Created with ASCIItoSVG -->
+<svg width="756px" height="272px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <defs>
+    <filter id="dsFilter" width="150%" height="150%">
+      <feOffset result="offOut" in="SourceGraphic" dx="2" dy="2"/>
+      <feColorMatrix result="matrixOut" in="offOut" type="matrix" values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0"/>
+      <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="3"/>
+      <feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
+    </filter>
+    <marker id="iPointer"
+      viewBox="0 0 10 10" refX="5" refY="5"
+      markerUnits="strokeWidth"
+      markerWidth="8" markerHeight="15"
+      orient="auto">
+      <path d="M 10 0 L 10 10 L 0 5 z" />
+    </marker>
+    <marker id="Pointer"
+      viewBox="0 0 10 10" refX="5" refY="5"
+      markerUnits="strokeWidth"
+      markerWidth="8" markerHeight="15"
+      orient="auto">
+      <path d="M 0 0 L 10 5 L 0 10 z" />
+    </marker>
+  </defs>
+  <g id="closed" stroke="#000" stroke-width="2" fill="none">
+    <path id="closed0" fill="#fff" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 364.5 72 L 355.5 72 L 346.5 72 L 337.5 72 L 328.5 72 L 319.5 72 L 310.5 72 L 301.5 72 L 292.5 72 L 283.5 72 L 274.5 72 L 265.5 72 L 256.5 72 L 247.5 72 L 238.5 72 L 239.5 72 Q 229.5 72 229.5 62 L 229.5 56 L 229.5 40 L 229.5 24 Z" />
+    <path id="closed3" fill="#fff" d="M 166.5 210 Q 166.5 200 176.5 200 L 175.5 200 L 184.5 200 L 193.5 200 L 202.5 200 L 211.5 200 L 220.5 200 L 229.5 200 L 238.5 200 L 247.5 200 L 256.5 200 L 265.5 200 L 274.5 200 L 283.5 200 L 282.5 200 Q 292.5 200 292.5 210 L 292.5 216 L 292.5 222 Q 292.5 232 282.5 232 L 283.5 232 L 274.5 232 L 265.5 232 L 256.5 232 L 247.5 232 L 238.5 232 L 229.5 232 L 220.5 232 L 211.5 232 L 202.5 232 L 193.5 232 L 184.5 232 L 175.5 232 L 176.5 232 Q 166.5 232 166.5 222 L 166.5 216 Z" />
+    <path id="closed4" fill="#fff" d="M 463.5 210 Q 463.5 200 473.5 200 L 472.5 200 L 481.5 200 L 490.5 200 L 499.5 200 L 508.5 200 L 517.5 200 L 526.5 200 L 535.5 200 L 544.5 200 L 553.5 200 L 562.5 200 L 571.5 200 L 570.5 200 Q 580.5 200 580.5 210 L 580.5 216 L 580.5 222 Q 580.5 232 570.5 232 L 571.5 232 L 562.5 232 L 553.5 232 L 544.5 232 L 535.5 232 L 526.5 232 L 517.5 232 L 508.5 232 L 499.5 232 L 490.5 232 L 481.5 232 L 472.5 232 L 473.5 232 Q 463.5 232 463.5 222 L 463.5 216 Z" />
+  </g>
+  <g id="lines" stroke="#000" stroke-width="2" fill="none">
+    <path id="open1" marker-end="url(#Pointer)" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 373.5 88 L 373.5 104 L 373.5 120 L 373.5 136 L 364.5 136 L 355.5 136 L 346.5 136 L 337.5 136 L 328.5 136 L 319.5 136 L 310.5 136 L 301.5 136 L 292.5 136 L 283.5 136 L 274.5 136 L 265.5 136 L 256.5 136 L 247.5 136 L 238.5 136 L 229.5 136 L 229.5 152 L 229.5 168 L 229.5 184 " />
+    <path id="open2" marker-end="url(#Pointer)" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 373.5 88 L 373.5 104 L 373.5 120 L 373.5 136 L 382.5 136 L 391.5 136 L 400.5 136 L 409.5 136 L 418.5 136 L 427.5 136 L 436.5 136 L 445.5 136 L 454.5 136 L 463.5 136 L 472.5 136 L 481.5 136 L 490.5 136 L 499.5 136 L 508.5 136 L 517.5 136 L 517.5 152 L 517.5 168 L 517.5 184 " />
+    <path id="open5" d="M 616.5 200 L 625.5 200 " />
+    <path id="open6" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 49.5 216 L 58.5 216 L 67.5 216 L 76.5 216 L 85.5 216 L 94.5 216 L 103.5 216 L 112.5 216 L 121.5 216 L 130.5 216 L 139.5 216 L 148.5 216 L 157.5 216 " />
+    <path id="open7" stroke-dasharray="5 5" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 301.5 216 L 310.5 216 L 319.5 216 L 328.5 216 L 337.5 216 L 346.5 216 L 355.5 216 L 364.5 216 L 373.5 216 L 382.5 216 L 391.5 216 L 400.5 216 L 409.5 216 L 418.5 216 L 427.5 216 L 436.5 216 L 445.5 216 L 454.5 216 " />
+    <path id="open8" d="M 481.5 216 L 490.5 216 " />
+    <path id="open9" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 589.5 216 L 598.5 216 L 607.5 216 L 616.5 216 L 625.5 216 L 634.5 216 L 643.5 216 L 652.5 216 L 661.5 216 L 670.5 216 L 679.5 216 L 688.5 216 L 697.5 216 " />
+    <path id="open10" d="M 724.5 216 L 733.5 216 " />
+    <circle cx="724.5" cy="232" r="3" fill="#000" />
+    <path id="open11" d="M 724.5 216 L 724.5 232 " />
+  </g>
+  <g id="text" stroke="none" style="font-family:Consolas,Monaco,Anonymous Pro,Anonymous,Bitstream Sans Mono,monospace;font-size:15.2px" >
+    <text id="obj12" x="301.5" y="40" fill="#000">[cxx::bridge] mod</text>
+    <text id="obj13" x="247.5" y="56" fill="#000">definitions and declarations</text>
+    <text id="obj14" x="220.5" y="120" fill="#000">Macro expansion</text>
+    <text id="obj15" x="391.5" y="120" fill="#000">Code generation (cxx_build, etc)</text>
+    <text id="obj16" x="85.5" y="168" fill="#000">Safe</text>
+    <text id="obj17" x="40.5" y="184" fill="#000">straightforward</text>
+    <text id="obj18" x="319.5" y="184" fill="#000">C ABI (hidden</text>
+    <text id="obj19" x="580.5" y="184" fill="#000">Straightforward</text>
+    <text id="obj20" x="67.5" y="200" fill="#000">Rust APIs</text>
+    <text id="obj21" x="337.5" y="200" fill="#000">to users)</text>
+    <text id="obj22" x="607.5" y="200" fill="#000">C</text>
+    <text id="obj23" x="643.5" y="200" fill="#000">APIs</text>
+    <text id="obj24" x="4.5" y="216" fill="#000">Rust</text>
+    <text id="obj25" x="175.5" y="216" fill="#000">Rust bindings</text>
+    <text id="obj26" x="472.5" y="216" fill="#000">C</text>
+    <text id="obj27" x="508.5" y="216" fill="#000">bindings</text>
+    <text id="obj28" x="715.5" y="216" fill="#000">C</text>
+    <text id="obj29" x="4.5" y="232" fill="#000">code</text>
+    <text id="obj30" x="715.5" y="232" fill="#000">c</text>
+    <text id="obj31" x="733.5" y="232" fill="#000">de</text>
+  </g>
+</svg>

From e04fcfa9ce1f667943591f6fbb519e4538ee5e88 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:02:05 +0000
Subject: [PATCH 1437/2232] Switch overview.svg to svgbob


---

diff --git a/book/diagram/Makefile b/book/diagram/Makefile
index 11486ee..161da34 100644
--- a/book/diagram/Makefile
+++ b/book/diagram/Makefile
@@ -1,13 +1,10 @@
 all: overview.svg
 
-bin/asciitosvg:
-	rm -rf build
-	mkdir -p bin build/src/github.com/asciitosvg
-	git clone https://github.com/dtolnay/asciitosvg build/src/github.com/asciitosvg/asciitosvg
-	GOPATH=${CURDIR}/build go build -o $@ ./build/src/github.com/asciitosvg/asciitosvg/cmd/a2s
-
-%.svg: %.ascii bin/asciitosvg
-	bin/asciitosvg -i $< -o $@ -b
+build/bin/svgbob:
+	cargo install --git https://github.com/ivanceras/svgbob --rev df01674c47350665158ececa476e63f51c58a9c7 --root build
+
+%.svg: %.ascii build/bin/svgbob
+	build/bin/svgbob $< > $@
 
 clean:
 	rm -f *.svg
diff --git a/book/diagram/overview.ascii b/book/diagram/overview.ascii
index c5491e4..06323ca 100644
--- a/book/diagram/overview.ascii
+++ b/book/diagram/overview.ascii
@@ -1,15 +1,13 @@
-                         .-------------------------------.
-                         |                               |
-                         |      #[cxx::bridge] mod       |
-                         | definitions and declarations  |
-                         '---------------+---------------'
-                                         |
-                                         |
-                        Macro expansion  | Code generation (cxx_build, etc)
-                         +---------------+---------------+
-                         |                               |
-         Safe            |                               |
-    straightforward      v         C ABI (hidden         v      Straightforward
-       Rust APIs  .-------------.    to users)     .------------.  C++ APIs
-Rust <----------->|Rust bindings|<================>|C++ bindings|<-----------> C++
-code              '-------------'                  '------------'              code
+                            .-----------------------------.
+                           |     #[cxx::bridge]  mod       |
+                           | definitions and declarations  |
+                            '--------------+--------------'
+                                           |
+                                           |
+                         "Macro expansion" |  "Code generation"
+                           +---------------+---------------+
+         Safe              |                               |
+    straightforward        v                               v      Straightforward
+       "Rust APIs".----------------. "Hidden C ABI".---------------.  "C++ APIs"
+Rust <----------->| "Rust bindings"|<~~~~~~~~~~~~~>| "C++ bindings"|<-----------> "C++"
+code              '----------------'               '---------------'              code
diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg
index 3a44802..69baaf2 100644
--- a/book/diagram/overview.svg
+++ b/book/diagram/overview.svg
@@ -1,65 +1,132 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Created with ASCIItoSVG -->
-<svg width="756px" height="272px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-  <defs>
-    <filter id="dsFilter" width="150%" height="150%">
-      <feOffset result="offOut" in="SourceGraphic" dx="2" dy="2"/>
-      <feColorMatrix result="matrixOut" in="offOut" type="matrix" values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0"/>
-      <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="3"/>
-      <feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
-    </filter>
-    <marker id="iPointer"
-      viewBox="0 0 10 10" refX="5" refY="5"
-      markerUnits="strokeWidth"
-      markerWidth="8" markerHeight="15"
-      orient="auto">
-      <path d="M 10 0 L 10 10 L 0 5 z" />
-    </marker>
-    <marker id="Pointer"
-      viewBox="0 0 10 10" refX="5" refY="5"
-      markerUnits="strokeWidth"
-      markerWidth="8" markerHeight="15"
-      orient="auto">
-      <path d="M 0 0 L 10 5 L 0 10 z" />
-    </marker>
-  </defs>
-  <g id="closed" stroke="#000" stroke-width="2" fill="none">
-    <path id="closed0" fill="#fff" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 364.5 72 L 355.5 72 L 346.5 72 L 337.5 72 L 328.5 72 L 319.5 72 L 310.5 72 L 301.5 72 L 292.5 72 L 283.5 72 L 274.5 72 L 265.5 72 L 256.5 72 L 247.5 72 L 238.5 72 L 239.5 72 Q 229.5 72 229.5 62 L 229.5 56 L 229.5 40 L 229.5 24 Z" />
-    <path id="closed3" fill="#fff" d="M 166.5 210 Q 166.5 200 176.5 200 L 175.5 200 L 184.5 200 L 193.5 200 L 202.5 200 L 211.5 200 L 220.5 200 L 229.5 200 L 238.5 200 L 247.5 200 L 256.5 200 L 265.5 200 L 274.5 200 L 283.5 200 L 282.5 200 Q 292.5 200 292.5 210 L 292.5 216 L 292.5 222 Q 292.5 232 282.5 232 L 283.5 232 L 274.5 232 L 265.5 232 L 256.5 232 L 247.5 232 L 238.5 232 L 229.5 232 L 220.5 232 L 211.5 232 L 202.5 232 L 193.5 232 L 184.5 232 L 175.5 232 L 176.5 232 Q 166.5 232 166.5 222 L 166.5 216 Z" />
-    <path id="closed4" fill="#fff" d="M 463.5 210 Q 463.5 200 473.5 200 L 472.5 200 L 481.5 200 L 490.5 200 L 499.5 200 L 508.5 200 L 517.5 200 L 526.5 200 L 535.5 200 L 544.5 200 L 553.5 200 L 562.5 200 L 571.5 200 L 570.5 200 Q 580.5 200 580.5 210 L 580.5 216 L 580.5 222 Q 580.5 232 570.5 232 L 571.5 232 L 562.5 232 L 553.5 232 L 544.5 232 L 535.5 232 L 526.5 232 L 517.5 232 L 508.5 232 L 499.5 232 L 490.5 232 L 481.5 232 L 472.5 232 L 473.5 232 Q 463.5 232 463.5 222 L 463.5 216 Z" />
-  </g>
-  <g id="lines" stroke="#000" stroke-width="2" fill="none">
-    <path id="open1" marker-end="url(#Pointer)" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 373.5 88 L 373.5 104 L 373.5 120 L 373.5 136 L 364.5 136 L 355.5 136 L 346.5 136 L 337.5 136 L 328.5 136 L 319.5 136 L 310.5 136 L 301.5 136 L 292.5 136 L 283.5 136 L 274.5 136 L 265.5 136 L 256.5 136 L 247.5 136 L 238.5 136 L 229.5 136 L 229.5 152 L 229.5 168 L 229.5 184 " />
-    <path id="open2" marker-end="url(#Pointer)" d="M 229.5 18 Q 229.5 8 239.5 8 L 238.5 8 L 247.5 8 L 256.5 8 L 265.5 8 L 274.5 8 L 283.5 8 L 292.5 8 L 301.5 8 L 310.5 8 L 319.5 8 L 328.5 8 L 337.5 8 L 346.5 8 L 355.5 8 L 364.5 8 L 373.5 8 L 382.5 8 L 391.5 8 L 400.5 8 L 409.5 8 L 418.5 8 L 427.5 8 L 436.5 8 L 445.5 8 L 454.5 8 L 463.5 8 L 472.5 8 L 481.5 8 L 490.5 8 L 499.5 8 L 508.5 8 L 507.5 8 Q 517.5 8 517.5 18 L 517.5 24 L 517.5 40 L 517.5 56 L 517.5 62 Q 517.5 72 507.5 72 L 508.5 72 L 499.5 72 L 490.5 72 L 481.5 72 L 472.5 72 L 463.5 72 L 454.5 72 L 445.5 72 L 436.5 72 L 427.5 72 L 418.5 72 L 409.5 72 L 400.5 72 L 391.5 72 L 382.5 72 L 373.5 72 L 373.5 88 L 373.5 104 L 373.5 120 L 373.5 136 L 382.5 136 L 391.5 136 L 400.5 136 L 409.5 136 L 418.5 136 L 427.5 136 L 436.5 136 L 445.5 136 L 454.5 136 L 463.5 136 L 472.5 136 L 481.5 136 L 490.5 136 L 499.5 136 L 508.5 136 L 517.5 136 L 517.5 152 L 517.5 168 L 517.5 184 " />
-    <path id="open5" d="M 616.5 200 L 625.5 200 " />
-    <path id="open6" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 49.5 216 L 58.5 216 L 67.5 216 L 76.5 216 L 85.5 216 L 94.5 216 L 103.5 216 L 112.5 216 L 121.5 216 L 130.5 216 L 139.5 216 L 148.5 216 L 157.5 216 " />
-    <path id="open7" stroke-dasharray="5 5" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 301.5 216 L 310.5 216 L 319.5 216 L 328.5 216 L 337.5 216 L 346.5 216 L 355.5 216 L 364.5 216 L 373.5 216 L 382.5 216 L 391.5 216 L 400.5 216 L 409.5 216 L 418.5 216 L 427.5 216 L 436.5 216 L 445.5 216 L 454.5 216 " />
-    <path id="open8" d="M 481.5 216 L 490.5 216 " />
-    <path id="open9" marker-start="url(#iPointer)" marker-end="url(#Pointer)" d="M 589.5 216 L 598.5 216 L 607.5 216 L 616.5 216 L 625.5 216 L 634.5 216 L 643.5 216 L 652.5 216 L 661.5 216 L 670.5 216 L 679.5 216 L 688.5 216 L 697.5 216 " />
-    <path id="open10" d="M 724.5 216 L 733.5 216 " />
-    <circle cx="724.5" cy="232" r="3" fill="#000" />
-    <path id="open11" d="M 724.5 216 L 724.5 232 " />
-  </g>
-  <g id="text" stroke="none" style="font-family:Consolas,Monaco,Anonymous Pro,Anonymous,Bitstream Sans Mono,monospace;font-size:15.2px" >
-    <text id="obj12" x="301.5" y="40" fill="#000">[cxx::bridge] mod</text>
-    <text id="obj13" x="247.5" y="56" fill="#000">definitions and declarations</text>
-    <text id="obj14" x="220.5" y="120" fill="#000">Macro expansion</text>
-    <text id="obj15" x="391.5" y="120" fill="#000">Code generation (cxx_build, etc)</text>
-    <text id="obj16" x="85.5" y="168" fill="#000">Safe</text>
-    <text id="obj17" x="40.5" y="184" fill="#000">straightforward</text>
-    <text id="obj18" x="319.5" y="184" fill="#000">C ABI (hidden</text>
-    <text id="obj19" x="580.5" y="184" fill="#000">Straightforward</text>
-    <text id="obj20" x="67.5" y="200" fill="#000">Rust APIs</text>
-    <text id="obj21" x="337.5" y="200" fill="#000">to users)</text>
-    <text id="obj22" x="607.5" y="200" fill="#000">C</text>
-    <text id="obj23" x="643.5" y="200" fill="#000">APIs</text>
-    <text id="obj24" x="4.5" y="216" fill="#000">Rust</text>
-    <text id="obj25" x="175.5" y="216" fill="#000">Rust bindings</text>
-    <text id="obj26" x="472.5" y="216" fill="#000">C</text>
-    <text id="obj27" x="508.5" y="216" fill="#000">bindings</text>
-    <text id="obj28" x="715.5" y="216" fill="#000">C</text>
-    <text id="obj29" x="4.5" y="232" fill="#000">code</text>
-    <text id="obj30" x="715.5" y="232" fill="#000">c</text>
-    <text id="obj31" x="733.5" y="232" fill="#000">de</text>
-  </g>
+<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224">
+    <style>line, path, circle,rect,polygon {
+                          stroke: black;
+                          stroke-width: 2;
+                          stroke-opacity: 1;
+                          fill-opacity: 1;
+                          stroke-linecap: round;
+                          stroke-linejoin: miter;
+                        }
+
+                    text {
+                        fill: black;
+                        }
+                        rect.backdrop{
+                            stroke: none;
+                            fill: white;
+                        }
+                        .broken{
+                            stroke-dasharray: 8;
+                        }
+                        .filled{
+                            fill: black;
+                        }
+                        .bg_filled{
+                            fill: white;
+                        }
+                        .nofill{
+                            fill: white;
+                        }
+
+                        text {
+                         font-family: monospace;
+                         font-size: 14px;
+                        }
+
+                        .end_marked_arrow{
+                            marker-end: url(#arrow);
+                         }
+                        .start_marked_arrow{
+                            marker-start: url(#arrow);
+                         }
+
+                        .end_marked_diamond{
+                            marker-end: url(#diamond);
+                         }
+                        .start_marked_diamond{
+                            marker-start: url(#diamond);
+                         }
+
+                        .end_marked_circle{
+                            marker-end: url(#circle);
+                         }
+                        .start_marked_circle{
+                            marker-start: url(#circle);
+                         }
+
+                        .end_marked_open_circle{
+                            marker-end: url(#open_circle);
+                         }
+                        .start_marked_open_circle{
+                            marker-start: url(#open_circle);
+                         }
+
+                        .end_marked_big_open_circle{
+                            marker-end: url(#big_open_circle);
+                         }
+                        .start_marked_big_open_circle{
+                            marker-start: url(#big_open_circle);
+                         }
+
+                         
+                        </style>
+    <defs>
+        <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,0 0,4 4,2 0,0"></polygon>
+        </marker>
+        <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon>
+        </marker>
+        <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="filled"></circle>
+        </marker>
+        <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="bg_filled"></circle>
+        </marker>
+        <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="3" class="bg_filled"></circle>
+        </marker>
+    </defs>
+    <rect class="backdrop" x="0" y="0" width="696" height="224"></rect>
+    <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect>
+    <text x="162" y="188" >Rust bindings</text>
+    <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect>
+    <text x="426" y="188" >C++ bindings</text>
+    <text x="266" y="28" >#[cxx::bridge]</text>
+    <text x="394" y="28" >mod</text>
+    <text x="234" y="44" >definitions</text>
+    <text x="330" y="44" >and</text>
+    <text x="362" y="44" >declarations</text>
+    <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
+    <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
+    <text x="74" y="140" >Safe</text>
+    <text x="34" y="156" >straightforward</text>
+    <text x="530" y="156" >Straightforward</text>
+    <polygon points="48,180 40,184 48,188" class="filled"></polygon>
+    <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line>
+    <polygon points="296,180 288,184 296,188" class="filled"></polygon>
+    <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line>
+    <polygon points="552,180 544,184 552,188" class="filled"></polygon>
+    <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line>
+    <text x="2" y="188" >Rust</text>
+    <text x="2" y="204" >code</text>
+    <text x="658" y="204" >code</text>
+    <text x="202" y="108" >Macro expansion</text>
+    <text x="370" y="108" >Code generation</text>
+    <text x="58" y="172" >Rust APIs</text>
+    <text x="298" y="172" >Hidden C ABI</text>
+    <text x="562" y="172" >C++ APIs</text>
+    <text x="658" y="188" >C++</text>
+    <g>
+        <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path>
+        <line x1="228" y1="8" x2="468" y2="8" class="solid"></line>
+        <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path>
+        <line x1="220" y1="16" x2="220" y2="48" class="solid"></line>
+        <line x1="476" y1="16" x2="476" y2="48" class="solid"></line>
+        <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path>
+        <line x1="228" y1="56" x2="468" y2="56" class="solid"></line>
+        <line x1="348" y1="56" x2="348" y2="120" class="solid"></line>
+        <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path>
+        <line x1="220" y1="120" x2="476" y2="120" class="solid"></line>
+    </g>
 </svg>

From 348d3752555fe3372650e413024f2adddef66cdd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:22:36 +0000
Subject: [PATCH 1438/2232] Merge pull request #481 from dtolnay/svg


Add overview svg
---

diff --git a/book/diagram/.gitignore b/book/diagram/.gitignore
new file mode 100644
index 0000000..81631c6
--- /dev/null
+++ b/book/diagram/.gitignore
@@ -0,0 +1,2 @@
+/bin
+/build
diff --git a/book/diagram/Makefile b/book/diagram/Makefile
new file mode 100644
index 0000000..161da34
--- /dev/null
+++ b/book/diagram/Makefile
@@ -0,0 +1,12 @@
+all: overview.svg
+
+build/bin/svgbob:
+	cargo install --git https://github.com/ivanceras/svgbob --rev df01674c47350665158ececa476e63f51c58a9c7 --root build
+
+%.svg: %.ascii build/bin/svgbob
+	build/bin/svgbob $< > $@
+
+clean:
+	rm -f *.svg
+
+.PHONY: all clean
diff --git a/book/diagram/overview.ascii b/book/diagram/overview.ascii
new file mode 100644
index 0000000..06323ca
--- /dev/null
+++ b/book/diagram/overview.ascii
@@ -0,0 +1,13 @@
+                            .-----------------------------.
+                           |     #[cxx::bridge]  mod       |
+                           | definitions and declarations  |
+                            '--------------+--------------'
+                                           |
+                                           |
+                         "Macro expansion" |  "Code generation"
+                           +---------------+---------------+
+         Safe              |                               |
+    straightforward        v                               v      Straightforward
+       "Rust APIs".----------------. "Hidden C ABI".---------------.  "C++ APIs"
+Rust <----------->| "Rust bindings"|<~~~~~~~~~~~~~>| "C++ bindings"|<-----------> "C++"
+code              '----------------'               '---------------'              code
diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg
new file mode 100644
index 0000000..69baaf2
--- /dev/null
+++ b/book/diagram/overview.svg
@@ -0,0 +1,132 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224">
+    <style>line, path, circle,rect,polygon {
+                          stroke: black;
+                          stroke-width: 2;
+                          stroke-opacity: 1;
+                          fill-opacity: 1;
+                          stroke-linecap: round;
+                          stroke-linejoin: miter;
+                        }
+
+                    text {
+                        fill: black;
+                        }
+                        rect.backdrop{
+                            stroke: none;
+                            fill: white;
+                        }
+                        .broken{
+                            stroke-dasharray: 8;
+                        }
+                        .filled{
+                            fill: black;
+                        }
+                        .bg_filled{
+                            fill: white;
+                        }
+                        .nofill{
+                            fill: white;
+                        }
+
+                        text {
+                         font-family: monospace;
+                         font-size: 14px;
+                        }
+
+                        .end_marked_arrow{
+                            marker-end: url(#arrow);
+                         }
+                        .start_marked_arrow{
+                            marker-start: url(#arrow);
+                         }
+
+                        .end_marked_diamond{
+                            marker-end: url(#diamond);
+                         }
+                        .start_marked_diamond{
+                            marker-start: url(#diamond);
+                         }
+
+                        .end_marked_circle{
+                            marker-end: url(#circle);
+                         }
+                        .start_marked_circle{
+                            marker-start: url(#circle);
+                         }
+
+                        .end_marked_open_circle{
+                            marker-end: url(#open_circle);
+                         }
+                        .start_marked_open_circle{
+                            marker-start: url(#open_circle);
+                         }
+
+                        .end_marked_big_open_circle{
+                            marker-end: url(#big_open_circle);
+                         }
+                        .start_marked_big_open_circle{
+                            marker-start: url(#big_open_circle);
+                         }
+
+                         
+                        </style>
+    <defs>
+        <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,0 0,4 4,2 0,0"></polygon>
+        </marker>
+        <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon>
+        </marker>
+        <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="filled"></circle>
+        </marker>
+        <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="bg_filled"></circle>
+        </marker>
+        <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="3" class="bg_filled"></circle>
+        </marker>
+    </defs>
+    <rect class="backdrop" x="0" y="0" width="696" height="224"></rect>
+    <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect>
+    <text x="162" y="188" >Rust bindings</text>
+    <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect>
+    <text x="426" y="188" >C++ bindings</text>
+    <text x="266" y="28" >#[cxx::bridge]</text>
+    <text x="394" y="28" >mod</text>
+    <text x="234" y="44" >definitions</text>
+    <text x="330" y="44" >and</text>
+    <text x="362" y="44" >declarations</text>
+    <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
+    <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
+    <text x="74" y="140" >Safe</text>
+    <text x="34" y="156" >straightforward</text>
+    <text x="530" y="156" >Straightforward</text>
+    <polygon points="48,180 40,184 48,188" class="filled"></polygon>
+    <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line>
+    <polygon points="296,180 288,184 296,188" class="filled"></polygon>
+    <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line>
+    <polygon points="552,180 544,184 552,188" class="filled"></polygon>
+    <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line>
+    <text x="2" y="188" >Rust</text>
+    <text x="2" y="204" >code</text>
+    <text x="658" y="204" >code</text>
+    <text x="202" y="108" >Macro expansion</text>
+    <text x="370" y="108" >Code generation</text>
+    <text x="58" y="172" >Rust APIs</text>
+    <text x="298" y="172" >Hidden C ABI</text>
+    <text x="562" y="172" >C++ APIs</text>
+    <text x="658" y="188" >C++</text>
+    <g>
+        <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path>
+        <line x1="228" y1="8" x2="468" y2="8" class="solid"></line>
+        <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path>
+        <line x1="220" y1="16" x2="220" y2="48" class="solid"></line>
+        <line x1="476" y1="16" x2="476" y2="48" class="solid"></line>
+        <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path>
+        <line x1="228" y1="56" x2="468" y2="56" class="solid"></line>
+        <line x1="348" y1="56" x2="348" y2="120" class="solid"></line>
+        <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path>
+        <line x1="220" y1="120" x2="476" y2="120" class="solid"></line>
+    </g>
+</svg>

From 8f8ee538af8fc57400cae996609b91c8f3d141db Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:22:44 +0000
Subject: [PATCH 1439/2232] Book style tweaks


---

diff --git a/book/book.toml b/book/book.toml
index fe8b5fc..d8928fb 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -8,8 +8,11 @@ edition = "2018"
 
 [build]
 build-dir = "build"
+create-missing = false
 
 [output.html]
 additional-css = ["css/cxx.css"]
 cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"
+playground = { copyable = false }
+print = { enable = false }
diff --git a/book/build.js b/book/build.js
index e7ec435..091d4ce 100755
--- a/book/build.js
+++ b/book/build.js
@@ -14,6 +14,11 @@ https://github.com/dtolnay/cxx\
 </a>\
 </li>`;
 
+const htmljs = `\
+var html = document.querySelector('html');
+html.classList.remove('no-js');
+html.classList.add('js');`;
+
 const dirs = ['build'];
 while (dirs.length) {
   const dir = dirs.pop();
@@ -32,7 +37,11 @@ while (dirs.length) {
     const index = fs.readFileSync(path, 'utf8');
     const $ = cheerio.load(index, { decodeEntities: false });
 
+    $('script:nth-of-type(3)').text(htmljs);
     $('nav#sidebar ol.chapter').append(githublink);
+    $('head link[href="tomorrow-night.css"]').attr('disabled', true);
+    $('head link[href="ayu-highlight.css"]').attr('disabled', true);
+    $('button#theme-toggle').attr('style', 'display:none');
     $('pre code').each(function () {
       const node = $(this);
       const langClass = node.attr('class').split(' ', 2)[0];
@@ -44,6 +53,7 @@ while (dirs.length) {
       const boring = lines.map((line) =>
         line.includes('<span class="boring">')
       );
+      const ellipsis = lines.map((line) => line.includes('// ...'));
       const target = entities.decode(node.text());
       const highlighted = hljs.highlight(lang, target).value;
       const result = highlighted
@@ -51,14 +61,21 @@ while (dirs.length) {
         .map(function (line, i) {
           if (boring[i]) {
             line = '<span class="boring">' + line;
+          } else if (ellipsis[i]) {
+            line = '<span class="ellipsis">' + line;
           }
-          if (i > 0 && boring[i - 1]) {
+          if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) {
             line = '</span>' + line;
           }
           return line;
         })
         .join('\n');
-      node.text(result).removeClass(langClass).addClass('hidelines');
+      node.text(result);
+      node.removeClass(langClass);
+      if (!node.hasClass('focuscomment')) {
+        node.addClass('hidelines');
+        node.addClass('hide-boring');
+      }
     });
     $('code').each(function () {
       $(this).addClass('hljs');
@@ -68,3 +85,10 @@ while (dirs.length) {
     fs.writeFileSync(path, out);
   });
 }
+
+fs.copyFileSync('build/highlight.css', 'build/tomorrow-night.css');
+fs.copyFileSync('build/highlight.css', 'build/ayu-highlight.css');
+
+var bookjs = fs.readFileSync('build/book.js', 'utf8');
+bookjs = bookjs.replace('set_theme(theme, false);', '');
+fs.writeFileSync('build/book.js', bookjs);
diff --git a/book/css/cxx.css b/book/css/cxx.css
index 2a167bc..647f4f7 100644
--- a/book/css/cxx.css
+++ b/book/css/cxx.css
@@ -1,7 +1,36 @@
-.no-js .boring {
+:root {
+    --sidebar-width: 310px;
+}
+
+.badges img {
+    margin: 0 7px 7px 0;
+}
+
+.badges {
+    margin: 16px 0 120px;
+}
+
+.boring {
+    opacity: 0.5;
+}
+
+.no-js code:not(.focuscomment) .boring {
     display: none;
 }
 
+.js code:not(.hide-boring) .ellipsis {
+    display: none;
+}
+
+.focuscomment .hljs-comment {
+    font-weight: bold;
+    color: black;
+}
+
+.focuscomment .boring {
+    opacity: 0.5;
+}
+
 nav.sidebar li.part-title i.fa-github {
     font-size: 20px;
     padding-right: 5px;
@@ -9,3 +38,7 @@ nav.sidebar li.part-title i.fa-github {
     position: relative;
     top: 1px;
 }
+
+.sidebar .sidebar-scrollbox {
+    padding: 10px 0 10px 10px;
+}
diff --git a/book/diagram/overview.ascii b/book/diagram/overview.ascii
index 06323ca..dd1c4b9 100644
--- a/book/diagram/overview.ascii
+++ b/book/diagram/overview.ascii
@@ -1,6 +1,6 @@
                             .-----------------------------.
                            |     #[cxx::bridge]  mod       |
-                           | definitions and declarations  |
+                           |   description of boundary     |
                             '--------------+--------------'
                                            |
                                            |
diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg
index 69baaf2..c551687 100644
--- a/book/diagram/overview.svg
+++ b/book/diagram/overview.svg
@@ -94,9 +94,9 @@
     <text x="426" y="188" >C++ bindings</text>
     <text x="266" y="28" >#[cxx::bridge]</text>
     <text x="394" y="28" >mod</text>
-    <text x="234" y="44" >definitions</text>
-    <text x="330" y="44" >and</text>
-    <text x="362" y="44" >declarations</text>
+    <text x="250" y="44" >description</text>
+    <text x="346" y="44" >of</text>
+    <text x="370" y="44" >boundary</text>
     <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
     <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
     <text x="74" y="140" >Safe</text>

From ac8662cdc7d5784590748cfad00436f2b390deb5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:22:44 +0000
Subject: [PATCH 1440/2232] Add book opengraph metadata


---

diff --git a/book/book.toml b/book/book.toml
index d8928fb..0644e05 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -1,7 +1,7 @@
 [book]
-title = "CXX"
+#title = "Rust ♡ C++"
 authors = ["David Tolnay"]
-description = "Guide for the `cxx` crate, a safe approach to FFI between Rust and C++."
+description = "CXX — safe interop between Rust and C++"
 
 [rust]
 edition = "2018"
diff --git a/book/build.js b/book/build.js
index 091d4ce..2cda586 100755
--- a/book/build.js
+++ b/book/build.js
@@ -14,6 +14,15 @@ https://github.com/dtolnay/cxx\
 </a>\
 </li>`;
 
+const opengraph = `\
+<meta property="og:image" content="https://cxx.rs/cxx.png" />\
+<meta property="og:site_name" content="CXX" />\
+<meta property="og:title" content="CXX — safe interop between Rust and C++" />\
+<meta name="twitter:image:src" content="https://cxx.rs/cxx.png" />\
+<meta name="twitter:site" content="@davidtolnay" />\
+<meta name="twitter:card" content="summary" />\
+<meta name="twitter:title" content="CXX — safe interop between Rust and C++" />`;
+
 const htmljs = `\
 var html = document.querySelector('html');
 html.classList.remove('no-js');
@@ -37,6 +46,7 @@ while (dirs.length) {
     const index = fs.readFileSync(path, 'utf8');
     const $ = cheerio.load(index, { decodeEntities: false });
 
+    $('head').append(opengraph);
     $('script:nth-of-type(3)').text(htmljs);
     $('nav#sidebar ol.chapter').append(githublink);
     $('head link[href="tomorrow-night.css"]').attr('disabled', true);
diff --git a/book/src/cxx.png b/book/src/cxx.png
new file mode 100644
index 0000000..aeb7ca9
Binary files /dev/null and b/book/src/cxx.png differ

From 7a39745472699575a71eeb15e575a26add2bc293 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:22:44 +0000
Subject: [PATCH 1441/2232] Book content


---

diff --git a/book/book.toml b/book/book.toml
index 0644e05..066f3a6 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -16,3 +16,7 @@ cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"
 playground = { copyable = false }
 print = { enable = false }
+
+[output.html.redirect]
+"binding/index.html" = "../bindings.html"
+"build/index.html" = "../building.html"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index f3fa924..31cbb46 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -1,3 +1,35 @@
 # Summary
 
-[Rust ❤️ C++](about.md)
+- [Rust ❤️ C++](index.md)
+
+- [Core concepts](concepts.md)
+
+- [Tutorial](tutorial.md)
+
+- [Other Rust&ndash;C++ interop tools](context.md)
+
+- [Multi-language build system options](building.md)
+    - [Cargo](build/cargo.md)
+    - [Bazel](build/bazel.md)
+    - [CMake](build/cmake.md)
+    - [More...](build/other.md)
+
+- [Reference: the bridge module](reference.md)
+    - [extern "Rust"](extern-rust.md)
+    - [extern "C++"](extern-c++.md)
+    - [Shared types](shared.md)
+    - [Attributes](attributes.md)
+    - [Async functions](async.md)
+    - [Error handling](binding/result.md)
+
+- [Reference: built-in bindings](bindings.md)
+    - [String &mdash; rust::String](binding/string.md)
+    - [&str &mdash; rust::Str](binding/str.md)
+    - [&&#91;T&#93; &mdash; rust::Slice\<const T\>](binding/slice.md)
+    - [CxxString &mdash; std::string](binding/cxxstring.md)
+    - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
+    - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
+    - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
+    - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
+    - [Function pointers](binding/fn.md)
+    - [Result\<T\>](binding/result.md)
diff --git a/book/src/about.md b/book/src/about.md
deleted file mode 100644
index 6e63bf5..0000000
--- a/book/src/about.md
+++ /dev/null
@@ -1 +0,0 @@
-### Coming soon
diff --git a/book/src/async.md b/book/src/async.md
new file mode 100644
index 0000000..7574a22
--- /dev/null
+++ b/book/src/async.md
@@ -0,0 +1,86 @@
+{{#title Async functions — Rust ♡ C++}}
+# Async functions
+
+Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up)
+but is not implemented yet in the current release. We are aiming for an
+implementation that is as easy as:
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        async fn doThing(arg: Arg) -> Ret;
+    }
+}
+```
+
+```cpp,hidelines
+rust::Future<Ret> doThing(Arg arg) {
+  auto v1 = co_await f();
+  auto v2 = co_await g(arg);
+  co_return v1 + v2;
+}
+```
+
+## Workaround
+
+For now the recommended approach is to handle the return codepath over a oneshot
+channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust
+type on the FFI.
+
+[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html
+
+```rust,noplayground
+// bridge.rs
+
+use futures::channel::oneshot;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type DoThingContext;
+    }
+
+    unsafe extern "C++" {
+        include!("path/to/bridge_shim.h");
+
+        fn shim_doThing(
+            arg: Arg,
+            done: fn(Box<DoThingContext>, ret: Ret),
+            ctx: Box<DoThingContext>,
+        );
+    }
+}
+
+struct DoThingContext(oneshot::Sender<Ret>);
+
+pub async fn do_thing(arg: Arg) -> Ret {
+    let (tx, rx) = oneshot::channel();
+    let context = Box::new(DoThingContext(tx));
+
+    ffi::shim_doThing(
+        arg,
+        |tx, ret| { let _ = tx.0.send(ret); },
+        context,
+    );
+
+    rx.await.unwrap()
+}
+```
+
+```cpp
+// bridge_shim.cc
+
+#include "path/to/bridge.rs.h"
+#include "rust/cxx.h"
+
+void shim_doThing(
+    Arg arg,
+    rust::Fn<void(rust::Box<DoThingContext> ctx, Ret ret)> done,
+    rust::Box<DoThingContext> ctx) noexcept {
+  doThing(arg)
+      .then([done, ctx(std::move(ctx))](auto &&res) mutable {
+        (*done)(std::move(ctx), std::move(res));
+      });
+}
+```
diff --git a/book/src/attributes.md b/book/src/attributes.md
new file mode 100644
index 0000000..b41515a
--- /dev/null
+++ b/book/src/attributes.md
@@ -0,0 +1,74 @@
+{{#title Attributes — Rust ♡ C++}}
+# Attributes
+
+## namespace
+
+The top-level cxx::bridge attribute macro takes an optional `namespace` argument
+to control the C++ namespace into which to emit extern Rust items and the
+namespace in which to expect to find the extern C++ items.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "path::of::my::company")]
+mod ffi {
+    extern "Rust" {
+        type MyType;  // emitted to path::of::my::company::MyType
+    }
+
+    extern "C++" {
+        type TheirType;  // refers to path::of::my::company::TheirType
+    }
+}
+```
+
+Additionally, a `#[namespace = "..."]` attribute may be used inside the bridge
+module on any extern block or individual item. An item will inherit the
+namespace specified on its surrounding extern block if any, otherwise the
+namespace specified with the top level cxx::bridge attribute if any, otherwise
+the global namespace.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "third_priority")]
+mod ffi {
+    #[namespace = "second_priority"]
+    extern "Rust" {
+        fn f();
+
+        #[namespace = "first_priority"]
+        fn g();
+    }
+
+    extern "Rust" {
+        fn h();
+    }
+}
+```
+
+The above would result in functions `::second_priority::f`,
+`::first_priority::g`, `::third_priority::h`.
+
+## rust\_name, cxx\_name
+
+Sometimes you want the Rust name of a function to differ from its C++ name.
+Importantly, this enables binding multiple overloads of the same C++ function
+name using distinct Rust names.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        #[rust_name = "i32_overloaded_function"]
+        fn cOverloadedFunction(x: i32) -> String;
+        #[rust_name = "str_overloaded_function"]
+        fn cOverloadedFunction(x: &str) -> String;
+    }
+}
+```
+
+The `#[rust_name = "..."]` attribute replaces the name that Rust should use for
+this function, and an analogous `#[cxx_name = "..."]` attribute replaces the
+name that C++ should use.
+
+Either of the two attributes may be used on extern "Rust" as well as extern
+"C++" functions, according to which one you find clearer in context.
+
+Support for renaming type names and enum variants is not implemented yet.
diff --git a/book/src/binding/box.md b/book/src/binding/box.md
new file mode 100644
index 0000000..8bcae58
--- /dev/null
+++ b/book/src/binding/box.md
@@ -0,0 +1,120 @@
+{{#title rust::Box<T> — Rust ♡ C++}}
+# rust::Box\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <type_traits>
+#
+# namespace rust {
+
+template <typename T>
+class Box final {
+public:
+  using value_type = T;
+  using const_pointer =
+      typename std::add_pointer<typename std::add_const<T>::type>::type;
+  using pointer = typename std::add_pointer<T>::type;
+
+  Box(const Box &);
+  Box(Box &&) noexcept;
+  ~Box() noexcept;
+
+  explicit Box(const T &);
+  explicit Box(T &&);
+
+  Box &operator=(const Box &);
+  Box &operator=(Box &&) noexcept;
+
+  const T *operator->() const noexcept;
+  const T &operator*() const noexcept;
+  T *operator->() noexcept;
+  T &operator*() noexcept;
+
+  template <typename... Fields>
+  static Box in_place(Fields &&...);
+
+  // Important: requires that `raw` came from an into_raw call. Do not
+  // pass a pointer from `new` or any other source.
+  static Box from_raw(T *) noexcept;
+
+  T *into_raw() noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Box\<T\> does not support T being an opaque C++ type. You should use
+[UniquePtr\<T\>](uniqueptr.md) instead for transferring ownership of opaque C++
+types on the language boundary.
+
+If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
+known at compile time. In the future we may introduce support for dynamically
+sized opaque Rust types.
+
+[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html
+
+## Example
+
+This program uses a Box to pass ownership of some opaque piece of Rust state
+over to C++ and then back to a Rust callback, which is a useful pattern for
+implementing [async functions over FFI](../async.md).
+
+```rust,noplayground
+// src/main.rs
+
+use std::io::Write;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type File;
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        fn f(
+            callback: fn(Box<File>, fst: &str, snd: &str),
+            out: Box<File>,
+        );
+    }
+}
+
+pub struct File(std::fs::File);
+
+fn main() {
+    let out = std::fs::File::create("example.log").unwrap();
+
+    ffi::f(
+        |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); },
+        Box::new(File(out)),
+    );
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
+       rust::Box<File> out);
+```
+
+```cpp
+// include/example.cc
+
+#include "example/include/example.h"
+
+void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
+       rust::Box<File> out) {
+  callback(std::move(out), "fearless", "concurrency");
+}
+```
diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md
new file mode 100644
index 0000000..0a643c2
--- /dev/null
+++ b/book/src/binding/cxxstring.md
@@ -0,0 +1,137 @@
+{{#title std::string — Rust ♡ C++}}
+# std::string
+
+The Rust binding of std::string is called **[`CxxString`]**. See the link for
+documentation of the Rust API.
+
+[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html
+
+### Restrictions:
+
+Rust code can never obtain a CxxString by value. C++'s string requires a move
+constructor and may hold internal pointers, which is not compatible with Rust's
+move behavior. Instead in Rust code we will only ever look at a CxxString
+through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\>
+or UniquePtr\<CxxString\>.
+
+In order to construct a CxxString on the stack from Rust, you must use the
+[`let_cxx_string!`] macro which will pin the string properly. The code below
+uses this in one place, and the link covers the syntax.
+
+[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html
+
+## Example
+
+This example uses C++17's std::variant to build a toy JSON type. JSON can hold
+various types including strings, and JSON's object type is a map with string
+keys. The example demonstrates Rust indexing into one of those maps.
+
+```rust,noplayground
+// src/main.rs
+
+use cxx::let_cxx_string;
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/json.h");
+
+        type json;
+        type object;
+
+        fn isNull(self: &json) -> bool;
+        fn isNumber(self: &json) -> bool;
+        fn isString(self: &json) -> bool;
+        fn isArray(self: &json) -> bool;
+        fn isObject(self: &json) -> bool;
+
+        fn getNumber(self: &json) -> f64;
+        fn getString(self: &json) -> &CxxString;
+        fn getArray(self: &json) -> &CxxVector<json>;
+        fn getObject(self: &json) -> &object;
+
+        #[cxx_name = "at"]  // https://en.cppreference.com/w/cpp/container/map/at
+        fn get<'a>(self: &'a object, key: &CxxString) -> &'a json;
+
+        fn load_config() -> UniquePtr<json>;
+    }
+}
+
+fn main() {
+    let config = ffi::load_config();
+
+    let_cxx_string!(key = "name");
+    println!("{}", config.getObject().get(&key).getString());
+}
+```
+
+```cpp
+// include/json.h
+
+#pragma once
+#include <map>
+#include <memory>
+#include <variant>
+#include <vector>
+
+class json final {
+public:
+  static const json null;
+  using number = double;
+  using string = std::string;
+  using array = std::vector<json>;
+  using object = std::map<string, json>;
+
+  json() noexcept = default;
+  json(const json &) = default;
+  json(json &&) = default;
+  template <typename... T>
+  json(T &&... value) : value(std::forward<T>(value)...) {}
+
+  bool isNull() const;
+  bool isNumber() const;
+  bool isString() const;
+  bool isArray() const;
+  bool isObject() const;
+
+  number getNumber() const;
+  const string &getString() const;
+  const array &getArray() const;
+  const object &getObject() const;
+
+private:
+  std::variant<std::monostate, number, string, array, object> value;
+};
+
+using object = json::object;
+
+std::unique_ptr<json> load_config();
+```
+
+```cpp
+// include/json.cc
+
+#include "example/include/json.h"
+#include <initializer_list>
+#include <utility>
+
+const json json::null{};
+bool json::isNull() const { return std::holds_alternative<std::monostate>(value); }
+bool json::isNumber() const { return std::holds_alternative<number>(value); }
+bool json::isString() const { return std::holds_alternative<string>(value); }
+bool json::isArray() const { return std::holds_alternative<array>(value); }
+bool json::isObject() const { return std::holds_alternative<object>(value); }
+json::number json::getNumber() const { return std::get<number>(value); }
+const json::string &json::getString() const { return std::get<string>(value); }
+const json::array &json::getArray() const { return std::get<array>(value); }
+const json::object &json::getObject() const { return std::get<object>(value); }
+
+std::unique_ptr<json> load_config() {
+  return std::make_unique<json>(
+      std::in_place_type<json::object>,
+      std::initializer_list<std::pair<const std::string, json>>{
+          {"name", "cxx-example"},
+          {"edition", 2018.},
+          {"repository", json::null}});
+}
+```
diff --git a/book/src/binding/cxxvector.md b/book/src/binding/cxxvector.md
new file mode 100644
index 0000000..fd95a2d
--- /dev/null
+++ b/book/src/binding/cxxvector.md
@@ -0,0 +1,62 @@
+{{#title std::vector<T> — Rust ♡ C++}}
+# std::vector\<T\>
+
+The Rust binding of std::vector\<T\> is called **[`CxxVector<T>`]**. See the
+link for documentation of the Rust API.
+
+[`CxxVector<T>`]: https://docs.rs/cxx/*/cxx/struct.CxxVector.html
+
+### Restrictions:
+
+Rust code can never obtain a CxxVector by value. Instead in Rust code we will
+only ever look at a vector behind a reference or smart pointer, as in
+&CxxVector\<T\> or UniquePtr\<CxxVector\<T\>\>.
+
+CxxVector\<T\> does not support T being an opaque Rust type. You should use a
+Vec\<T\> (C++ rust::Vec\<T\>) instead for collections of opaque Rust types on
+the language boundary.
+
+## Example
+
+This program involves Rust code converting a `CxxVector<CxxString>` (i.e.
+`std::vector<std::string>`) into a Rust `Vec<String>`.
+
+```rust,noplayground
+// src/main.rs
+
+#![no_main] // main defined in C++ by main.cc
+
+use cxx::{CxxString, CxxVector};
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f(vec: &CxxVector<CxxString>);
+    }
+}
+
+fn f(vec: &CxxVector<CxxString>) {
+    let vec: Vec<String> = vec
+        .iter()
+        .map(|s| s.to_string_lossy().into_owned())
+        .collect();
+    g(&vec);
+}
+
+fn g(vec: &[String]) {
+    println!("{:?}", vec);
+}
+```
+
+```cpp
+// src/main.cc
+
+#include "example/src/main.rs.h"
+#include <string>
+#include <vector>
+
+int main() {
+  std::vector<std::string> vec{"fearless", "concurrency"};
+  f(vec);
+}
+```
diff --git a/book/src/binding/fn.md b/book/src/binding/fn.md
new file mode 100644
index 0000000..2934b06
--- /dev/null
+++ b/book/src/binding/fn.md
@@ -0,0 +1,34 @@
+{{#title Function pointers — Rust ♡ C++}}
+# Function pointers
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+template <typename Signature>
+class Fn;
+
+template <typename Ret, typename... Args>
+class Fn<Ret(Args...)> final {
+public:
+  Ret operator()(Args... args) const noexcept;
+  Fn operator*() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Function pointers with a Result return type are not implemented yet.
+
+Passing a function pointer from C++ to Rust is not implemented yet, only from
+Rust to an `extern "C++"` function is implemented.
+
+## Example
+
+Function pointers are commonly useful for implementing [async functions over
+FFI](../async.md). See the example code on that page.
diff --git a/book/src/binding/result.md b/book/src/binding/result.md
new file mode 100644
index 0000000..e49dcf4
--- /dev/null
+++ b/book/src/binding/result.md
@@ -0,0 +1,148 @@
+{{#title Result<T> — Rust ♡ C++}}
+# Result\<T\>
+
+Result\<T\> is allowed as the return type of an extern function in either
+direction. Its behavior is to translate to/from C++ exceptions. If your codebase
+does not use C++ exceptions, or prefers to represent fallibility using something
+like outcome\<T\>, leaf::result\<T\>, StatusOr\<T\>, etc then you'll need to
+handle the translation of those to Rust Result\<T\> using your own shims for
+now. Better support for this is planned.
+
+If an exception is thrown from an `extern "C++"` function that is *not* declared
+by the CXX bridge to return Result, the program calls C++'s `std::terminate`.
+The behavior is equivalent to the same exception being thrown through a
+`noexcept` C++ function.
+
+If a panic occurs in *any* `extern "Rust"` function, regardless of whether it is
+declared by the CXX bridge to return Result, a message is logged and the program
+calls Rust's `std::process::abort`.
+
+## Returning Result from Rust to C++
+
+An `extern "Rust"` function returning a Result turns into a `throw` in C++ if
+the Rust side produces an error.
+
+Note that the return type written inside of cxx::bridge must be written without
+a second type parameter. Only the Ok type is specified for the purpose of the
+FFI. The Rust *implementation* (outside of the bridge module) may pick any error
+type as long as it has a std::fmt::Display impl.
+
+```rust,noplayground
+# use std::io;
+#
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn fallible1(depth: usize) -> Result<String>;
+        fn fallible2() -> Result<()>;
+    }
+}
+
+fn fallible1(depth: usize) -> anyhow::Result<String> {
+    if depth == 0 {
+        return Err(anyhow::Error::msg("fallible1 requires depth > 0"));
+    }
+    ...
+}
+
+fn fallible2() -> Result<(), io::Error> {
+    ...
+    Ok(())
+}
+```
+
+The exception that gets thrown by CXX on the C++ side is always of type
+`rust::Error` and has the following C++ public API. The `what()` member function
+gives the error message according to the Rust error's std::fmt::Display impl.
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+class Error final : public std::exception {
+public:
+  Error(const Error &);
+  Error(Error &&) noexcept;
+  ~Error() noexcept;
+
+  Error &operator=(const Error &);
+  Error &operator=(Error &&) noexcept;
+
+  const char *what() const noexcept override;
+};
+#
+# } // namespace rust
+```
+
+## Returning Result from C++ to Rust
+
+An `extern "C++"` function returning a Result turns into a `catch` in C++ that
+converts the exception into an Err for Rust.
+
+Note that the return type written inside of cxx::bridge must be written without
+a second type parameter. Only the Ok type is specified for the purpose of the
+FFI. The resulting error type created by CXX when an `extern "C++"` function
+throws will always be of type **[`cxx::Exception`]**.
+
+[`cxx::Exception`]: https://docs.rs/cxx/*/cxx/struct.Exception.html
+
+```rust,noplayground
+# use std::process;
+#
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+        fn fallible1(depth: usize) -> Result<String>;
+        fn fallible2() -> Result<()>;
+    }
+}
+
+fn main() {
+    if let Err(err) = ffi::fallible1(99) {
+        eprintln!("Error: {}", err);
+        process::exit(1);
+    }
+}
+```
+
+The specific set of caught exceptions and the conversion to error message are
+both customizable. The way you do this is by defining a template function
+`rust::behavior::trycatch` with a suitable signature inside any one of the
+headers `include!`'d by your cxx::bridge.
+
+The template signature is required to be:
+
+```cpp,hidelines
+namespace rust {
+namespace behavior {
+
+template <typename Try, typename Fail>
+static void trycatch(Try &&func, Fail &&fail) noexcept;
+
+} // namespace behavior
+} // namespace rust
+```
+
+The default `trycatch` used by CXX if you have not provided your own is the
+following. You must follow the same pattern: invoke `func` with no arguments,
+catch whatever exception(s) you want, and invoke `fail` with the error message
+you'd like for the Rust error to have.
+
+```cpp,hidelines
+# #include <exception>
+#
+# namespace rust {
+# namespace behavior {
+#
+template <typename Try, typename Fail>
+static void trycatch(Try &&func, Fail &&fail) noexcept try {
+  func();
+} catch (const std::exception &e) {
+  fail(e.what());
+}
+#
+# } // namespace behavior
+# } // namespace rust
+```
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
new file mode 100644
index 0000000..aacd56b
--- /dev/null
+++ b/book/src/binding/slice.md
@@ -0,0 +1,115 @@
+{{#title rust::Slice<T> — Rust ♡ C++}}
+# rust::Slice\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+template <typename T>
+class Slice final {
+public:
+  Slice() noexcept;
+  Slice(const Slice<T> &) noexcept;
+  Slice(T *, size_t count) noexcept;
+
+  Slice &operator=(const Slice<T> &) noexcept;
+
+  T *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Only &amp;\[u8\] i.e. rust::Slice\<const uint8\_t\> is currently implemented.
+Support for arbitrary &amp;\[T\] is coming.
+
+Allowed as function argument or return value. Not supported in shared structs.
+&amp;mut \[T\] is not supported yet.
+
+## Example
+
+This example is a C++ program that constructs a slice containing JSON data (by
+reading from stdin, but it could be from anywhere), then calls into Rust to
+pretty-print that JSON data into a std::string via the [serde_json] and
+[serde_transcode] crates.
+
+[serde_json]: https://github.com/serde-rs/json
+[serde_transcode]: https://github.com/sfackler/serde-transcode
+
+```rust,noplayground
+// src/main.rs
+
+#![no_main] // main defined in C++ by main.cc
+
+use cxx::CxxString;
+use std::io::{self, Write};
+use std::pin::Pin;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>;
+    }
+}
+
+struct WriteToCxxString<'a>(Pin<&'a mut CxxString>);
+
+impl<'a> Write for WriteToCxxString<'a> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.as_mut().push_bytes(buf);
+        Ok(buf.len())
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> {
+    let writer = WriteToCxxString(output);
+    let mut deserializer = serde_json::Deserializer::from_slice(input);
+    let mut serializer = serde_json::Serializer::pretty(writer);
+    serde_transcode::transcode(&mut deserializer, &mut serializer)
+}
+```
+
+```cpp
+// src/main.cc
+
+#include "example/src/main.rs.h"
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+int main() {
+  // Read json from stdin.
+  std::istreambuf_iterator<char> begin{std::cin}, end;
+  std::vector<unsigned char> input{begin, end};
+  rust::Slice<const uint8_t> slice{input.data(), input.size()};
+
+  // Prettify using serde_json and serde_transcode.
+  std::string output;
+  prettify_json(slice, output);
+
+  // Write to stdout.
+  std::cout << output << std::endl;
+}
+```
+
+Testing the example:
+
+```console
+$  echo '{"fearless":"concurrency"}' | cargo run
+    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
+     Running `target/debug/example`
+{
+  "fearless": "concurrency"
+}
+```
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
new file mode 100644
index 0000000..2774754
--- /dev/null
+++ b/book/src/binding/str.md
@@ -0,0 +1,101 @@
+{{#title rust::Str — Rust ♡ C++}}
+# rust::Str
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iosfwd>
+# #include <string>
+#
+# namespace rust {
+
+class Str final {
+public:
+  Str() noexcept;
+  Str(const Str &) noexcept;
+
+  // Throws std::invalid_argument if not utf-8.
+  Str(const std::string &);
+  Str(const char *);
+  Str(const char *, size_t);
+  Str(std::string &&) = delete;
+
+  Str &operator=(const Str &) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+
+std::ostream &operator<<(std::ostream &, const Str &);
+#
+# } // namespace rust
+```
+
+### Notes:
+
+**Be aware that rust::Str behaves like &amp;str i.e. it is a borrow!**&ensp;C++
+needs to be mindful of the lifetimes at play.
+
+Just to reiterate: &amp;str is rust::Str. Do not try to write &amp;str as `const
+rust::Str &`. A language-level C++ reference is not able to capture the fat
+pointer nature of &amp;str.
+
+### Restrictions:
+
+Allowed as function argument or return value. Not supported in shared structs
+yet. `&mut str` is not supported yet, but is also extremely obscure so this is
+fine.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn r(greeting: &str);
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/greeting.h");
+        fn c(greeting: &str);
+    }
+}
+
+fn r(greeting: &str) {
+    println!("{}", greeting);
+}
+
+fn main() {
+    ffi::c("hello from Rust");
+}
+```
+
+```cpp
+// include/greeting.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void c(rust::Str greeting);
+```
+
+```cpp
+// src/greeting.cc
+
+#include "example/include/greeting.h"
+#include <iostream>
+
+void c(rust::Str greeting) {
+  std::cout << greeting << std::endl;
+  r("hello from C++");
+}
+```
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
new file mode 100644
index 0000000..ac44fb2
--- /dev/null
+++ b/book/src/binding/string.md
@@ -0,0 +1,94 @@
+{{#title rust::String — Rust ♡ C++}}
+# rust::String
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iosfwd>
+# #include <string>
+#
+# namespace rust {
+
+class String final {
+public:
+  String() noexcept;
+  String(const String &) noexcept;
+  String(String &&) noexcept;
+  ~String() noexcept;
+
+  // Throws std::invalid_argument if not utf-8.
+  String(const std::string &);
+  String(const char *);
+  String(const char *, size_t);
+
+  String &operator=(const String &) noexcept;
+  String &operator=(String &&) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+
+std::ostream &operator<<(std::ostream &, const String &);
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+None. Strings may be used as function arguments and function return values, by
+value or by reference, as well as fields of shared structs.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct ConcatRequest {
+        fst: String,
+        snd: String,
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/concat.h");
+        fn concat(r: ConcatRequest) -> String;
+    }
+}
+
+fn main() {
+    let concatenated = ffi::concat(ffi::ConcatRequest {
+        fst: "fearless".to_owned(),
+        snd: "concurrency".to_owned(),
+    });
+    println!("concatenated: {:?}", concatenated);
+}
+```
+
+```cpp
+// include/concat.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+rust::String concat(ConcatRequest r);
+```
+
+```cpp
+// src/concat.cc
+
+#include "example/include/concat.h"
+
+rust::String concat(ConcatRequest r) {
+  // The full suite of operator overloads hasn't been added
+  // yet on rust::String, but we can get it done like this:
+  return std::string(r.fst) + std::string(r.snd);
+}
+```
diff --git a/book/src/binding/uniqueptr.md b/book/src/binding/uniqueptr.md
new file mode 100644
index 0000000..eefbc34
--- /dev/null
+++ b/book/src/binding/uniqueptr.md
@@ -0,0 +1,63 @@
+{{#title std::unique_ptr<T> — Rust ♡ C++}}
+# std::unique\_ptr\<T\>
+
+The Rust binding of std::unique\_ptr\<T\> is called **[`UniquePtr<T>`]**. See
+the link for documentation of the Rust API.
+
+[`UniquePtr<T>`]: https://docs.rs/cxx/*/cxx/struct.UniquePtr.html
+
+### Restrictions:
+
+Only `std::unique_ptr<T, std::default_delete<T>>` is currently supported. Custom
+deleters may be supported in the future.
+
+UniquePtr\<T\> does not support T being an opaque Rust type. You should use a
+Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of
+opaque Rust types on the language boundary.
+
+## Example
+
+UniquePtr is commonly useful for returning opaque C++ objects to Rust. This use
+case was featured in the [*blobstore tutorial*](../tutorial.md).
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        // ...
+    }
+}
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+    // ...
+}
+```
+
+```cpp
+// include/blobstore.h
+
+#pragma once
+#include <memory>
+
+class BlobstoreClient;
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp
+// src/blobstore.cc
+
+#include "example/include/blobstore.h"
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::make_unique<BlobstoreClient>();
+}
+```
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
new file mode 100644
index 0000000..f3056fb
--- /dev/null
+++ b/book/src/binding/vec.md
@@ -0,0 +1,128 @@
+{{#title rust::Vec<T> — Rust ♡ C++}}
+# rust::Vec\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iterator>
+# #include <type_traits>
+#
+# namespace rust {
+
+template <typename T>
+class Vec final {
+public:
+  using value_type = T;
+
+  Vec() noexcept;
+  Vec(Vec &&) noexcept;
+  ~Vec() noexcept;
+
+  Vec &operator=(Vec &&) noexcept;
+
+  size_t size() const noexcept;
+  bool empty() const noexcept;
+  const T *data() const noexcept;
+  T *data() noexcept;
+
+  const T &operator[](size_t n) const noexcept;
+  const T &at(size_t n) const;
+
+  const T &front() const;
+  const T &back() const;
+
+  void reserve(size_t new_cap);
+  void push_back(const T &value);
+  void push_back(T &&value);
+  template <typename... Args>
+  void emplace_back(Args &&... args);
+
+  class const_iterator final {
+  public:
+    using difference_type = ptrdiff_t;
+    using value_type = typename std::add_const<T>::type;
+    using pointer =
+        typename std::add_pointer<typename std::add_const<T>::type>::type;
+    using reference = typename std::add_lvalue_reference<
+        typename std::add_const<T>::type>::type;
+    using iterator_category = std::forward_iterator_tag;
+
+    const T &operator*() const noexcept;
+    const T *operator->() const noexcept;
+    const_iterator &operator++() noexcept;
+    const_iterator operator++(int) noexcept;
+    bool operator==(const const_iterator &) const noexcept;
+    bool operator!=(const const_iterator &) const noexcept;
+  };
+
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Vec\<T\> does not support T being an opaque C++ type. You should use
+CxxVector\<T\> (C++ std::vector\<T\>) instead for collections of opaque C++
+types on the language boundary.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        v: u32,
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        fn f(elements: Vec<Shared>);
+    }
+}
+
+fn main() {
+    let shared = |v| ffi::Shared { v };
+    let elements = vec![shared(3), shared(2), shared(1)];
+    ffi::f(elements);
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void f(rust::Vec<Shared> elements);
+```
+
+```cpp
+// src/example.cc
+
+#include "example/include/example.h"
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <iterator>
+#include <vector>
+
+void f(rust::Vec<Shared> v) {
+  for (auto shared : v) {
+    std::cout << shared.v << std::endl;
+  }
+
+  // Copy the elements to a C++ std::vector using STL algorithm.
+  std::vector<Shared> stdv;
+  std::copy(v.begin(), v.end(), std::back_inserter(stdv));
+  assert(v.size() == stdv.size());
+}
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
new file mode 100644
index 0000000..f19dc5d
--- /dev/null
+++ b/book/src/bindings.md
@@ -0,0 +1,54 @@
+{{#title Built-in bindings — Rust ♡ C++}}
+# Built-in bindings reference
+
+In addition to all the primitive types (i32 &lt;=&gt; int32_t), the following
+common types may be used in the fields of shared structs and the arguments and
+returns of extern functions.
+
+<br>
+
+<table>
+<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
+<tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
+</table>
+
+<br>
+
+The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
+the CXX GitHub repo. You will need to include this header in your C++ code when
+working with those types. **When using Cargo and the cxx-build crate, the header
+is made available to you at `#include "rust/cxx.h"`.**
+
+The `rust` namespace additionally provides lowercase type aliases of all the
+types mentioned in the table, for use in codebases preferring that style. For
+example `rust::String`, `rust::Vec` may alternatively be written `rust::string`,
+`rust::vec` etc.
+
+## Pending bindings
+
+The following types are intended to be supported "soon" but are just not
+implemented yet. I don't expect any of these to be hard to make work but it's a
+matter of designing a nice API for each in its non-native language.
+
+<br>
+
+<table>
+<tr><th>name in Rust</th><th>name in C++</th></tr>
+<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td></tr>
+<tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
+</table>
diff --git a/book/src/build/bazel.md b/book/src/build/bazel.md
new file mode 100644
index 0000000..08edb19
--- /dev/null
+++ b/book/src/build/bazel.md
@@ -0,0 +1,106 @@
+{{#title Bazel, Buck — Rust ♡ C++}}
+## Bazel, Buck, potentially other similar environments
+
+Starlark-based build systems with the ability to compile a code generator and
+invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge`
+command line interface.
+
+The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built
+from the *gen/cmd/* directory of the CXX GitHub repo.
+
+```console
+$  cargo install cxxbridge-cmd
+
+$  cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
+$  cxxbridge src/bridge.rs > path/to/bridge.rs.cc
+```
+
+The CXX repo maintains working Bazel `BUILD` and Buck `BUCK` targets for the
+complete blobstore tutorial (chapter 3) for your reference, tested in CI. These
+aren't meant to be directly what you use in your codebase, but serve as an
+illustration of one possible working pattern.
+
+```python
+# tools/bazel/rust_cxx_bridge.bzl
+
+load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+def rust_cxx_bridge(name, src, deps = []):
+    native.alias(
+        name = "%s/header" % name,
+        actual = src + ".h",
+    )
+
+    native.alias(
+        name = "%s/source" % name,
+        actual = src + ".cc",
+    )
+
+    run_binary(
+        name = "%s/generated" % name,
+        srcs = [src],
+        outs = [
+            src + ".h",
+            src + ".cc",
+        ],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.h)" % src,
+            "-o",
+            "$(location %s.cc)" % src,
+        ],
+        tool = "//:codegen",
+    )
+
+    cc_library(
+        name = name,
+        srcs = [src + ".cc"],
+        deps = deps + [":%s/include" % name],
+    )
+
+    cc_library(
+        name = "%s/include" % name,
+        hdrs = [src + ".h"],
+    )
+```
+
+```python
+# demo/BUILD
+
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("//tools/bazel:rust.bzl", "rust_binary")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
+
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":blobstore-sys",
+        ":bridge",
+        "//:cxx",
+    ],
+)
+
+rust_cxx_bridge(
+    name = "bridge",
+    src = "src/main.rs",
+    deps = [":blobstore-include"],
+)
+
+cc_library(
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
+    deps = [
+        ":blobstore-include",
+        ":bridge/include",
+    ],
+)
+
+cc_library(
+    name = "blobstore-include",
+    hdrs = ["include/blobstore.h"],
+    deps = ["//:core"],
+)
+```
diff --git a/book/src/build/cargo.md b/book/src/build/cargo.md
new file mode 100644
index 0000000..82ccfb5
--- /dev/null
+++ b/book/src/build/cargo.md
@@ -0,0 +1,306 @@
+{{#title Cargo-based setup — Rust ♡ C++}}
+# Cargo-based builds
+
+As one aspect of delivering a good Rust&ndash;C++ interop experience, CXX turns
+Cargo into a quite usable build system for C++ projects published as a
+collection of crates.io packages, including a consistent and frictionless
+experience `#include`-ing C++ headers across dependencies.
+
+## Canonical setup
+
+CXX's integration with Cargo is handled through the [cxx-build] crate.
+
+[cxx-build]: https://docs.rs/cxx-build
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "..."
+# version = "..."
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+
+[build-dependencies]
+cxx-build = "1.0"
+```
+
+The canonical build script is as follows. The indicated line returns a
+[`cc::Build`] instance (from the usual widely used `cc` crate) on which you can
+set up any additional source files and compiler flags as normal.
+
+[`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
+
+```rust,noplayground
+// build.rs
+
+fn main() {
+    cxx_build::bridge("src/main.rs")  // returns a cc::Build
+        .file("src/demo.cc")
+        .flag_if_supported("-std=c++11")
+        .compile("cxxbridge-demo");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
+}
+```
+
+The `rerun-if-changed` lines are optional but make it so that Cargo does not
+spend time recompiling your C++ code when only non-C++ code has changed since
+the previous Cargo build. By default without any `rerun-if-changed`, Cargo will
+re-execute the build script after *any* file changed in the project.
+
+If stuck, try comparing what you have against the *demo/* directory of the CXX
+GitHub repo, which maintains a working Cargo-based setup for the blobstore
+tutorial (chapter 3).
+
+## Header include paths
+
+With cxx-build, by default your include paths always start with the crate name.
+This applies to both `#include` within your C++ code, and `include!` in the
+`extern "C++"` section of your Rust cxx::bridge.
+
+Your crate name is determined by the `name` entry in Cargo.toml.
+
+For example if your crate is named `yourcratename` and contains a C++ header
+file `path/to/header.h` relative to Cargo.toml, that file will be includable as:
+
+```cpp
+#include "yourcratename/path/to/header.h"
+```
+
+A crate can choose a prefix for its headers that is different from the crate
+name by modifying **[`CFG.include_prefix`][CFG]** from build.rs:
+
+[CFG]: https://docs.rs/cxx-build/*/cxx_build/static.CFG.html
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.include_prefix = "my/project";
+
+    cxx_build::bridge(...)...
+}
+```
+
+Subsequently the header located at `path/to/header.h` would now be includable
+as:
+
+```cpp
+#include "my/project/path/to/header.h"
+```
+
+The empty string `""` is a valid include prefix and will make it possible to
+have `#include "path/to/header.h"`. However, if your crate is a library, be
+considerate of possible name collisions that may occur in downstream crates. If
+using an empty include prefix, you'll want to make sure your headers' local path
+within the crate is sufficiently namespaced or unique.
+
+## Including generated code
+
+If your `#[cxx::bridge]` module contains an `extern "Rust"` block i.e. types or
+functions exposed from Rust to C++, or any shared data structures, the
+CXX-generated C++ header declaring those things is available using a `.rs.h`
+extension on the Rust source file's name.
+
+```cpp
+// the header generated from path/to/lib.rs
+#include "yourcratename/path/to/lib.rs.h"
+```
+
+For giggles, it's also available using just a plain `.rs` extension as if you
+were including the Rust file directly. Use whichever you find more palatable.
+
+```cpp
+#include "yourcratename/path/to/lib.rs"
+```
+
+## Including headers from dependencies
+
+You get to include headers from your dependencies, both handwritten ones
+contained as `.h` files in their Cargo package, as well as CXX-generated ones.
+
+It works the same as an include of a local header: use the crate name (or their
+include\_prefix if their crate changed it) followed by the relative path of the
+header within the crate.
+
+```cpp
+#include "dependencycratename/path/to/their/header.h`
+```
+
+Note that cross-crate imports are only made available between **direct
+dependencies**. You must directly depend on the other crate in order to #include
+its headers; a transitive dependency is not sufficient.
+
+Additionally, headers from a direct dependency are only importable if the
+dependency's Cargo.toml manifest contains a `links` key. If not, its headers
+will not be importable from outside of the same crate. See *[the `links`
+manifest key][links]* in the Cargo reference.
+
+[links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+
+<br><br><br>
+
+# Advanced features
+
+The following CFG settings are only relevant to you if you are writing a library
+that needs to support downstream crates `#include`-ing its C++ public headers.
+
+## Publicly exporting header directories
+
+**[`CFG.exported_header_dirs`][CFG]** (vector of absolute paths) defines a set
+of additional directories from which the current crate, directly dependent
+crates, and further crates to which this crate's headers are exported (more
+below) will be able to `#include` headers.
+
+Adding a directory to `exported_header_dirs` is similar to adding it to the
+current build via the `cc` crate's [`Build::include`], but *also* makes the
+directory available to downstream crates that want to `#include` one of the
+headers from your crate. If the dir were added only using `Build::include`, the
+downstream crate including your header would need to manually add the same
+directory to their own build as well.
+
+[`Build::include`]: https://docs.rs/cc/1/cc/struct.Build.html#method.include
+
+When using `exported_header_dirs`, your crate must also set a `links` key for
+itself in Cargo.toml. See [*the `links` manifest key*][links]. The reason is
+that Cargo imposes no ordering on the execution of build scripts without a
+`links` key, which means the downstream crate's build script might otherwise
+execute before yours decides what to put into `exported_header_dirs`.
+
+### Example
+
+One of your crate's headers wants to include a system library, such as `#include
+"Python.h"`.
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+use std::path::PathBuf;
+
+fn main() {
+    let python3 = pkg_config::probe_library("python3").unwrap();
+    let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path);
+    CFG.exported_header_dirs.extend(python_include_paths);
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
+
+### Example
+
+Your crate wants to rearrange the headers that it exports vs how they're laid
+out locally inside the crate's source directory.
+
+Suppose the crate as published contains a file at `./include/myheader.h` but
+wants it available to downstream crates as `#include "foo/v1/public.h"`.
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+use std::path::Path;
+use std::{env, fs};
+
+fn main() {
+    let out_dir = env::var_os("OUT_DIR").unwrap();
+    let headers = Path::new(&out_dir).join("headers");
+    CFG.exported_header_dirs.push(&headers);
+
+    // We contain `include/myheader.h` locally, but
+    // downstream will use `#include "foo/v1/public.h"`
+    let foo = headers.join("foo").join("v1");
+    fs::create_dir_all(&foo).unwrap();
+    fs::copy("include/myheader.h", foo.join("public.h")).unwrap();
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
+
+## Publicly exporting dependencies
+
+**[`CFG.exported_header_prefixes`][CFG]** (vector of strings) each refer to the
+`include_prefix` of one of your direct dependencies, or a prefix thereof. They
+describe which of your dependencies participate in your crate's C++ public API,
+as opposed to private use by your crate's implementation.
+
+As a general rule, if one of your headers `#include`s something from one of your
+dependencies, you need to put that dependency's `include_prefix` into
+`CFG.exported_header_prefixes` (*or* their `links` key into
+`CFG.exported_header_links`; see below). On the other hand if only your C++
+implementation files and *not* your headers are importing from the dependency,
+you do not export that dependency.
+
+The significance of exported headers is that if downstream code (crate **𝒜**)
+contains an `#include` of a header from your crate (**ℬ**) and your header
+contains an `#include` of something from your dependency (**𝒞**), the exported
+dependency **𝒞** becomes available during the downstream crate **𝒜**'s build.
+Otherwise the downstream crate **𝒜** doesn't know about **𝒞** and wouldn't be
+able to find what header your header is referring to, and would fail to build.
+
+When using `exported_header_prefixes`, your crate must also set a `links` key
+for itself in Cargo.toml.
+
+### Example
+
+Suppose you have a crate with 5 direct dependencies and the `include_prefix` for
+each one are:
+
+- "crate0"
+- "group/api/crate1"
+- "group/api/crate2"
+- "group/api/contrib/crate3"
+- "detail/crate4"
+
+Your header involves types from the first four so we re-export those as part of
+your public API, while crate4 is only used internally by your cc file not your
+header, so we do not export:
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.exported_header_prefixes = vec!["crate0", "group/api"];
+
+    cxx_build::bridge("src/bridge.rs")
+        .file("src/impl.cc")
+        .compile("demo");
+}
+```
+
+<br>
+
+For more fine grained control, there is **[`CFG.exported_header_links`][CFG]**
+(vector of strings) which each refer to the `links` attribute ([*the `links`
+manifest key*][links]) of one of your crate's direct dependencies.
+
+This achieves an equivalent result to `CFG.exported_header_prefixes` by
+re-exporting a C++ dependency as part of your crate's public API, except with
+finer control for cases when multiple crates might be sharing the same
+`include_prefix` and you'd like to export some but not others. Links attributes
+are guaranteed to be unique identifiers by Cargo.
+
+When using `exported_header_links`, your crate must also set a `links` key for
+itself in Cargo.toml.
+
+### Example
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.exported_header_links.push("git2");
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
diff --git a/book/src/build/cmake.md b/book/src/build/cmake.md
new file mode 100644
index 0000000..ed3cb61
--- /dev/null
+++ b/book/src/build/cmake.md
@@ -0,0 +1,24 @@
+{{#title CMake — Rust ♡ C++}}
+# CMake
+
+There is not an officially endorsed CMake setup for CXX, but a few developers
+have shared one that they got working. You can try one of these as a starting
+point. If you feel that you have arrived at a CMake setup that is superior to
+what is available in these links, feel free to make a PR adding it to this list.
+
+<br>
+
+---
+
+- **<https://github.com/XiangpengHao/cxx-cmake-example>**
+
+  - Supports cross-language link time optimization (LTO)
+
+---
+
+- **<https://github.com/david-cattermole/cxx-demo-example>**
+
+  - Includes a cbindgen component
+  - Tested on Windows 10 with MSVC, and on Linux
+
+---
diff --git a/book/src/build/other.md b/book/src/build/other.md
new file mode 100644
index 0000000..8933c41
--- /dev/null
+++ b/book/src/build/other.md
@@ -0,0 +1,75 @@
+{{#title Other build systems — Rust ♡ C++}}
+# Some other build system
+
+You will need to achieve at least these three things:
+
+- Produce the CXX-generated C++ bindings code.
+- Compile the generated C++ code.
+- Link the resulting objects together with your other C++ and Rust objects.
+
+### Producing the generated code
+
+CXX's Rust code generation automatically happens when the `#[cxx::bridge]`
+procedural macro is expanded during the normal Rust compilation process, so no
+special build steps are required there.
+
+But the C++ side of the bindings needs to be generated. Your options are:
+
+- Use the `cxxbridge` command, which is a standalone command line interface to
+  the CXX C++ code generator. Wire up your build system to compile and invoke
+  this tool.
+
+  ```console
+  $  cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
+  $  cxxbridge src/bridge.rs > path/to/bridge.rs.cc
+  ```
+
+  It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from
+  the *gen/cmd/* directory of the CXX GitHub repo.
+
+- Or, build your own code generator frontend on top of the [cxx-gen] crate. This
+  is currently unofficial and unsupported.
+
+[cxx-gen]: https://docs.rs/cxx-gen
+
+### Compiling C++
+
+However you like. We can provide no guidance.
+
+### Linking the C++ and Rust together
+
+When linking a binary which contains mixed Rust and C++ code, you will have to
+choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you
+may already have extensively tuned.
+
+Rust does not generate simple standalone `.o` files, so you can't just throw the
+Rust-generated code into your existing C++ toolchain linker. Instead you need to
+choose one of these options:
+
+* Use `rustc` as the final linker. Pass any non-Rust libraries using `-L
+  <directory>` and `-l<library>` rustc arguments, and/or `#[link]` directives in
+  your Rust code. If you need to link against C/C++ `.o` files you can use
+  `-Clink-arg=file.o`.
+
+* Use your C++ linker. In this case, you first need to use `rustc` and/or
+  `cargo` to generate a _single_ Rust `staticlib` target and pass that into your
+  foreign linker invocation.
+
+  * If you need to link multiple Rust subsystems, you will need to generate a
+    _single_ `staticlib` perhaps using lots of `extern crate` statements to
+    include multiple Rust `rlib`s.  Multiple Rust `staticlib` files are likely
+    to conflict.
+
+Passing Rust `rlib`s directly into your non-Rust linker is not supported (but
+apparently sometimes works).
+
+See the [Rust reference's *Linkage*][linkage] page for some general information
+here.
+
+[linkage]: https://doc.rust-lang.org/reference/linkage.html
+
+The following open rust-lang issues might hold more recent guidance or
+inspiration: [rust-lang/rust#73632], [rust-lang/rust#73295].
+
+[rust-lang/rust#73632]: https://github.com/rust-lang/rust/issues/73632
+[rust-lang/rust#73295]: https://github.com/rust-lang/rust/issues/73295
diff --git a/book/src/building.md b/book/src/building.md
new file mode 100644
index 0000000..c75939e
--- /dev/null
+++ b/book/src/building.md
@@ -0,0 +1,20 @@
+{{#title Multi-language build system options — Rust ♡ C++}}
+# Multi-language build system options
+
+CXX is designed to be convenient to integrate into a variety of build systems.
+
+If you are working in a project that does not already have a preferred build
+system for its C++ code *or* which will be relying heavily on open source
+libraries from the Rust package registry, you're likely to have the easiest
+experience with Cargo which is the build system commonly used by open source
+Rust projects. Refer to the ***[Cargo](build/cargo.md)*** chapter about CXX's
+Cargo support.
+
+Among build systems designed for first class multi-language support, Bazel is a
+solid choice. Refer to the ***[Bazel](build/bazel.md)*** chapter.
+
+If your codebase is already invested in CMake, refer to the
+***[CMake](build/cmake.md)*** chapter.
+
+If you have some other build system that you'd like to try to make work with
+CXX, see [this page](build/other.md) for notes.
diff --git a/book/src/concepts.md b/book/src/concepts.md
new file mode 100644
index 0000000..75daedd
--- /dev/null
+++ b/book/src/concepts.md
@@ -0,0 +1,85 @@
+{{#title Core concepts — Rust ♡ C++}}
+# Core concepts
+
+This page is a brief overview of the major concepts of CXX, enough so that you
+recognize the shape of things as you read the tutorial and following chapters.
+
+In CXX, the language of the FFI boundary involves 3 kinds of items:
+
+- **Shared structs** &mdash; data structures whose fields are made visible to
+  both languages. The definition written within cxx::bridge in Rust is usually
+  the single source of truth, though there are ways to do sharing based on a
+  bindgen-generated definition with C++ as source of truth.
+
+- **Opaque types** &mdash; their fields are secret from the other language.
+  These cannot be passed across the FFI by value but only behind an indirection,
+  such as a reference `&`, a Rust `Box`, or a C++ `unique_ptr`. Can be a type
+  alias for an arbitrarily complicated generic language-specific type depending
+  on your use case.
+
+- **Functions** &mdash; implemented in either language, callable from the other
+  language.
+
+```rust,noplayground,focuscomment
+# #[cxx::bridge]
+# mod ffi {
+    // Any shared structs, whose fields will be visible to both languages.
+#     struct BlobMetadata {
+#         size: usize,
+#         tags: Vec<String>,
+#     }
+#
+#     extern "Rust" {
+        // Zero or more opaque types which both languages can pass around
+        // but only Rust can see the fields.
+#         type MultiBuf;
+#
+        // Functions implemented in Rust.
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+        // One or more headers with the matching C++ declarations for the
+        // enclosing extern "C++" block. Our code generators don't read it
+        // but it gets #include'd and used in static assertions to ensure
+        // our picture of the FFI boundary is accurate.
+#         include!("demo/include/blobstore.h");
+#
+        // Zero or more opaque types which both languages can pass around
+        // but only C++ can see the fields.
+#         type BlobstoreClient;
+#
+        // Functions implemented in C++.
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#         fn tag(&self, blobid: u64, tag: &str);
+#         fn metadata(&self, blobid: u64) -> BlobMetadata;
+#     }
+# }
+```
+
+Within the `extern "Rust"` part of the CXX bridge we list the types and
+functions for which Rust is the source of truth. These all implicitly refer to
+the `super` module, the parent module of the CXX bridge. You can think of the
+two items listed in the example above as being like `use super::MultiBuf` and
+`use super::next_chunk` except re-exported to C++. The parent module will either
+contain the definitions directly for simple things, or contain the relevant
+`use` statements to bring them into scope from elsewhere.
+
+Within the `extern "C++"` part, we list types and functions for which C++ is the
+source of truth, as well as the header(s) that declare those APIs. In the future
+it's possible that this section could be generated bindgen-style from the
+headers but for now we need the signatures written out; static assertions verify
+that they are accurate.
+
+<br><br>
+
+Be aware that the design of this library is intentionally restrictive and
+opinionated! It isn't a goal to be flexible enough to handle an arbitrary
+signature in either language. Instead this project is about carving out a highly
+expressive set of functionality about which we can make powerful safety
+guarantees today and extend over time. You may find that it takes some practice
+to use CXX bridge effectively as it won't work in all the ways that you may be
+used to.
+
+<br>
diff --git a/book/src/context.md b/book/src/context.md
new file mode 100644
index 0000000..516ee91
--- /dev/null
+++ b/book/src/context.md
@@ -0,0 +1,118 @@
+{{#title Other Rust–C++ interop tools — Rust ♡ C++}}
+# Context: other Rust&ndash;C++ interop tools
+
+When it comes to interacting with an idiomatic Rust API or idiomatic C++ API
+from the other language, the generally applicable approaches outside of the CXX
+crate are:
+
+- Build a C-compatible wrapper around the code (expressed using `extern "C"`
+  signatures, primitives, C-compatible structs, raw pointers). Translate that
+  manually to equivalent `extern "C"` declarations in the other language and
+  keep them in sync. Preferably, build a safe/idiomatic wrapper around the
+  translated `extern "C"` signatures for callers to use.
+
+- Build a C wrapper around the C++ code and use **[bindgen]** to translate that
+  programmatically to `extern "C"` Rust signatures. Preferably, build a
+  safe/idiomatic Rust wrapper on top.
+
+- Build a C-compatible Rust wrapper around the Rust code and use **[cbindgen]**
+  to translate that programmatically to an `extern "C"` C++ header. Preferably,
+  build an idiomatic C++ wrapper.
+
+**If the code you are binding is already *"effectively C"*, the above has you
+covered.** You should use bindgen or cbindgen, or manually translated C
+signatures if there aren't too many and they seldom change.
+
+[bindgen]: https://github.com/rust-lang/rust-bindgen
+[cbindgen]: https://github.com/eqrion/cbindgen
+
+## C++ vs C
+
+Bindgen has some basic support for C++. It can reason about classes, member
+functions, and the layout of templated types. However, everything it does
+related to C++ is best-effort only. Bindgen starts from a point of wanting to
+generate declarations for everything, so any C++ detail that it hasn't
+implemented will cause a crash if you are lucky ([bindgen#388]) or more likely
+silently emit an incompatible signature ([bindgen#380], [bindgen#607],
+[bindgen#652], [bindgen#778], [bindgen#1194]) which will do arbitrary
+memory-unsafe things at runtime whenever called.
+
+[bindgen#388]: https://github.com/rust-lang/rust-bindgen/issues/388
+[bindgen#380]: https://github.com/rust-lang/rust-bindgen/issues/380
+[bindgen#607]: https://github.com/rust-lang/rust-bindgen/issues/607
+[bindgen#652]: https://github.com/rust-lang/rust-bindgen/issues/652
+[bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
+[bindgen#1194]: https://github.com/rust-lang/rust-bindgen/issues/1194
+
+Thus using bindgen correctly requires not just juggling all your pointers
+correctly at the language boundary, but also understanding ABI details and their
+workarounds and reliably applying them. For example, the programmer will
+discover that their program sometimes segfaults if they call a function that
+returns std::unique\_ptr\<T\> through bindgen. Why? Because unique\_ptr, despite
+being "just a pointer", has a different ABI than a pointer or a C struct
+containing a pointer ([bindgen#778]) and is not directly expressible in Rust.
+Bindgen emitted something that *looks* reasonable and you will have a hell of a
+time in gdb working out what went wrong. Eventually people learn to avoid
+anything involving a non-trivial copy constructor, destructor, or inheritance,
+and instead stick to raw pointers and primitives and trivial structs only
+&mdash; in other words C.
+
+## Geometric intuition for why there is so much opportunity for improvement
+
+The CXX project attempts a different approach to C++ FFI.
+
+Imagine Rust and C and C++ as three vertices of a scalene triangle, with length
+of the edges being related to similarity of the languages when it comes to
+library design.
+
+The most similar pair (the shortest edge) is Rust&ndash;C++. These languages
+have largely compatible concepts of things like ownership, vectors, strings,
+fallibility, etc that translate clearly from signatures in either language to
+signatures in the other language.
+
+When we make a binding for an idiomatic C++ API using bindgen, and we fall down
+to raw pointers and primitives and trivial structs as described above, what we
+are really doing is coding the two longest edges of the triangle: getting from
+C++ down to C, and C back up to Rust. The Rust&ndash;C edge always involves a
+great deal of `unsafe` code, and the C++&ndash;C edge similarly requires care
+just for basic memory safety. Something as basic as "how do I pass ownership of
+a string to the other language?" becomes a strap-yourself-in moment,
+particularly for someone not already an expert in one or both sides.
+
+You should think of the `cxx` crate as being the midpoint of the Rust&ndash;C++
+edge. Rather than coding the two long edges, you will code half the short edge
+in Rust and half the short edge in C++, in both cases with the library playing
+to the strengths of the Rust type system *and* the C++ type system to help
+assure correctness.
+
+If you've already been through the tutorial in the previous chapter, take a
+moment to appreciate that the C++ side *really* looks like we are just writing
+C++ and the Rust side *really* looks like we are just writing Rust. Anything you
+could do wrong in Rust, and almost anything you could reasonably do wrong in
+C++, will be caught by the compiler. This highlights that we are on the "short
+edge of the triangle".
+
+But it all still boils down to the same things: it's still FFI from one piece of
+native code to another, nothing is getting serialized or allocated or
+runtime-checked in between.
+
+## Role of CXX
+
+The role of CXX is to capture the language boundary with more fidelity than what
+`extern "C"` is able to represent. You can think of CXX as being a replacement
+for `extern "C"` in a sense.
+
+From this perspective, CXX is a lower level tool than the bindgens. Just as
+bindgen and cbindgen are built on top of `extern "C"`, it makes sense to think
+about higher level tools built on top of CXX. Such a tool might consume a C++
+header and/or Rust module (and/or IDL like Thrift) and emit the corresponding
+safe cxx::bridge language boundary, leveraging CXX's static analysis and
+underlying implementation of that boundary. We are beginning to see this space
+explored by the [autocxx] tool, though nothing yet ready for broad use in the
+way that CXX on its own is.
+
+[autocxx]: https://github.com/google/autocxx
+
+But note in other ways CXX is higher level than the bindgens, with rich support
+for common standard library types. CXX's types serve as an intuitive vocabulary
+for designing a good boundary between components in different languages.
diff --git a/book/src/extern-c++.md b/book/src/extern-c++.md
new file mode 100644
index 0000000..c015b03
--- /dev/null
+++ b/book/src/extern-c++.md
@@ -0,0 +1,315 @@
+{{#title extern "C++" — Rust ♡ C++}}
+# extern "C++"
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        include!("path/to/header.h");
+        include!("path/to/another.h");
+
+        ...
+    }
+}
+```
+
+The `extern "C++"` section of a CXX bridge declares C++ types and signatures to
+be made available to Rust, and gives the paths of the header(s) which contain
+the corresponding C++ declarations.
+
+A bridge module may contain zero or more extern "C++" blocks.
+
+## Opaque C++ types
+
+Type defined in C++ that are made available to Rust, but only behind an
+indirection.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "C++" {
+        # include!("path/to/header.h");
+        #
+        type MyType;
+        type MyOtherType;
+    }
+# }
+```
+
+For example in the ***[Tutorial](tutorial.md)*** we saw `BlobstoreClient`
+implemented as an opaque C++ type. The blobstore client was created in C++ and
+returned to Rust by way of a UniquePtr.
+
+**Mutability:** Unlike extern Rust types and shared types, an extern C++ type is
+not permitted to be passed by plain mutable reference `&mut MyType` across the
+FFI bridge. For mutation support, the bridge is required to use `Pin<&mut
+MyType>`. This is to safeguard against things like mem::swap-ing the contents of
+two mutable references, given that Rust doesn't have information about the size
+of the underlying object and couldn't invoke an appropriate C++ move constructor
+anyway.
+
+**Thread safety:** Be aware that CXX does not assume anything about the thread
+safety of your extern C++ types. In other words the `MyType` etc bindings which
+CXX produces for you in Rust *do not* come with `Send` and `Sync` impls. If you
+are sure that your C++ type satisfies the requirements of `Send` and/or `Sync`
+and need to leverage that fact from Rust, you must provide your own unsafe
+marker trait impls.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+#     extern "C++" {
+#         include!("path/to/header.h");
+#
+#         type MyType;
+#     }
+# }
+#
+/// The C++ implementation of MyType is thread safe.
+unsafe impl Send for ffi::MyType {}
+unsafe impl Sync for ffi::MyType {}
+```
+
+Take care in doing this because thread safety in C++ can be extremely tricky to
+assess if you are coming from a Rust background. For example the
+`BlobstoreClient` type in the tutorial is *not thread safe* despite doing only
+completely innocuous things in its implementation. Concurrent calls to the `tag`
+member function trigger a data race on the `blobs` map.
+
+## Functions and member functions
+
+This largely follows the same principles as ***[extern
+"Rust"](extern-rust.md)*** functions and methods. In particular, any signature
+with a `self` parameter is interpreted as a C++ non-static member function and
+exposed to Rust as a method.
+
+The programmer **does not** need to promise that the signatures they have typed
+in are accurate; that would be unreasonable. CXX performs static assertions that
+the signatures exactly correspond with what is declared in C++. Rather, the
+programmer is only on the hook for things that C++'s static information is not
+precise enough to capture, i.e. things that would only be represented at most by
+comments in the C++ code unintelligible to a static assertion: namely whether
+the C++ function is safe or unsafe to be called from Rust.
+
+**Safety:** the extern "C++" block is responsible for deciding whether to expose
+each signature inside as safe-to-call or unsafe-to-call. If an extern block
+contains at least one safe-to-call signature, it must be written as an `unsafe
+extern` block, which serves as an item level unsafe block to indicate that an
+unchecked safety claim is being made about the contents of the block.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        # include!("path/to/header.h");
+        #
+        fn f();  // safe to call
+    }
+
+    extern "C++" {
+        unsafe fn g();  // unsafe to call
+    }
+}
+```
+
+
+## Reusing existing binding types
+
+Extern C++ types support a syntax for declaring that a Rust binding of the
+correct C++ type already exists outside of the current bridge module. This
+avoids generating a fresh new binding which Rust's type system would consider
+non-interchangeable with the first.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "path::to")]
+mod ffi {
+    extern "C++" {
+        type MyType = crate::existing::MyType;
+    }
+
+    extern "Rust" {
+        fn f(x: &MyType) -> usize;
+    }
+}
+```
+
+In this case rather than producing a unique new Rust type `ffi::MyType` for the
+Rust binding of C++'s `::path::to::MyType`, CXX will reuse the already existing
+binding at `crate::existing::MyType` in expressing the signature of `f` and any
+other uses of `MyType` within the bridge module.
+
+CXX safely validates that `crate::existing::MyType` is in fact a binding for the
+right C++ type `::path::to::MyType` by generating a static assertion based on
+`crate::existing::MyType`'s implementation of [`ExternType`], which is a trait
+automatically implemented by CXX for bindings that it generates but can also be
+manually implemented as described below.
+
+[`ExternType`]: https://docs.rs/cxx/*/cxx/trait.ExternType.html
+
+`ExternType` serves the following two related use cases.
+
+#### Safely unifying occurrences of an extern type across bridges
+
+In the following snippet, two #\[cxx::bridge\] invocations in different files
+(possibly different crates) both contain function signatures involving the same
+C++ type `example::Demo`. If both were written just containing `type Demo;`,
+then both macro expansions would produce their own separate Rust type called
+`Demo` and thus the compiler wouldn't allow us to take the `Demo` returned by
+`file1::ffi::create_demo` and pass it as the `Demo` argument accepted by
+`file2::ffi::take_ref_demo`. Instead, one of the two `Demo`s has been defined as
+an extern type alias of the other, making them the same type in Rust.
+
+```rust,noplayground
+// file1.rs
+#[cxx::bridge(namespace = "example")]
+pub mod ffi {
+    unsafe extern "C++" {
+        type Demo;
+
+        fn create_demo() -> UniquePtr<Demo>;
+    }
+}
+```
+
+```rust,noplayground
+// file2.rs
+#[cxx::bridge(namespace = "example")]
+pub mod ffi {
+    unsafe extern "C++" {
+        type Demo = crate::file1::ffi::Demo;
+
+        fn take_ref_demo(demo: &Demo);
+    }
+}
+```
+
+#### Integrating with bindgen-generated or handwritten unsafe bindings
+
+Handwritten `ExternType` impls make it possible to plug in a data structure
+emitted by bindgen as the definition of a C++ type emitted by CXX.
+
+By writing the unsafe `ExternType` impl, the programmer asserts that the C++
+namespace and type name given in the type id refers to a C++ type that is
+equivalent to Rust type that is the `Self` type of the impl.
+
+```rust,noplayground
+mod folly_sys;  // the bindgen-generated bindings
+
+use cxx::{type_id, ExternType};
+
+unsafe impl ExternType for folly_sys::StringPiece {
+    type Id = type_id!("folly::StringPiece");
+    type Kind = cxx::kind::Opaque;
+}
+
+#[cxx::bridge(namespace = "folly")]
+pub mod ffi {
+    unsafe extern "C++" {
+        include!("rust_cxx_bindings.h");
+
+        type StringPiece = crate::folly_sys::StringPiece;
+
+        fn print_string_piece(s: &StringPiece);
+    }
+}
+
+// Now if we construct a StringPiece or obtain one through one
+// of the bindgen-generated signatures, we are able to pass it
+// along to ffi::print_string_piece.
+```
+
+The `ExternType::Id` associated type encodes a type-level representation of the
+type's C++ namespace and type name. It will always be defined using the
+`type_id!` macro exposed in the cxx crate.
+
+The `ExternType::Kind` associated type will always be either
+[`cxx::kind::Opaque`] or [`cxx::kind::Trivial`] identifying whether a C++ type
+is soundly relocatable by Rust's move semantics. A C++ type is only okay to hold
+and pass around by value in Rust if its [move constructor is trivial] and it has
+no destructor. In CXX, these are called Trivial extern C++ types, while types
+with nontrivial move behavior or a destructor must be considered Opaque and
+handled by Rust only behind an indirection, such as a reference or UniquePtr.
+
+[`cxx::kind::Opaque`]: https://docs.rs/cxx/*/cxx/kind/enum.Opaque.html
+[`cxx::kind::Trivial`]: https://docs.rs/cxx/*/cxx/kind/enum.Trivial.html
+[move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
+
+If you believe your C++ type reflected by the ExternType impl is indeed fine to
+hold by value and move in Rust, you can specify:
+
+```rust,noplayground
+# unsafe impl cxx::ExternType for TypeName {
+#     type Id = cxx::type_id!("name::space::of::TypeName");
+    type Kind = cxx::kind::Trivial;
+# }
+```
+
+which will enable you to pass it into C++ functions by value, return it by
+value, and include it in `struct`s that you have declared to `cxx::bridge`. Your
+claim about the triviality of the C++ type will be checked by a `static_assert`
+in the generated C++ side of the binding.
+
+## Explicit shim trait impls
+
+This is a somewhat niche feature, but important when you need it.
+
+CXX's support for C++'s std::unique\_ptr and std::vector is built on a set of
+internal trait impls connecting the Rust API of UniquePtr and CxxVector to
+underlying template instantiations performed by the C++ compiler.
+
+When reusing a binding type across multiple bridge modules as described in the
+previous section, you may find that your code needs some trait impls which CXX
+hasn't decided to generate.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        include!("path/to/header.h");
+
+        type A;
+        type B;
+
+        // Okay: CXX sees UniquePtr<B> using a type B defined within the same
+        // bridge, and automatically emits the right template instantiations
+        // corresponding to std::unique_ptr<B>.
+        fn get_b() -> UniquePtr<B>;
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    extern "C++" {
+        type A = crate::ffi1::A;
+
+        // Rust trait error: CXX processing this module has no visibility into
+        // whether template instantiations corresponding to std::unique_ptr<A>
+        // have already been emitted by the upstream library, so it does not
+        // emit them here. If the upstream library does not have any signatures
+        // involving UniquePtr<A>, an explicit instantiation of the template
+        // needs to be requested in one module or the other.
+        fn get_a() -> UniquePtr<A>;
+    }
+}
+```
+
+You can request a specific template instantiation at a particular location in
+the Rust crate hierarchy by writing `impl UniquePtr<A> {}` inside of the bridge
+module which defines `A` but does not otherwise contain any use of
+`UniquePtr<A>`.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        include!("path/to/header.h");
+
+        type A;
+        type B;
+
+        fn get_b() -> UniquePtr<B>;
+    }
+
+    impl UniquePtr<A> {}  // explicit instantiation
+}
+```
diff --git a/book/src/extern-rust.md b/book/src/extern-rust.md
new file mode 100644
index 0000000..a9ad8b6
--- /dev/null
+++ b/book/src/extern-rust.md
@@ -0,0 +1,165 @@
+{{#title extern "Rust" — Rust ♡ C++}}
+# extern "Rust"
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+
+    }
+}
+```
+
+The `extern "Rust"` section of a CXX bridge declares Rust types and signatures
+to be made available to C++.
+
+The CXX code generator uses your extern "Rust" section(s) to produce a C++
+header file containing the corresponding C++ declarations. The generated header
+has the same path as the Rust source file containing the bridge, except with a
+`.rs.h` file extension.
+
+A bridge module may contain zero or more extern "Rust" blocks.
+
+## Opaque Rust types
+
+Types defined in Rust that are made available to C++, but only behind an
+indirection.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type MyType;
+        type MyOtherType;
+        type OneMoreType;
+    }
+# }
+```
+
+For example in the ***[Tutorial](tutorial.md)*** we saw `MultiBuf` used in this
+way. Rust code created the `MultiBuf`, passed a `&mut MultiBuf` to C++, and C++
+later passed a `&mut MultiBuf` back across the bridge to Rust.
+
+Another example is the one on the ***[Box\<T\>](binding/box.md)*** page, which
+exposes the Rust standard library's `std::fs::File` to C++ as an opaque type in
+a similar way but with Box as the indirection rather than &mut.
+
+The types named as opaque types (`MyType` etc) refer to types in the `super`
+module, the parent module of the CXX bridge. You can think of an opaque type `T`
+as being like a re-export `use super::T` made available to C++ via the generated
+header.
+
+Opaque types are currently required to be [`Sized`] and [`Unpin`]. In
+particular, a trait object `dyn MyTrait` or slice `[T]` may not be used for an
+opaque Rust type. These restrictions may be lifted in the future.
+
+[`Sized`]: https://doc.rust-lang.org/std/marker/trait.Sized.html
+[`Unpin`]: https://doc.rust-lang.org/std/marker/trait.Unpin.html
+
+For now, types used as extern Rust types are required to be defined by the same
+crate that contains the bridge using them. This restriction may be lifted in the
+future.
+
+The bridge's parent module will contain the appropriate imports or definitions
+for these types.
+
+```rust,noplayground
+use path::to::MyType;
+
+pub struct MyOtherType {
+    ...
+}
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MyType;
+#         type MyOtherType;
+#     }
+# }
+```
+
+## Functions
+
+Rust functions made callable to C++.
+
+Just like for opaque types, these functions refer implicitly to something in
+scope in the `super` module, whether defined there or imported by some `use`
+statement.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        struct MyType;
+        fn f() -> Box<MyType>;
+    }
+}
+
+struct MyType(i32);
+
+fn f() -> Box<MyType> {
+    return Box::new(MyType(1));
+}
+```
+
+Extern Rust function signature may consist of types defined in the bridge,
+primitives, and [any of these additional bindings](bindings.md).
+
+## Methods
+
+Any signature with a `self` parameter is interpreted as a Rust method and
+exposed to C++ as a non-static member function.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type MyType;
+        fn f(&self) -> usize;
+    }
+# }
+```
+
+The `self` parameter may be a shared reference `&self`, an exclusive reference
+`&mut self`, or a pinned reference `self: Pin<&mut Self>`. A by-value `self` is
+not currently supported.
+
+If the surrounding `extern "Rust"` block contains exactly one extern type, that
+type is implicitly the receiver for a `&self` or `&mut self` method. If the
+surrounding block contains *more than one* extern type, a receiver type must be
+provided explicitly for the self parameter, or you can consider splitting into
+multiple extern blocks.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type First;
+        type Second;
+        fn bar(self: &First);
+        fn foo(self: &mut Second);
+    }
+# }
+```
+
+## Functions with explicit lifetimes
+
+An extern Rust function signature is allowed to contain explicit lifetimes but
+in this case the function must be declared unsafe-to-call. This is pretty
+meaningless given we're talking about calls from C++, but at least it draws some
+extra attention from the caller that they may be responsible for upholding some
+atypical lifetime relationship.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MyType;
+        unsafe fn f<'a>(&'a self, s: &str) -> &'a str;
+    }
+}
+```
+
+Bounds on a lifetime (like `<'a, 'b: 'a>`) are not currently supported. Nor are
+type parameters or where-clauses.
diff --git a/book/src/index.md b/book/src/index.md
new file mode 100644
index 0000000..7b03e7e
--- /dev/null
+++ b/book/src/index.md
@@ -0,0 +1,83 @@
+<div class="badges">
+<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" alt="docs-rs" height="28" class="badge"></a>
+</div>
+
+# CXX — safe interop between Rust and C++
+
+This library provides a safe mechanism for calling C++ code from Rust and Rust
+code from C++. It carves out a regime of commonality where Rust and C++ are
+semantically very similar and guides the programmer to express their language
+boundary effectively within this regime. CXX fills in the low level stuff so
+that you get a safe binding, preventing the pitfalls of doing a foreign function
+interface over unsafe C-style signatures.
+
+<div style="height:226px;padding:34px 0 24px">
+<object type="image/svg+xml" data="overview.svg"></object>
+</div>
+
+From a high level description of the language boundary, CXX uses static analysis
+of the types and function signatures to protect both Rust's and C++'s
+invariants. Then it uses a pair of code generators to implement the boundary
+efficiently on both sides together with any necessary static assertions for
+later in the build process to verify correctness.
+
+The resulting FFI bridge operates at zero or negligible overhead, i.e. no
+copying, no serialization, no memory allocation, no runtime checks needed.
+
+The FFI signatures are able to use native data structures from whichever side
+they please. In addition, CXX provides builtin bindings for key standard library
+types like strings, vectors, Box, unique\_ptr, etc to expose an idiomatic API on
+those types to the other language.
+
+## Example
+
+In this example we are writing a Rust application that calls a C++ client of a
+large-file blobstore service. The blobstore supports a `put` operation for a
+discontiguous buffer upload. For example we might be uploading snapshots of a
+circular buffer which would tend to consist of 2 pieces, or fragments of a file
+spread across memory for some other reason (like a rope data structure).
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MultiBuf;
+
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
+    }
+}
+```
+
+Now we simply provide Rust definitions of all the things in the `extern "Rust"`
+block and C++ definitions of all the things in the `extern "C++"` block, and get
+to call back and forth safely.
+
+The [***Tutorial***](tutorial.md) chapter walks through a fleshed out version of
+this blobstore example in full detail, including all of the Rust code and all of
+the C++ code. The code is also provided in runnable form in the *demo* directory
+of <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
+directory.
+
+- [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
+- [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
+- [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
+
+The key takeaway, which is enabled by the CXX library, is that the Rust code in
+main.rs is 100% ordinary safe Rust code working idiomatically with Rust types
+while the C++ code in blobstore.cc is 100% ordinary C++ code working
+idiomatically with C++ types. The Rust code feels like Rust and the C++ code
+feels like C++, not like C-style "FFI glue".
+
+<br>
+
+***Chapter outline:** See the hamburger menu in the top left if you are on a
+small screen and it didn't open with a sidebar by default.*
diff --git a/book/src/overview.svg b/book/src/overview.svg
new file mode 100644
index 0000000..850e034
--- /dev/null
+++ b/book/src/overview.svg
@@ -0,0 +1,131 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224">
+    <style>line, path, circle,rect,polygon {
+                          stroke: black;
+                          stroke-width: 2;
+                          stroke-opacity: 1;
+                          fill-opacity: 1;
+                          stroke-linecap: round;
+                          stroke-linejoin: miter;
+                        }
+
+                    text {
+                        fill: black;
+                        }
+                        rect.backdrop{
+                            stroke: none;
+                            fill: white;
+                            fill-opacity: 0;
+                        }
+                        .broken{
+                            stroke-dasharray: 8;
+                        }
+                        .filled{
+                            fill: black;
+                        }
+                        .bg_filled{
+                            fill: white;
+                        }
+                        .nofill{
+                            fill: white;
+                            fill-opacity: 0;
+                        }
+
+                        text {
+                         font-family: monospace;
+                         font-size: 14px;
+                        }
+
+                        .end_marked_arrow{
+                            marker-end: url(#arrow);
+                         }
+                        .start_marked_arrow{
+                            marker-start: url(#arrow);
+                         }
+
+                        .end_marked_diamond{
+                            marker-end: url(#diamond);
+                         }
+                        .start_marked_diamond{
+                            marker-start: url(#diamond);
+                         }
+
+                        .end_marked_circle{
+                            marker-end: url(#circle);
+                         }
+                        .start_marked_circle{
+                            marker-start: url(#circle);
+                         }
+
+                        .end_marked_open_circle{
+                            marker-end: url(#open_circle);
+                         }
+                        .start_marked_open_circle{
+                            marker-start: url(#open_circle);
+                         }
+
+                        .end_marked_big_open_circle{
+                            marker-end: url(#big_open_circle);
+                         }
+                        .start_marked_big_open_circle{
+                            marker-start: url(#big_open_circle);
+                         }
+
+                         
+                        </style>
+    <defs>
+        <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,0 0,4 4,2 0,0"></polygon>
+        </marker>
+        <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon>
+        </marker>
+        <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="filled"></circle>
+        </marker>
+        <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="bg_filled"></circle>
+        </marker>
+        <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="3" class="bg_filled"></circle>
+        </marker>
+    </defs>
+    <rect class="backdrop" x="0" y="0" width="696" height="224"></rect>
+    <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect>
+    <text x="162" y="188" >Rust bindings</text>
+    <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect>
+    <text x="426" y="188" >C++ bindings</text>
+    <text x="272" y="28" >#[cxx::bridge] mod</text>
+    <text x="250" y="44" >description of boundary</text>
+    <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
+    <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
+    <text x="74" y="140" >Safe</text>
+    <text x="34" y="156" >straightforward</text>
+    <text x="530" y="156" >Straightforward</text>
+    <polygon points="48,180 40,184 48,188" class="filled"></polygon>
+    <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line>
+    <polygon points="296,180 288,184 296,188" class="filled"></polygon>
+    <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line>
+    <polygon points="552,180 544,184 552,188" class="filled"></polygon>
+    <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line>
+    <text x="2" y="188" >Rust</text>
+    <text x="2" y="204" >code</text>
+    <text x="658" y="204" >code</text>
+    <text x="202" y="108" >Macro expansion</text>
+    <text x="370" y="108" >Code generation</text>
+    <text x="58" y="172" >Rust APIs</text>
+    <text x="298" y="172" >Hidden C ABI</text>
+    <text x="562" y="172" >C++ APIs</text>
+    <text x="658" y="188" >C++</text>
+    <g>
+        <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path>
+        <line x1="228" y1="8" x2="468" y2="8" class="solid"></line>
+        <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path>
+        <line x1="220" y1="16" x2="220" y2="48" class="solid"></line>
+        <line x1="476" y1="16" x2="476" y2="48" class="solid"></line>
+        <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path>
+        <line x1="228" y1="56" x2="468" y2="56" class="solid"></line>
+        <line x1="348" y1="56" x2="348" y2="120" class="solid"></line>
+        <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path>
+        <line x1="220" y1="120" x2="476" y2="120" class="solid"></line>
+    </g>
+</svg>
diff --git a/book/src/reference.md b/book/src/reference.md
new file mode 100644
index 0000000..62ca35c
--- /dev/null
+++ b/book/src/reference.md
@@ -0,0 +1,29 @@
+{{#title The bridge module — Rust ♡ C++}}
+# The bridge module reference
+
+The ***[Core concepts](concepts.md)*** in chapter 2 covered the high level model
+that CXX uses to represent a language boundary. This chapter builds on that one
+to document an exhaustive reference on the syntax and functionality of
+\#\[cxx::bridge\].
+
+- ***[extern "Rust"](extern-rust.md)*** &mdash; exposing opaque Rust types, Rust
+  functions, Rust methods to C++; functions with lifetimes.
+
+- ***[extern "C++"](extern-c++.md)*** &mdash; binding opaque C++ types, C++
+  functions, C++ member functions; sharing an opaque type definition across
+  multiple bridge modules or different crates; using bindgen-generated data
+  structures across a CXX bridge; Rust orphan-rule-compatible way to request
+  that particular glue code be emitted in a specific bridge module.
+
+- ***[Shared types](shared.md)*** &mdash; shared structs; shared enums; using
+  Rust as source of truth vs C++ as source of truth.
+
+- ***[Attributes](attributes.md)*** &mdash; working with namespaces; giving
+  functions a different name in their non-native language.
+
+- ***[Async functions](async.md)*** &mdash; integrating async C++ with async
+  Rust.
+
+- ***[Error handling](binding/result.md)*** &mdash; representing fallibility on
+  the language boundary; accessing a Rust error message from C++; customizing
+  the set of caught exceptions and their conversion to a Rust error message.
diff --git a/book/src/shared.md b/book/src/shared.md
new file mode 100644
index 0000000..09465fe
--- /dev/null
+++ b/book/src/shared.md
@@ -0,0 +1,181 @@
+{{#title Shared types — Rust ♡ C++}}
+# Shared types
+
+Shared types enable *both* languages to have visibility into the internals of a
+type. This is in contrast to opaque Rust types and opaque C++ types, for which
+only one side gets to manipulate the internals.
+
+Unlike opaque types, the FFI bridge is allowed to pass and return shared types
+by value.
+
+The order in which shared types are written is not important. C++ is order
+sensitive but CXX will topologically sort and forward-declare your types as
+necessary.
+
+## Shared structs and enums
+
+For enums, only C-like a.k.a. unit variants are currently supported.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    struct PlayingCard {
+        suit: Suit,
+        value: u8,  // A=1, J=11, Q=12, K=13
+    }
+
+    enum Suit {
+        Clubs,
+        Diamonds,
+        Hearts,
+        Spades,
+    }
+
+    unsafe extern "C++" {
+        fn deck() -> Vec<PlayingCard>;
+        fn sort(cards: &mut Vec<PlayingCard>);
+    }
+}
+```
+
+## The generated data structures
+
+Shared structs compile to an aggregate-initialization compatible C++ struct.
+
+Shared enums compile to a C++ `enum class` with a sufficiently sized integral
+base type decided by CXX.
+
+```cpp
+// generated header
+
+struct PlayingCard final {
+  Suit suit;
+  uint8_t value;
+};
+
+enum class Suit : uint8_t {
+  Clubs = 0,
+  Diamonds = 1,
+  Hearts = 2,
+  Spades = 3,
+};
+```
+
+Because it is not UB in C++ for an `enum class` to hold a value different from
+all of the listed variants, we use a Rust representation for shared enums that
+is compatible with this. The API you'll get is something like:
+
+```rust,noplayground
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[repr(transparent)]
+pub struct Suit {
+    pub repr: u8,
+}
+#[allow(non_upper_case_globals)]
+impl Suit {
+    pub const Clubs: Self = Suit { repr: 0 };
+    pub const Diamonds: Self = Suit { repr: 1 };
+    pub const Hearts: Self = Suit { repr: 2 };
+    pub const Spades: Self = Suit { repr: 3 };
+}
+```
+
+Notice you're free to treat the enum as an integer in Rust code via the public
+`repr` field.
+
+Pattern matching with `match` still works but will require you to write wildcard
+arms to handle the situation of an enum value that is not one of the listed
+variants.
+
+```rust,noplayground
+fn main() {
+    let suit: Suit = /*...*/;
+    match suit {
+        Suit::Clubs => ...,
+        Suit::Diamonds => ...,
+        Suit::Hearts => ...,
+        Suit::Spades => ...,
+        _ => ...,  // fallback arm
+    }
+}
+```
+
+## Enum discriminants
+
+You may provide explicit discriminants for some or all of the enum variants, in
+which case those numbers will be propagated into the generated C++ `enum class`.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    enum SmallPrime {
+        Two = 2,
+        Three = 3,
+        Five = 5,
+        Seven = 7,
+    }
+}
+```
+
+Variants without an explicit discriminant are assigned the previous discriminant
+plus 1. If the first variant has not been given an explicit discriminant, it is
+assigned discriminant 0.
+
+By default CXX represents your enum using the smallest integer type capable of
+fitting all the discriminants (whether explicit or implicit). If you need a
+different representation for reasons, provide a `repr` attribute.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    #[repr(i32)]
+    enum Enum {
+        Zero,
+        One,
+        Five = 5,
+        Six,
+    }
+}
+```
+
+```cpp
+// generated header
+
+enum class Enum : int32_t {
+  Zero = 0,
+  One = 1,
+  Five = 5,
+  Six = 6,
+};
+```
+
+## Extern enums
+
+If you need to interoperate with an already existing enum for which an existing
+C++ definition is the source of truth, make sure that definition is provided by
+some header in the bridge and then declare your enum *additionally* as an extern
+C++ type.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    enum Enum {
+        Yes,
+        No,
+    }
+
+    extern "C++" {
+        include!("path/to/the/header.h");
+        type Enum;
+    }
+}
+```
+
+CXX will recognize this pattern and, instead of generating a C++ definition of
+the enum, will instead generate C++ static assertions asserting that the
+variants and discriminant values and integer representation written in Rust all
+correctly match the existing C++ enum definition.
+
+Extern enums support all the same features as ordinary shared enums (explicit
+discriminants, repr). Again, CXX will static assert that all of those things you
+wrote are correct.
diff --git a/book/src/tutorial.md b/book/src/tutorial.md
new file mode 100644
index 0000000..a375ea0
--- /dev/null
+++ b/book/src/tutorial.md
@@ -0,0 +1,687 @@
+{{#title Tutorial — Rust ♡ C++}}
+# Tutorial: CXX blobstore client
+
+This example walks through a Rust application that calls into a C++ client of a
+blobstore service. In fact we'll see calls going in both directions: Rust to C++
+as well as C++ to Rust. For your own use case it may be that you need just one
+of these directions.
+
+All of the code involved in the example is shown on this page, but it's also
+provided in runnable form in the *demo* directory of
+<https://github.com/dtolnay/cxx>. To try it out directly, run `cargo run` from
+that directory.
+
+This tutorial assumes you've read briefly about **shared structs**, **opaque
+types**, and **functions** in the [*Core concepts*](concepts.md) page.
+
+## Creating the project
+
+We'll use Cargo, which is the build system commonly used by open source Rust
+projects. (CXX works with other build systems too; refer to chapter 5.)
+
+Create a blank Cargo project: `mkdir cxx-demo`; `cd cxx-demo`; `cargo init`.
+
+Edit the Cargo.toml to add a dependency on the `cxx` crate:
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "cxx-demo"
+# version = "0.1.0"
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+```
+
+We'll revisit this Cargo.toml later when we get to compiling some C++ code.
+
+## Defining the language boundary
+
+CXX relies on a description of the function signatures that will be exposed from
+each language to the other. You provide this description using `extern` blocks
+in a Rust module annotated with the `#[cxx::bridge]` attribute macro.
+
+We'll open with just the following at the top of src/main.rs and walk through
+each item in detail.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+
+}
+#
+# fn main() {}
+```
+
+The contents of this module will be everything that needs to be agreed upon by
+both sides of the FFI boundary.
+
+## Calling a C++ function from Rust
+
+Let's obtain an instance of the C++ blobstore client, a class `BlobstoreClient`
+defined in C++.
+
+We'll treat `BlobstoreClient` as an *opaque type* in CXX's classification so
+that Rust does not need to assume anything about its implementation, not even
+its size or alignment. In general, a C++ type might have a move-constructor
+which is incompatible with Rust's move semantics, or may hold internal
+references which cannot be modeled by Rust's borrowing system. Though there are
+alternatives, the easiest way to not care about any such thing on an FFI
+boundary is to require no knowledge about a type by treating it as opaque.
+
+Opaque types may only be manipulated behind an indirection such as a reference
+`&`, a Rust `Box`, or a `UniquePtr` (Rust binding of `std::unique_ptr`). We'll
+add a function through which C++ can return a `std::unique_ptr<BlobstoreClient>`
+to Rust.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("cxx-demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+    }
+}
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+}
+```
+
+The nature of `unsafe` extern blocks is clarified in more detail in the
+[*extern "C++"*](extern-c++.md) chapter. In brief: the programmer is **not**
+promising that the signatures they have typed in are accurate; that would be
+unreasonable. CXX performs static assertions that the signatures exactly match
+what is declared in C++. Rather, the programmer is only on the hook for things
+that C++'s semantics are not precise enough to capture, i.e. things that would
+only be represented at most by comments in the C++ code. In this case, it's
+whether `new_blobstore_client` is safe or unsafe to call. If that function said
+something like "must be called at most once or we'll stomp yer memery", Rust
+would instead want to expose it as `unsafe fn new_blobstore_client`, this time
+inside a safe `extern "C++"` block because the programmer is no longer on the
+hook for any safety claim about the signature.
+
+If you build this file right now with `cargo build`, it won't build because we
+haven't written a C++ implementation of `new_blobstore_client` nor instructed
+Cargo about how to link it into the resulting binary. You'll see an error from
+the linker like this:
+
+```console
+error: linking with `cc` failed: exit code: 1
+ |
+ = /bin/ld: target/debug/deps/cxx-demo-7cb7fddf3d67d880.rcgu.o: in function `cxx_demo::ffi::new_blobstore_client':
+   src/main.rs:1: undefined reference to `cxxbridge1$new_blobstore_client'
+   collect2: error: ld returned 1 exit status
+```
+
+## Adding in the C++ code
+
+In CXX's integration with Cargo, all #include paths begin with a crate name by
+default (when not explicitly selected otherwise by a crate; see
+`CFG.include_prefix` in chapter 5). That's why we see
+`include!("cxx-demo/include/blobstore.h")` above &mdash; we'll be putting the
+C++ header at relative path `include/blobstore.h` within the Rust crate. If your
+crate is named something other than `cxx-demo` according to the `name` field in
+Cargo.toml, you will need to use that name everywhere in place of `cxx-demo`
+throughout this tutorial.
+
+```cpp
+// include/blobstore.h
+
+#pragma once
+#include <memory>
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+};
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp
+// src/blobstore.cc
+
+#include "cxx-demo/include/blobstore.h"
+
+BlobstoreClient::BlobstoreClient() {}
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::unique_ptr<BlobstoreClient>(new BlobstoreClient());
+}
+```
+
+Using `std::make_unique` would work too, as long as you pass `-std=c++14` to the
+C++ compiler as described later on.
+
+The placement in *include/* and *src/* is not significant; you can place C++
+code anywhere else in the crate as long as you use the right paths throughout
+the tutorial.
+
+Be aware that *CXX does not look at any of these files.* You're free to put
+arbitrary C++ code in here, #include your own libraries, etc. All we do is emit
+static assertions against what you provide in the headers.
+
+## Compiling the C++ code with Cargo
+
+Cargo has a [build scripts] feature suitable for compiling non-Rust code.
+
+We need to introduce a new build-time dependency on CXX's C++ code generator in
+Cargo.toml:
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "cxx-demo"
+# version = "0.1.0"
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+
+[build-dependencies]
+cxx-build = "1.0"
+```
+
+Then add a build.rs build script adjacent to Cargo.toml to run the cxx-build
+code generator and C++ compiler. The relevant arguments are the path to the Rust
+source file containing the cxx::bridge language boundary definition, and the
+paths to any additional C++ source files to be compiled during the Rust crate's
+build.
+
+```rust,noplayground
+// build.rs
+
+fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/blobstore.cc")
+        .compile("cxx-demo");
+}
+```
+
+This build.rs would also be where you set up C++ compiler flags, for example if
+you'd like to have access to `std::make_unique` from C++14. See the page on
+***[Cargo-based builds](build/cargo.md)*** for more details about CXX's Cargo
+integration.
+
+```rust,noplayground
+# // build.rs
+#
+# fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/blobstore.cc")
+        .flag_if_supported("-std=c++14")
+        .compile("cxx-demo");
+# }
+```
+
+[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
+
+The project should now build and run successfully, though not do anything useful
+yet.
+
+```console
+cxx-demo$  cargo run
+  Compiling cxx-demo v0.1.0
+  Finished dev [unoptimized + debuginfo] target(s) in 0.34s
+  Running `target/debug/cxx-demo`
+
+cxx-demo$
+```
+
+## Calling a Rust function from C++
+
+Our C++ blobstore supports a `put` operation for a discontiguous buffer upload.
+For example we might be uploading snapshots of a circular buffer which would
+tend to consist of 2 pieces, or fragments of a file spread across memory for
+some other reason (like a rope data structure).
+
+We'll express this by handing off an iterator over contiguous borrowed chunks.
+This loosely resembles the API of the widely used `bytes` crate's `Buf` trait.
+During a `put`, we'll make C++ call back into Rust to obtain contiguous chunks
+of the upload (all with no copying or allocation on the language boundary). In
+reality the C++ client might contain some sophisticated batching of chunks
+and/or parallel uploading that all of this ties into.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MultiBuf;
+
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        include!("cxx-demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+    }
+}
+#
+# fn main() {
+#     let client = ffi::new_blobstore_client();
+# }
+```
+
+Any signature having a `self` parameter (the Rust name for C++'s `this`) is
+considered a method / non-static member function. If there is only one `type` in
+the surrounding extern block, it'll be a method of that type. If there is more
+than one `type`, you can disambiguate which one a method belongs to by writing
+`self: &BlobstoreClient` in the argument list.
+
+As usual, now we need to provide Rust definitions of everything declared by the
+`extern "Rust"` block and a C++ definition of the new signature declared by the
+`extern "C++"` block.
+
+```rust,noplayground
+// src/main.rs
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#     }
+# }
+
+// An iterator over contiguous chunks of a discontiguous file object. Toy
+// implementation uses a Vec<Vec<u8>> but in reality this might be iterating
+// over some more complex Rust data structure like a rope, or maybe loading
+// chunks lazily from somewhere.
+pub struct MultiBuf {
+    chunks: Vec<Vec<u8>>,
+    pos: usize,
+}
+
+pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+    let next = buf.chunks.get(buf.pos);
+    buf.pos += 1;
+    next.map(Vec::as_slice).unwrap_or(&[])
+}
+#
+# fn main() {
+#     let client = ffi::new_blobstore_client();
+# }
+```
+
+```cpp,hidelines
+// include/blobstore.h
+
+# #pragma once
+# #include <memory>
+#
+struct MultiBuf;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+};
+#
+#std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+In blobstore.cc we're able to call the Rust `next_chunk` function, exposed to
+C++ by a header `main.rs.h` generated by the CXX code generator. In CXX's Cargo
+integration this generated header has a path containing the crate name, the
+relative path of the Rust source file within the crate, and a `.rs.h` extension.
+
+```cpp,hidelines
+// src/blobstore.cc
+
+##include "cxx-demo/include/blobstore.h"
+##include "cxx-demo/src/main.rs.h"
+##include <functional>
+#
+# BlobstoreClient::BlobstoreClient() {}
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+#   return std::make_unique<BlobstoreClient>();
+# }
+
+// Upload a new blob and return a blobid that serves as a handle to the blob.
+uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+  // Traverse the caller's chunk iterator.
+  std::string contents;
+  while (true) {
+    auto chunk = next_chunk(buf);
+    if (chunk.size() == 0) {
+      break;
+    }
+    contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+  }
+
+  // Pretend we did something useful to persist the data.
+  auto blobid = std::hash<std::string>{}(contents);
+  return blobid;
+}
+```
+
+This is now ready to use. :)
+
+```rust,noplayground
+// src/main.rs
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#     }
+# }
+#
+# pub struct MultiBuf {
+#     chunks: Vec<Vec<u8>>,
+#     pos: usize,
+# }
+# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+#     let next = buf.chunks.get(buf.pos);
+#     buf.pos += 1;
+#     next.map(Vec::as_slice).unwrap_or(&[])
+# }
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+}
+```
+
+```console
+cxx-demo$  cargo run
+  Compiling cxx-demo v0.1.0
+  Finished dev [unoptimized + debuginfo] target(s) in 0.41s
+  Running `target/debug/cxx-demo`
+
+blobid = 9851996977040795552
+```
+
+## Interlude: What gets generated?
+
+For the curious, it's easy to look behind the scenes at what CXX has done to
+make these function calls work. You shouldn't need to do this during normal
+usage of CXX, but for the purpose of this tutorial it can be educative.
+
+CXX comprises *two* code generators: a Rust one (which is the cxx::bridge
+attribute procedural macro) and a C++ one.
+
+### Rust generated code
+
+It's easiest to view the output of the procedural macro by installing
+[cargo-expand]. Then run `cargo expand ::ffi` to macro-expand the `mod ffi`
+module.
+
+[cargo-expand]: https://github.com/dtolnay/cargo-expand
+
+```console
+cxx-demo$  cargo install cargo-expand
+cxx-demo$  cargo expand ::ffi
+```
+
+You'll see some deeply unpleasant code involving `#[repr(C)]`, `#[link_name]`,
+and `#[export_name]`.
+
+### C++ generated code
+
+For debugging convenience, `cxx_build` links all generated C++ code into Cargo's
+target directory under *target/cxxbridge/*.
+
+```console
+cxx-demo$  exa -T target/cxxbridge/
+target/cxxbridge
+├── cxx-demo
+│  └── src
+│     ├── main.rs.cc -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/sources/cxx-demo/src/main.rs.cc
+│     └── main.rs.h -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/include/cxx-demo/src/main.rs.h
+└── rust
+   └── cxx.h -> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cxx-1.0.0/include/cxx.h
+```
+
+In those files you'll see declarations or templates of any CXX Rust types
+present in your language boundary (like `rust::Slice<T>` for `&[T]`) and `extern
+"C"` signatures corresponding to your extern functions.
+
+If it fits your workflow better, the CXX C++ code generator is also available as
+a standalone executable which outputs generated code to stdout.
+
+```console
+cxx-demo$  cargo install cxxbridge-cmd
+cxx-demo$  cxxbridge src/main.rs
+```
+
+## Shared data structures
+
+So far the calls in both directions above only used **opaque types**, not
+**shared structs**.
+
+Shared structs are data structures whose complete definition is visible to both
+languages, making it possible to pass them by value across the language
+boundary. Shared structs translate to a C++ aggregate-initialization compatible
+struct exactly matching the layout of the Rust one.
+
+As the last step of this demo, we'll use a shared struct `BlobMetadata` to pass
+metadata about blobs between our Rust application and C++ blobstore client.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
+    }
+
+    extern "Rust" {
+        // ...
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        // ...
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
+    }
+}
+#
+# pub struct MultiBuf {
+#     chunks: Vec<Vec<u8>>,
+#     pos: usize,
+# }
+# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+#     let next = buf.chunks.get(buf.pos);
+#     buf.pos += 1;
+#     next.map(Vec::as_slice).unwrap_or(&[])
+# }
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+
+    // Add a tag.
+    client.tag(blobid, "rust");
+
+    // Read back the tags.
+    let metadata = client.metadata(blobid);
+    println!("tags = {:?}", metadata.tags);
+}
+```
+
+```cpp,hidelines
+// include/blobstore.h
+#
+# #pragma once
+# #include "rust/cxx.h"
+# #include <memory>
+
+struct MultiBuf;
+struct BlobMetadata;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+  void tag(uint64_t blobid, rust::Str tag) const;
+  BlobMetadata metadata(uint64_t blobid) const;
+
+private:
+  class impl;
+  std::shared_ptr<impl> impl;
+};
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp,hidelines
+// src/blobstore.cc
+
+##include "cxx-demo/include/blobstore.h"
+##include "cxx-demo/src/main.rs.h"
+##include <algorithm>
+##include <functional>
+##include <set>
+##include <string>
+##include <unordered_map>
+
+// Toy implementation of an in-memory blobstore.
+//
+// In reality the implementation of BlobstoreClient could be a large
+// complex C++ library.
+class BlobstoreClient::impl {
+  friend BlobstoreClient;
+  using Blob = struct {
+    std::string data;
+    std::set<std::string> tags;
+  };
+  std::unordered_map<uint64_t, Blob> blobs;
+};
+
+BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {}
+#
+# // Upload a new blob and return a blobid that serves as a handle to the blob.
+# uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+#   // Traverse the caller's chunk iterator.
+#   std::string contents;
+#   while (true) {
+#     auto chunk = next_chunk(buf);
+#     if (chunk.size() == 0) {
+#       break;
+#     }
+#     contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+#   }
+#
+#   // Insert into map and provide caller the handle.
+#   auto blobid = std::hash<std::string>{}(contents);
+#   impl->blobs[blobid] = {std::move(contents), {}};
+#   return blobid;
+# }
+
+// Add tag to an existing blob.
+void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {
+  impl->blobs[blobid].tags.emplace(tag);
+}
+
+// Retrieve metadata about a blob.
+BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
+  BlobMetadata metadata{};
+  auto blob = impl->blobs.find(blobid);
+  if (blob != impl->blobs.end()) {
+    metadata.size = blob->second.data.size();
+    std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
+                  [&](auto &t) { metadata.tags.emplace_back(t); });
+  }
+  return metadata;
+}
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+#   return std::make_unique<BlobstoreClient>();
+# }
+```
+
+```console
+cxx-demo$  cargo run
+  Running `target/debug/cxx-demo`
+
+blobid = 9851996977040795552
+tags = ["rust"]
+```
+
+*You've now seen all the code involved in the tutorial. It's available all
+together in runnable form in the* demo *directory of
+<https://github.com/dtolnay/cxx>. You can run it directly without stepping
+through the steps above by running `cargo run` from that directory.*
+
+<br>
+
+# Takeaways
+
+The key contribution of CXX is it gives you Rust&ndash;C++ interop in which
+*all* of the Rust side of the code you write *really* looks like you are just
+writing normal Rust, and the C++ side *really* looks like you are just writing
+normal C++.
+
+You've seen in this tutorial that none of the code involved feels like C or like
+the usual perilous "FFI glue" prone to leaks or memory safety flaws.
+
+An expressive system of opaque types, shared types, and key standard library
+type bindings enables API design on the language boundary that captures the
+proper ownership and borrowing contracts of the interface.
+
+CXX plays to the strengths of the Rust type system *and* C++ type system *and*
+the programmer's intuitions. An individual working on the C++ side without a
+Rust background, or the Rust side without a C++ background, will be able to
+apply all their usual intuitions and best practices about development in their
+language to maintain a correct FFI.
+
+<br><br>

From f47403fccd1222f407fe316aad1a5a3cb0c777cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:22:44 +0000
Subject: [PATCH 1442/2232] Customize book 404 page


---

diff --git a/book/src/404.md b/book/src/404.md
new file mode 100644
index 0000000..c5b71f2
--- /dev/null
+++ b/book/src/404.md
@@ -0,0 +1,5 @@
+### Whoops, this page doesn’t exist :-(
+
+<br>
+
+<img src="https://www.rust-lang.org/static/images/ferris-error.png" alt="ferris" width="325">

From 123f70aaaca572104ba10961f24e559e21b71ebe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:29:58 +0000
Subject: [PATCH 1443/2232] Merge pull request #482 from dtolnay/book


Book content
---

diff --git a/book/book.toml b/book/book.toml
index 0644e05..066f3a6 100644
--- a/book/book.toml
+++ b/book/book.toml
@@ -16,3 +16,7 @@ cname = "cxx.rs"
 git-repository-url = "https://github.com/dtolnay/cxx"
 playground = { copyable = false }
 print = { enable = false }
+
+[output.html.redirect]
+"binding/index.html" = "../bindings.html"
+"build/index.html" = "../building.html"
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index f3fa924..31cbb46 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -1,3 +1,35 @@
 # Summary
 
-[Rust ❤️ C++](about.md)
+- [Rust ❤️ C++](index.md)
+
+- [Core concepts](concepts.md)
+
+- [Tutorial](tutorial.md)
+
+- [Other Rust&ndash;C++ interop tools](context.md)
+
+- [Multi-language build system options](building.md)
+    - [Cargo](build/cargo.md)
+    - [Bazel](build/bazel.md)
+    - [CMake](build/cmake.md)
+    - [More...](build/other.md)
+
+- [Reference: the bridge module](reference.md)
+    - [extern "Rust"](extern-rust.md)
+    - [extern "C++"](extern-c++.md)
+    - [Shared types](shared.md)
+    - [Attributes](attributes.md)
+    - [Async functions](async.md)
+    - [Error handling](binding/result.md)
+
+- [Reference: built-in bindings](bindings.md)
+    - [String &mdash; rust::String](binding/string.md)
+    - [&str &mdash; rust::Str](binding/str.md)
+    - [&&#91;T&#93; &mdash; rust::Slice\<const T\>](binding/slice.md)
+    - [CxxString &mdash; std::string](binding/cxxstring.md)
+    - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
+    - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
+    - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
+    - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
+    - [Function pointers](binding/fn.md)
+    - [Result\<T\>](binding/result.md)
diff --git a/book/src/about.md b/book/src/about.md
deleted file mode 100644
index 6e63bf5..0000000
--- a/book/src/about.md
+++ /dev/null
@@ -1 +0,0 @@
-### Coming soon
diff --git a/book/src/async.md b/book/src/async.md
new file mode 100644
index 0000000..7574a22
--- /dev/null
+++ b/book/src/async.md
@@ -0,0 +1,86 @@
+{{#title Async functions — Rust ♡ C++}}
+# Async functions
+
+Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up)
+but is not implemented yet in the current release. We are aiming for an
+implementation that is as easy as:
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        async fn doThing(arg: Arg) -> Ret;
+    }
+}
+```
+
+```cpp,hidelines
+rust::Future<Ret> doThing(Arg arg) {
+  auto v1 = co_await f();
+  auto v2 = co_await g(arg);
+  co_return v1 + v2;
+}
+```
+
+## Workaround
+
+For now the recommended approach is to handle the return codepath over a oneshot
+channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust
+type on the FFI.
+
+[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html
+
+```rust,noplayground
+// bridge.rs
+
+use futures::channel::oneshot;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type DoThingContext;
+    }
+
+    unsafe extern "C++" {
+        include!("path/to/bridge_shim.h");
+
+        fn shim_doThing(
+            arg: Arg,
+            done: fn(Box<DoThingContext>, ret: Ret),
+            ctx: Box<DoThingContext>,
+        );
+    }
+}
+
+struct DoThingContext(oneshot::Sender<Ret>);
+
+pub async fn do_thing(arg: Arg) -> Ret {
+    let (tx, rx) = oneshot::channel();
+    let context = Box::new(DoThingContext(tx));
+
+    ffi::shim_doThing(
+        arg,
+        |tx, ret| { let _ = tx.0.send(ret); },
+        context,
+    );
+
+    rx.await.unwrap()
+}
+```
+
+```cpp
+// bridge_shim.cc
+
+#include "path/to/bridge.rs.h"
+#include "rust/cxx.h"
+
+void shim_doThing(
+    Arg arg,
+    rust::Fn<void(rust::Box<DoThingContext> ctx, Ret ret)> done,
+    rust::Box<DoThingContext> ctx) noexcept {
+  doThing(arg)
+      .then([done, ctx(std::move(ctx))](auto &&res) mutable {
+        (*done)(std::move(ctx), std::move(res));
+      });
+}
+```
diff --git a/book/src/attributes.md b/book/src/attributes.md
new file mode 100644
index 0000000..b41515a
--- /dev/null
+++ b/book/src/attributes.md
@@ -0,0 +1,74 @@
+{{#title Attributes — Rust ♡ C++}}
+# Attributes
+
+## namespace
+
+The top-level cxx::bridge attribute macro takes an optional `namespace` argument
+to control the C++ namespace into which to emit extern Rust items and the
+namespace in which to expect to find the extern C++ items.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "path::of::my::company")]
+mod ffi {
+    extern "Rust" {
+        type MyType;  // emitted to path::of::my::company::MyType
+    }
+
+    extern "C++" {
+        type TheirType;  // refers to path::of::my::company::TheirType
+    }
+}
+```
+
+Additionally, a `#[namespace = "..."]` attribute may be used inside the bridge
+module on any extern block or individual item. An item will inherit the
+namespace specified on its surrounding extern block if any, otherwise the
+namespace specified with the top level cxx::bridge attribute if any, otherwise
+the global namespace.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "third_priority")]
+mod ffi {
+    #[namespace = "second_priority"]
+    extern "Rust" {
+        fn f();
+
+        #[namespace = "first_priority"]
+        fn g();
+    }
+
+    extern "Rust" {
+        fn h();
+    }
+}
+```
+
+The above would result in functions `::second_priority::f`,
+`::first_priority::g`, `::third_priority::h`.
+
+## rust\_name, cxx\_name
+
+Sometimes you want the Rust name of a function to differ from its C++ name.
+Importantly, this enables binding multiple overloads of the same C++ function
+name using distinct Rust names.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        #[rust_name = "i32_overloaded_function"]
+        fn cOverloadedFunction(x: i32) -> String;
+        #[rust_name = "str_overloaded_function"]
+        fn cOverloadedFunction(x: &str) -> String;
+    }
+}
+```
+
+The `#[rust_name = "..."]` attribute replaces the name that Rust should use for
+this function, and an analogous `#[cxx_name = "..."]` attribute replaces the
+name that C++ should use.
+
+Either of the two attributes may be used on extern "Rust" as well as extern
+"C++" functions, according to which one you find clearer in context.
+
+Support for renaming type names and enum variants is not implemented yet.
diff --git a/book/src/binding/box.md b/book/src/binding/box.md
new file mode 100644
index 0000000..8bcae58
--- /dev/null
+++ b/book/src/binding/box.md
@@ -0,0 +1,120 @@
+{{#title rust::Box<T> — Rust ♡ C++}}
+# rust::Box\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <type_traits>
+#
+# namespace rust {
+
+template <typename T>
+class Box final {
+public:
+  using value_type = T;
+  using const_pointer =
+      typename std::add_pointer<typename std::add_const<T>::type>::type;
+  using pointer = typename std::add_pointer<T>::type;
+
+  Box(const Box &);
+  Box(Box &&) noexcept;
+  ~Box() noexcept;
+
+  explicit Box(const T &);
+  explicit Box(T &&);
+
+  Box &operator=(const Box &);
+  Box &operator=(Box &&) noexcept;
+
+  const T *operator->() const noexcept;
+  const T &operator*() const noexcept;
+  T *operator->() noexcept;
+  T &operator*() noexcept;
+
+  template <typename... Fields>
+  static Box in_place(Fields &&...);
+
+  // Important: requires that `raw` came from an into_raw call. Do not
+  // pass a pointer from `new` or any other source.
+  static Box from_raw(T *) noexcept;
+
+  T *into_raw() noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Box\<T\> does not support T being an opaque C++ type. You should use
+[UniquePtr\<T\>](uniqueptr.md) instead for transferring ownership of opaque C++
+types on the language boundary.
+
+If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
+known at compile time. In the future we may introduce support for dynamically
+sized opaque Rust types.
+
+[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html
+
+## Example
+
+This program uses a Box to pass ownership of some opaque piece of Rust state
+over to C++ and then back to a Rust callback, which is a useful pattern for
+implementing [async functions over FFI](../async.md).
+
+```rust,noplayground
+// src/main.rs
+
+use std::io::Write;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type File;
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        fn f(
+            callback: fn(Box<File>, fst: &str, snd: &str),
+            out: Box<File>,
+        );
+    }
+}
+
+pub struct File(std::fs::File);
+
+fn main() {
+    let out = std::fs::File::create("example.log").unwrap();
+
+    ffi::f(
+        |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); },
+        Box::new(File(out)),
+    );
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
+       rust::Box<File> out);
+```
+
+```cpp
+// include/example.cc
+
+#include "example/include/example.h"
+
+void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
+       rust::Box<File> out) {
+  callback(std::move(out), "fearless", "concurrency");
+}
+```
diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md
new file mode 100644
index 0000000..0a643c2
--- /dev/null
+++ b/book/src/binding/cxxstring.md
@@ -0,0 +1,137 @@
+{{#title std::string — Rust ♡ C++}}
+# std::string
+
+The Rust binding of std::string is called **[`CxxString`]**. See the link for
+documentation of the Rust API.
+
+[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html
+
+### Restrictions:
+
+Rust code can never obtain a CxxString by value. C++'s string requires a move
+constructor and may hold internal pointers, which is not compatible with Rust's
+move behavior. Instead in Rust code we will only ever look at a CxxString
+through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\>
+or UniquePtr\<CxxString\>.
+
+In order to construct a CxxString on the stack from Rust, you must use the
+[`let_cxx_string!`] macro which will pin the string properly. The code below
+uses this in one place, and the link covers the syntax.
+
+[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html
+
+## Example
+
+This example uses C++17's std::variant to build a toy JSON type. JSON can hold
+various types including strings, and JSON's object type is a map with string
+keys. The example demonstrates Rust indexing into one of those maps.
+
+```rust,noplayground
+// src/main.rs
+
+use cxx::let_cxx_string;
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/json.h");
+
+        type json;
+        type object;
+
+        fn isNull(self: &json) -> bool;
+        fn isNumber(self: &json) -> bool;
+        fn isString(self: &json) -> bool;
+        fn isArray(self: &json) -> bool;
+        fn isObject(self: &json) -> bool;
+
+        fn getNumber(self: &json) -> f64;
+        fn getString(self: &json) -> &CxxString;
+        fn getArray(self: &json) -> &CxxVector<json>;
+        fn getObject(self: &json) -> &object;
+
+        #[cxx_name = "at"]  // https://en.cppreference.com/w/cpp/container/map/at
+        fn get<'a>(self: &'a object, key: &CxxString) -> &'a json;
+
+        fn load_config() -> UniquePtr<json>;
+    }
+}
+
+fn main() {
+    let config = ffi::load_config();
+
+    let_cxx_string!(key = "name");
+    println!("{}", config.getObject().get(&key).getString());
+}
+```
+
+```cpp
+// include/json.h
+
+#pragma once
+#include <map>
+#include <memory>
+#include <variant>
+#include <vector>
+
+class json final {
+public:
+  static const json null;
+  using number = double;
+  using string = std::string;
+  using array = std::vector<json>;
+  using object = std::map<string, json>;
+
+  json() noexcept = default;
+  json(const json &) = default;
+  json(json &&) = default;
+  template <typename... T>
+  json(T &&... value) : value(std::forward<T>(value)...) {}
+
+  bool isNull() const;
+  bool isNumber() const;
+  bool isString() const;
+  bool isArray() const;
+  bool isObject() const;
+
+  number getNumber() const;
+  const string &getString() const;
+  const array &getArray() const;
+  const object &getObject() const;
+
+private:
+  std::variant<std::monostate, number, string, array, object> value;
+};
+
+using object = json::object;
+
+std::unique_ptr<json> load_config();
+```
+
+```cpp
+// include/json.cc
+
+#include "example/include/json.h"
+#include <initializer_list>
+#include <utility>
+
+const json json::null{};
+bool json::isNull() const { return std::holds_alternative<std::monostate>(value); }
+bool json::isNumber() const { return std::holds_alternative<number>(value); }
+bool json::isString() const { return std::holds_alternative<string>(value); }
+bool json::isArray() const { return std::holds_alternative<array>(value); }
+bool json::isObject() const { return std::holds_alternative<object>(value); }
+json::number json::getNumber() const { return std::get<number>(value); }
+const json::string &json::getString() const { return std::get<string>(value); }
+const json::array &json::getArray() const { return std::get<array>(value); }
+const json::object &json::getObject() const { return std::get<object>(value); }
+
+std::unique_ptr<json> load_config() {
+  return std::make_unique<json>(
+      std::in_place_type<json::object>,
+      std::initializer_list<std::pair<const std::string, json>>{
+          {"name", "cxx-example"},
+          {"edition", 2018.},
+          {"repository", json::null}});
+}
+```
diff --git a/book/src/binding/cxxvector.md b/book/src/binding/cxxvector.md
new file mode 100644
index 0000000..fd95a2d
--- /dev/null
+++ b/book/src/binding/cxxvector.md
@@ -0,0 +1,62 @@
+{{#title std::vector<T> — Rust ♡ C++}}
+# std::vector\<T\>
+
+The Rust binding of std::vector\<T\> is called **[`CxxVector<T>`]**. See the
+link for documentation of the Rust API.
+
+[`CxxVector<T>`]: https://docs.rs/cxx/*/cxx/struct.CxxVector.html
+
+### Restrictions:
+
+Rust code can never obtain a CxxVector by value. Instead in Rust code we will
+only ever look at a vector behind a reference or smart pointer, as in
+&CxxVector\<T\> or UniquePtr\<CxxVector\<T\>\>.
+
+CxxVector\<T\> does not support T being an opaque Rust type. You should use a
+Vec\<T\> (C++ rust::Vec\<T\>) instead for collections of opaque Rust types on
+the language boundary.
+
+## Example
+
+This program involves Rust code converting a `CxxVector<CxxString>` (i.e.
+`std::vector<std::string>`) into a Rust `Vec<String>`.
+
+```rust,noplayground
+// src/main.rs
+
+#![no_main] // main defined in C++ by main.cc
+
+use cxx::{CxxString, CxxVector};
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn f(vec: &CxxVector<CxxString>);
+    }
+}
+
+fn f(vec: &CxxVector<CxxString>) {
+    let vec: Vec<String> = vec
+        .iter()
+        .map(|s| s.to_string_lossy().into_owned())
+        .collect();
+    g(&vec);
+}
+
+fn g(vec: &[String]) {
+    println!("{:?}", vec);
+}
+```
+
+```cpp
+// src/main.cc
+
+#include "example/src/main.rs.h"
+#include <string>
+#include <vector>
+
+int main() {
+  std::vector<std::string> vec{"fearless", "concurrency"};
+  f(vec);
+}
+```
diff --git a/book/src/binding/fn.md b/book/src/binding/fn.md
new file mode 100644
index 0000000..2934b06
--- /dev/null
+++ b/book/src/binding/fn.md
@@ -0,0 +1,34 @@
+{{#title Function pointers — Rust ♡ C++}}
+# Function pointers
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+template <typename Signature>
+class Fn;
+
+template <typename Ret, typename... Args>
+class Fn<Ret(Args...)> final {
+public:
+  Ret operator()(Args... args) const noexcept;
+  Fn operator*() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Function pointers with a Result return type are not implemented yet.
+
+Passing a function pointer from C++ to Rust is not implemented yet, only from
+Rust to an `extern "C++"` function is implemented.
+
+## Example
+
+Function pointers are commonly useful for implementing [async functions over
+FFI](../async.md). See the example code on that page.
diff --git a/book/src/binding/result.md b/book/src/binding/result.md
new file mode 100644
index 0000000..e49dcf4
--- /dev/null
+++ b/book/src/binding/result.md
@@ -0,0 +1,148 @@
+{{#title Result<T> — Rust ♡ C++}}
+# Result\<T\>
+
+Result\<T\> is allowed as the return type of an extern function in either
+direction. Its behavior is to translate to/from C++ exceptions. If your codebase
+does not use C++ exceptions, or prefers to represent fallibility using something
+like outcome\<T\>, leaf::result\<T\>, StatusOr\<T\>, etc then you'll need to
+handle the translation of those to Rust Result\<T\> using your own shims for
+now. Better support for this is planned.
+
+If an exception is thrown from an `extern "C++"` function that is *not* declared
+by the CXX bridge to return Result, the program calls C++'s `std::terminate`.
+The behavior is equivalent to the same exception being thrown through a
+`noexcept` C++ function.
+
+If a panic occurs in *any* `extern "Rust"` function, regardless of whether it is
+declared by the CXX bridge to return Result, a message is logged and the program
+calls Rust's `std::process::abort`.
+
+## Returning Result from Rust to C++
+
+An `extern "Rust"` function returning a Result turns into a `throw` in C++ if
+the Rust side produces an error.
+
+Note that the return type written inside of cxx::bridge must be written without
+a second type parameter. Only the Ok type is specified for the purpose of the
+FFI. The Rust *implementation* (outside of the bridge module) may pick any error
+type as long as it has a std::fmt::Display impl.
+
+```rust,noplayground
+# use std::io;
+#
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn fallible1(depth: usize) -> Result<String>;
+        fn fallible2() -> Result<()>;
+    }
+}
+
+fn fallible1(depth: usize) -> anyhow::Result<String> {
+    if depth == 0 {
+        return Err(anyhow::Error::msg("fallible1 requires depth > 0"));
+    }
+    ...
+}
+
+fn fallible2() -> Result<(), io::Error> {
+    ...
+    Ok(())
+}
+```
+
+The exception that gets thrown by CXX on the C++ side is always of type
+`rust::Error` and has the following C++ public API. The `what()` member function
+gives the error message according to the Rust error's std::fmt::Display impl.
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+class Error final : public std::exception {
+public:
+  Error(const Error &);
+  Error(Error &&) noexcept;
+  ~Error() noexcept;
+
+  Error &operator=(const Error &);
+  Error &operator=(Error &&) noexcept;
+
+  const char *what() const noexcept override;
+};
+#
+# } // namespace rust
+```
+
+## Returning Result from C++ to Rust
+
+An `extern "C++"` function returning a Result turns into a `catch` in C++ that
+converts the exception into an Err for Rust.
+
+Note that the return type written inside of cxx::bridge must be written without
+a second type parameter. Only the Ok type is specified for the purpose of the
+FFI. The resulting error type created by CXX when an `extern "C++"` function
+throws will always be of type **[`cxx::Exception`]**.
+
+[`cxx::Exception`]: https://docs.rs/cxx/*/cxx/struct.Exception.html
+
+```rust,noplayground
+# use std::process;
+#
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+        fn fallible1(depth: usize) -> Result<String>;
+        fn fallible2() -> Result<()>;
+    }
+}
+
+fn main() {
+    if let Err(err) = ffi::fallible1(99) {
+        eprintln!("Error: {}", err);
+        process::exit(1);
+    }
+}
+```
+
+The specific set of caught exceptions and the conversion to error message are
+both customizable. The way you do this is by defining a template function
+`rust::behavior::trycatch` with a suitable signature inside any one of the
+headers `include!`'d by your cxx::bridge.
+
+The template signature is required to be:
+
+```cpp,hidelines
+namespace rust {
+namespace behavior {
+
+template <typename Try, typename Fail>
+static void trycatch(Try &&func, Fail &&fail) noexcept;
+
+} // namespace behavior
+} // namespace rust
+```
+
+The default `trycatch` used by CXX if you have not provided your own is the
+following. You must follow the same pattern: invoke `func` with no arguments,
+catch whatever exception(s) you want, and invoke `fail` with the error message
+you'd like for the Rust error to have.
+
+```cpp,hidelines
+# #include <exception>
+#
+# namespace rust {
+# namespace behavior {
+#
+template <typename Try, typename Fail>
+static void trycatch(Try &&func, Fail &&fail) noexcept try {
+  func();
+} catch (const std::exception &e) {
+  fail(e.what());
+}
+#
+# } // namespace behavior
+# } // namespace rust
+```
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
new file mode 100644
index 0000000..aacd56b
--- /dev/null
+++ b/book/src/binding/slice.md
@@ -0,0 +1,115 @@
+{{#title rust::Slice<T> — Rust ♡ C++}}
+# rust::Slice\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# namespace rust {
+
+template <typename T>
+class Slice final {
+public:
+  Slice() noexcept;
+  Slice(const Slice<T> &) noexcept;
+  Slice(T *, size_t count) noexcept;
+
+  Slice &operator=(const Slice<T> &) noexcept;
+
+  T *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Only &amp;\[u8\] i.e. rust::Slice\<const uint8\_t\> is currently implemented.
+Support for arbitrary &amp;\[T\] is coming.
+
+Allowed as function argument or return value. Not supported in shared structs.
+&amp;mut \[T\] is not supported yet.
+
+## Example
+
+This example is a C++ program that constructs a slice containing JSON data (by
+reading from stdin, but it could be from anywhere), then calls into Rust to
+pretty-print that JSON data into a std::string via the [serde_json] and
+[serde_transcode] crates.
+
+[serde_json]: https://github.com/serde-rs/json
+[serde_transcode]: https://github.com/sfackler/serde-transcode
+
+```rust,noplayground
+// src/main.rs
+
+#![no_main] // main defined in C++ by main.cc
+
+use cxx::CxxString;
+use std::io::{self, Write};
+use std::pin::Pin;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>;
+    }
+}
+
+struct WriteToCxxString<'a>(Pin<&'a mut CxxString>);
+
+impl<'a> Write for WriteToCxxString<'a> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.as_mut().push_bytes(buf);
+        Ok(buf.len())
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> {
+    let writer = WriteToCxxString(output);
+    let mut deserializer = serde_json::Deserializer::from_slice(input);
+    let mut serializer = serde_json::Serializer::pretty(writer);
+    serde_transcode::transcode(&mut deserializer, &mut serializer)
+}
+```
+
+```cpp
+// src/main.cc
+
+#include "example/src/main.rs.h"
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+int main() {
+  // Read json from stdin.
+  std::istreambuf_iterator<char> begin{std::cin}, end;
+  std::vector<unsigned char> input{begin, end};
+  rust::Slice<const uint8_t> slice{input.data(), input.size()};
+
+  // Prettify using serde_json and serde_transcode.
+  std::string output;
+  prettify_json(slice, output);
+
+  // Write to stdout.
+  std::cout << output << std::endl;
+}
+```
+
+Testing the example:
+
+```console
+$  echo '{"fearless":"concurrency"}' | cargo run
+    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
+     Running `target/debug/example`
+{
+  "fearless": "concurrency"
+}
+```
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
new file mode 100644
index 0000000..2774754
--- /dev/null
+++ b/book/src/binding/str.md
@@ -0,0 +1,101 @@
+{{#title rust::Str — Rust ♡ C++}}
+# rust::Str
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iosfwd>
+# #include <string>
+#
+# namespace rust {
+
+class Str final {
+public:
+  Str() noexcept;
+  Str(const Str &) noexcept;
+
+  // Throws std::invalid_argument if not utf-8.
+  Str(const std::string &);
+  Str(const char *);
+  Str(const char *, size_t);
+  Str(std::string &&) = delete;
+
+  Str &operator=(const Str &) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+
+std::ostream &operator<<(std::ostream &, const Str &);
+#
+# } // namespace rust
+```
+
+### Notes:
+
+**Be aware that rust::Str behaves like &amp;str i.e. it is a borrow!**&ensp;C++
+needs to be mindful of the lifetimes at play.
+
+Just to reiterate: &amp;str is rust::Str. Do not try to write &amp;str as `const
+rust::Str &`. A language-level C++ reference is not able to capture the fat
+pointer nature of &amp;str.
+
+### Restrictions:
+
+Allowed as function argument or return value. Not supported in shared structs
+yet. `&mut str` is not supported yet, but is also extremely obscure so this is
+fine.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        fn r(greeting: &str);
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/greeting.h");
+        fn c(greeting: &str);
+    }
+}
+
+fn r(greeting: &str) {
+    println!("{}", greeting);
+}
+
+fn main() {
+    ffi::c("hello from Rust");
+}
+```
+
+```cpp
+// include/greeting.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void c(rust::Str greeting);
+```
+
+```cpp
+// src/greeting.cc
+
+#include "example/include/greeting.h"
+#include <iostream>
+
+void c(rust::Str greeting) {
+  std::cout << greeting << std::endl;
+  r("hello from C++");
+}
+```
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
new file mode 100644
index 0000000..ac44fb2
--- /dev/null
+++ b/book/src/binding/string.md
@@ -0,0 +1,94 @@
+{{#title rust::String — Rust ♡ C++}}
+# rust::String
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iosfwd>
+# #include <string>
+#
+# namespace rust {
+
+class String final {
+public:
+  String() noexcept;
+  String(const String &) noexcept;
+  String(String &&) noexcept;
+  ~String() noexcept;
+
+  // Throws std::invalid_argument if not utf-8.
+  String(const std::string &);
+  String(const char *);
+  String(const char *, size_t);
+
+  String &operator=(const String &) noexcept;
+  String &operator=(String &&) noexcept;
+
+  explicit operator std::string() const;
+
+  // Note: no null terminator.
+  const char *data() const noexcept;
+  size_t size() const noexcept;
+  size_t length() const noexcept;
+};
+
+std::ostream &operator<<(std::ostream &, const String &);
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+None. Strings may be used as function arguments and function return values, by
+value or by reference, as well as fields of shared structs.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct ConcatRequest {
+        fst: String,
+        snd: String,
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/concat.h");
+        fn concat(r: ConcatRequest) -> String;
+    }
+}
+
+fn main() {
+    let concatenated = ffi::concat(ffi::ConcatRequest {
+        fst: "fearless".to_owned(),
+        snd: "concurrency".to_owned(),
+    });
+    println!("concatenated: {:?}", concatenated);
+}
+```
+
+```cpp
+// include/concat.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+rust::String concat(ConcatRequest r);
+```
+
+```cpp
+// src/concat.cc
+
+#include "example/include/concat.h"
+
+rust::String concat(ConcatRequest r) {
+  // The full suite of operator overloads hasn't been added
+  // yet on rust::String, but we can get it done like this:
+  return std::string(r.fst) + std::string(r.snd);
+}
+```
diff --git a/book/src/binding/uniqueptr.md b/book/src/binding/uniqueptr.md
new file mode 100644
index 0000000..eefbc34
--- /dev/null
+++ b/book/src/binding/uniqueptr.md
@@ -0,0 +1,63 @@
+{{#title std::unique_ptr<T> — Rust ♡ C++}}
+# std::unique\_ptr\<T\>
+
+The Rust binding of std::unique\_ptr\<T\> is called **[`UniquePtr<T>`]**. See
+the link for documentation of the Rust API.
+
+[`UniquePtr<T>`]: https://docs.rs/cxx/*/cxx/struct.UniquePtr.html
+
+### Restrictions:
+
+Only `std::unique_ptr<T, std::default_delete<T>>` is currently supported. Custom
+deleters may be supported in the future.
+
+UniquePtr\<T\> does not support T being an opaque Rust type. You should use a
+Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of
+opaque Rust types on the language boundary.
+
+## Example
+
+UniquePtr is commonly useful for returning opaque C++ objects to Rust. This use
+case was featured in the [*blobstore tutorial*](../tutorial.md).
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        // ...
+    }
+}
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+    // ...
+}
+```
+
+```cpp
+// include/blobstore.h
+
+#pragma once
+#include <memory>
+
+class BlobstoreClient;
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp
+// src/blobstore.cc
+
+#include "example/include/blobstore.h"
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::make_unique<BlobstoreClient>();
+}
+```
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
new file mode 100644
index 0000000..f3056fb
--- /dev/null
+++ b/book/src/binding/vec.md
@@ -0,0 +1,128 @@
+{{#title rust::Vec<T> — Rust ♡ C++}}
+# rust::Vec\<T\>
+
+### Public API:
+
+```cpp,hidelines
+// rust/cxx.h
+#
+# #include <iterator>
+# #include <type_traits>
+#
+# namespace rust {
+
+template <typename T>
+class Vec final {
+public:
+  using value_type = T;
+
+  Vec() noexcept;
+  Vec(Vec &&) noexcept;
+  ~Vec() noexcept;
+
+  Vec &operator=(Vec &&) noexcept;
+
+  size_t size() const noexcept;
+  bool empty() const noexcept;
+  const T *data() const noexcept;
+  T *data() noexcept;
+
+  const T &operator[](size_t n) const noexcept;
+  const T &at(size_t n) const;
+
+  const T &front() const;
+  const T &back() const;
+
+  void reserve(size_t new_cap);
+  void push_back(const T &value);
+  void push_back(T &&value);
+  template <typename... Args>
+  void emplace_back(Args &&... args);
+
+  class const_iterator final {
+  public:
+    using difference_type = ptrdiff_t;
+    using value_type = typename std::add_const<T>::type;
+    using pointer =
+        typename std::add_pointer<typename std::add_const<T>::type>::type;
+    using reference = typename std::add_lvalue_reference<
+        typename std::add_const<T>::type>::type;
+    using iterator_category = std::forward_iterator_tag;
+
+    const T &operator*() const noexcept;
+    const T *operator->() const noexcept;
+    const_iterator &operator++() noexcept;
+    const_iterator operator++(int) noexcept;
+    bool operator==(const const_iterator &) const noexcept;
+    bool operator!=(const const_iterator &) const noexcept;
+  };
+
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+};
+#
+# } // namespace rust
+```
+
+### Restrictions:
+
+Vec\<T\> does not support T being an opaque C++ type. You should use
+CxxVector\<T\> (C++ std::vector\<T\>) instead for collections of opaque C++
+types on the language boundary.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        v: u32,
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        fn f(elements: Vec<Shared>);
+    }
+}
+
+fn main() {
+    let shared = |v| ffi::Shared { v };
+    let elements = vec![shared(3), shared(2), shared(1)];
+    ffi::f(elements);
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include "example/src/main.rs.h"
+#include "rust/cxx.h"
+
+void f(rust::Vec<Shared> elements);
+```
+
+```cpp
+// src/example.cc
+
+#include "example/include/example.h"
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <iterator>
+#include <vector>
+
+void f(rust::Vec<Shared> v) {
+  for (auto shared : v) {
+    std::cout << shared.v << std::endl;
+  }
+
+  // Copy the elements to a C++ std::vector using STL algorithm.
+  std::vector<Shared> stdv;
+  std::copy(v.begin(), v.end(), std::back_inserter(stdv));
+  assert(v.size() == stdv.size());
+}
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
new file mode 100644
index 0000000..f19dc5d
--- /dev/null
+++ b/book/src/bindings.md
@@ -0,0 +1,54 @@
+{{#title Built-in bindings — Rust ♡ C++}}
+# Built-in bindings reference
+
+In addition to all the primitive types (i32 &lt;=&gt; int32_t), the following
+common types may be used in the fields of shared structs and the arguments and
+returns of extern functions.
+
+<br>
+
+<table>
+<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
+<tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
+</table>
+
+<br>
+
+The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
+the CXX GitHub repo. You will need to include this header in your C++ code when
+working with those types. **When using Cargo and the cxx-build crate, the header
+is made available to you at `#include "rust/cxx.h"`.**
+
+The `rust` namespace additionally provides lowercase type aliases of all the
+types mentioned in the table, for use in codebases preferring that style. For
+example `rust::String`, `rust::Vec` may alternatively be written `rust::string`,
+`rust::vec` etc.
+
+## Pending bindings
+
+The following types are intended to be supported "soon" but are just not
+implemented yet. I don't expect any of these to be hard to make work but it's a
+matter of designing a nice API for each in its non-native language.
+
+<br>
+
+<table>
+<tr><th>name in Rust</th><th>name in C++</th></tr>
+<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td></tr>
+<tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
+</table>
diff --git a/book/src/build/bazel.md b/book/src/build/bazel.md
new file mode 100644
index 0000000..08edb19
--- /dev/null
+++ b/book/src/build/bazel.md
@@ -0,0 +1,106 @@
+{{#title Bazel, Buck — Rust ♡ C++}}
+## Bazel, Buck, potentially other similar environments
+
+Starlark-based build systems with the ability to compile a code generator and
+invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge`
+command line interface.
+
+The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built
+from the *gen/cmd/* directory of the CXX GitHub repo.
+
+```console
+$  cargo install cxxbridge-cmd
+
+$  cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
+$  cxxbridge src/bridge.rs > path/to/bridge.rs.cc
+```
+
+The CXX repo maintains working Bazel `BUILD` and Buck `BUCK` targets for the
+complete blobstore tutorial (chapter 3) for your reference, tested in CI. These
+aren't meant to be directly what you use in your codebase, but serve as an
+illustration of one possible working pattern.
+
+```python
+# tools/bazel/rust_cxx_bridge.bzl
+
+load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
+def rust_cxx_bridge(name, src, deps = []):
+    native.alias(
+        name = "%s/header" % name,
+        actual = src + ".h",
+    )
+
+    native.alias(
+        name = "%s/source" % name,
+        actual = src + ".cc",
+    )
+
+    run_binary(
+        name = "%s/generated" % name,
+        srcs = [src],
+        outs = [
+            src + ".h",
+            src + ".cc",
+        ],
+        args = [
+            "$(location %s)" % src,
+            "-o",
+            "$(location %s.h)" % src,
+            "-o",
+            "$(location %s.cc)" % src,
+        ],
+        tool = "//:codegen",
+    )
+
+    cc_library(
+        name = name,
+        srcs = [src + ".cc"],
+        deps = deps + [":%s/include" % name],
+    )
+
+    cc_library(
+        name = "%s/include" % name,
+        hdrs = [src + ".h"],
+    )
+```
+
+```python
+# demo/BUILD
+
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("//tools/bazel:rust.bzl", "rust_binary")
+load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
+
+rust_binary(
+    name = "demo",
+    srcs = glob(["src/**/*.rs"]),
+    deps = [
+        ":blobstore-sys",
+        ":bridge",
+        "//:cxx",
+    ],
+)
+
+rust_cxx_bridge(
+    name = "bridge",
+    src = "src/main.rs",
+    deps = [":blobstore-include"],
+)
+
+cc_library(
+    name = "blobstore-sys",
+    srcs = ["src/blobstore.cc"],
+    deps = [
+        ":blobstore-include",
+        ":bridge/include",
+    ],
+)
+
+cc_library(
+    name = "blobstore-include",
+    hdrs = ["include/blobstore.h"],
+    deps = ["//:core"],
+)
+```
diff --git a/book/src/build/cargo.md b/book/src/build/cargo.md
new file mode 100644
index 0000000..82ccfb5
--- /dev/null
+++ b/book/src/build/cargo.md
@@ -0,0 +1,306 @@
+{{#title Cargo-based setup — Rust ♡ C++}}
+# Cargo-based builds
+
+As one aspect of delivering a good Rust&ndash;C++ interop experience, CXX turns
+Cargo into a quite usable build system for C++ projects published as a
+collection of crates.io packages, including a consistent and frictionless
+experience `#include`-ing C++ headers across dependencies.
+
+## Canonical setup
+
+CXX's integration with Cargo is handled through the [cxx-build] crate.
+
+[cxx-build]: https://docs.rs/cxx-build
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "..."
+# version = "..."
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+
+[build-dependencies]
+cxx-build = "1.0"
+```
+
+The canonical build script is as follows. The indicated line returns a
+[`cc::Build`] instance (from the usual widely used `cc` crate) on which you can
+set up any additional source files and compiler flags as normal.
+
+[`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html
+
+```rust,noplayground
+// build.rs
+
+fn main() {
+    cxx_build::bridge("src/main.rs")  // returns a cc::Build
+        .file("src/demo.cc")
+        .flag_if_supported("-std=c++11")
+        .compile("cxxbridge-demo");
+
+    println!("cargo:rerun-if-changed=src/main.rs");
+    println!("cargo:rerun-if-changed=src/demo.cc");
+    println!("cargo:rerun-if-changed=include/demo.h");
+}
+```
+
+The `rerun-if-changed` lines are optional but make it so that Cargo does not
+spend time recompiling your C++ code when only non-C++ code has changed since
+the previous Cargo build. By default without any `rerun-if-changed`, Cargo will
+re-execute the build script after *any* file changed in the project.
+
+If stuck, try comparing what you have against the *demo/* directory of the CXX
+GitHub repo, which maintains a working Cargo-based setup for the blobstore
+tutorial (chapter 3).
+
+## Header include paths
+
+With cxx-build, by default your include paths always start with the crate name.
+This applies to both `#include` within your C++ code, and `include!` in the
+`extern "C++"` section of your Rust cxx::bridge.
+
+Your crate name is determined by the `name` entry in Cargo.toml.
+
+For example if your crate is named `yourcratename` and contains a C++ header
+file `path/to/header.h` relative to Cargo.toml, that file will be includable as:
+
+```cpp
+#include "yourcratename/path/to/header.h"
+```
+
+A crate can choose a prefix for its headers that is different from the crate
+name by modifying **[`CFG.include_prefix`][CFG]** from build.rs:
+
+[CFG]: https://docs.rs/cxx-build/*/cxx_build/static.CFG.html
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.include_prefix = "my/project";
+
+    cxx_build::bridge(...)...
+}
+```
+
+Subsequently the header located at `path/to/header.h` would now be includable
+as:
+
+```cpp
+#include "my/project/path/to/header.h"
+```
+
+The empty string `""` is a valid include prefix and will make it possible to
+have `#include "path/to/header.h"`. However, if your crate is a library, be
+considerate of possible name collisions that may occur in downstream crates. If
+using an empty include prefix, you'll want to make sure your headers' local path
+within the crate is sufficiently namespaced or unique.
+
+## Including generated code
+
+If your `#[cxx::bridge]` module contains an `extern "Rust"` block i.e. types or
+functions exposed from Rust to C++, or any shared data structures, the
+CXX-generated C++ header declaring those things is available using a `.rs.h`
+extension on the Rust source file's name.
+
+```cpp
+// the header generated from path/to/lib.rs
+#include "yourcratename/path/to/lib.rs.h"
+```
+
+For giggles, it's also available using just a plain `.rs` extension as if you
+were including the Rust file directly. Use whichever you find more palatable.
+
+```cpp
+#include "yourcratename/path/to/lib.rs"
+```
+
+## Including headers from dependencies
+
+You get to include headers from your dependencies, both handwritten ones
+contained as `.h` files in their Cargo package, as well as CXX-generated ones.
+
+It works the same as an include of a local header: use the crate name (or their
+include\_prefix if their crate changed it) followed by the relative path of the
+header within the crate.
+
+```cpp
+#include "dependencycratename/path/to/their/header.h`
+```
+
+Note that cross-crate imports are only made available between **direct
+dependencies**. You must directly depend on the other crate in order to #include
+its headers; a transitive dependency is not sufficient.
+
+Additionally, headers from a direct dependency are only importable if the
+dependency's Cargo.toml manifest contains a `links` key. If not, its headers
+will not be importable from outside of the same crate. See *[the `links`
+manifest key][links]* in the Cargo reference.
+
+[links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
+
+<br><br><br>
+
+# Advanced features
+
+The following CFG settings are only relevant to you if you are writing a library
+that needs to support downstream crates `#include`-ing its C++ public headers.
+
+## Publicly exporting header directories
+
+**[`CFG.exported_header_dirs`][CFG]** (vector of absolute paths) defines a set
+of additional directories from which the current crate, directly dependent
+crates, and further crates to which this crate's headers are exported (more
+below) will be able to `#include` headers.
+
+Adding a directory to `exported_header_dirs` is similar to adding it to the
+current build via the `cc` crate's [`Build::include`], but *also* makes the
+directory available to downstream crates that want to `#include` one of the
+headers from your crate. If the dir were added only using `Build::include`, the
+downstream crate including your header would need to manually add the same
+directory to their own build as well.
+
+[`Build::include`]: https://docs.rs/cc/1/cc/struct.Build.html#method.include
+
+When using `exported_header_dirs`, your crate must also set a `links` key for
+itself in Cargo.toml. See [*the `links` manifest key*][links]. The reason is
+that Cargo imposes no ordering on the execution of build scripts without a
+`links` key, which means the downstream crate's build script might otherwise
+execute before yours decides what to put into `exported_header_dirs`.
+
+### Example
+
+One of your crate's headers wants to include a system library, such as `#include
+"Python.h"`.
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+use std::path::PathBuf;
+
+fn main() {
+    let python3 = pkg_config::probe_library("python3").unwrap();
+    let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path);
+    CFG.exported_header_dirs.extend(python_include_paths);
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
+
+### Example
+
+Your crate wants to rearrange the headers that it exports vs how they're laid
+out locally inside the crate's source directory.
+
+Suppose the crate as published contains a file at `./include/myheader.h` but
+wants it available to downstream crates as `#include "foo/v1/public.h"`.
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+use std::path::Path;
+use std::{env, fs};
+
+fn main() {
+    let out_dir = env::var_os("OUT_DIR").unwrap();
+    let headers = Path::new(&out_dir).join("headers");
+    CFG.exported_header_dirs.push(&headers);
+
+    // We contain `include/myheader.h` locally, but
+    // downstream will use `#include "foo/v1/public.h"`
+    let foo = headers.join("foo").join("v1");
+    fs::create_dir_all(&foo).unwrap();
+    fs::copy("include/myheader.h", foo.join("public.h")).unwrap();
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
+
+## Publicly exporting dependencies
+
+**[`CFG.exported_header_prefixes`][CFG]** (vector of strings) each refer to the
+`include_prefix` of one of your direct dependencies, or a prefix thereof. They
+describe which of your dependencies participate in your crate's C++ public API,
+as opposed to private use by your crate's implementation.
+
+As a general rule, if one of your headers `#include`s something from one of your
+dependencies, you need to put that dependency's `include_prefix` into
+`CFG.exported_header_prefixes` (*or* their `links` key into
+`CFG.exported_header_links`; see below). On the other hand if only your C++
+implementation files and *not* your headers are importing from the dependency,
+you do not export that dependency.
+
+The significance of exported headers is that if downstream code (crate **𝒜**)
+contains an `#include` of a header from your crate (**ℬ**) and your header
+contains an `#include` of something from your dependency (**𝒞**), the exported
+dependency **𝒞** becomes available during the downstream crate **𝒜**'s build.
+Otherwise the downstream crate **𝒜** doesn't know about **𝒞** and wouldn't be
+able to find what header your header is referring to, and would fail to build.
+
+When using `exported_header_prefixes`, your crate must also set a `links` key
+for itself in Cargo.toml.
+
+### Example
+
+Suppose you have a crate with 5 direct dependencies and the `include_prefix` for
+each one are:
+
+- "crate0"
+- "group/api/crate1"
+- "group/api/crate2"
+- "group/api/contrib/crate3"
+- "detail/crate4"
+
+Your header involves types from the first four so we re-export those as part of
+your public API, while crate4 is only used internally by your cc file not your
+header, so we do not export:
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.exported_header_prefixes = vec!["crate0", "group/api"];
+
+    cxx_build::bridge("src/bridge.rs")
+        .file("src/impl.cc")
+        .compile("demo");
+}
+```
+
+<br>
+
+For more fine grained control, there is **[`CFG.exported_header_links`][CFG]**
+(vector of strings) which each refer to the `links` attribute ([*the `links`
+manifest key*][links]) of one of your crate's direct dependencies.
+
+This achieves an equivalent result to `CFG.exported_header_prefixes` by
+re-exporting a C++ dependency as part of your crate's public API, except with
+finer control for cases when multiple crates might be sharing the same
+`include_prefix` and you'd like to export some but not others. Links attributes
+are guaranteed to be unique identifiers by Cargo.
+
+When using `exported_header_links`, your crate must also set a `links` key for
+itself in Cargo.toml.
+
+### Example
+
+```rust,noplayground
+// build.rs
+
+use cxx_build::CFG;
+
+fn main() {
+    CFG.exported_header_links.push("git2");
+
+    cxx_build::bridge("src/bridge.rs").compile("demo");
+}
+```
diff --git a/book/src/build/cmake.md b/book/src/build/cmake.md
new file mode 100644
index 0000000..ed3cb61
--- /dev/null
+++ b/book/src/build/cmake.md
@@ -0,0 +1,24 @@
+{{#title CMake — Rust ♡ C++}}
+# CMake
+
+There is not an officially endorsed CMake setup for CXX, but a few developers
+have shared one that they got working. You can try one of these as a starting
+point. If you feel that you have arrived at a CMake setup that is superior to
+what is available in these links, feel free to make a PR adding it to this list.
+
+<br>
+
+---
+
+- **<https://github.com/XiangpengHao/cxx-cmake-example>**
+
+  - Supports cross-language link time optimization (LTO)
+
+---
+
+- **<https://github.com/david-cattermole/cxx-demo-example>**
+
+  - Includes a cbindgen component
+  - Tested on Windows 10 with MSVC, and on Linux
+
+---
diff --git a/book/src/build/other.md b/book/src/build/other.md
new file mode 100644
index 0000000..8933c41
--- /dev/null
+++ b/book/src/build/other.md
@@ -0,0 +1,75 @@
+{{#title Other build systems — Rust ♡ C++}}
+# Some other build system
+
+You will need to achieve at least these three things:
+
+- Produce the CXX-generated C++ bindings code.
+- Compile the generated C++ code.
+- Link the resulting objects together with your other C++ and Rust objects.
+
+### Producing the generated code
+
+CXX's Rust code generation automatically happens when the `#[cxx::bridge]`
+procedural macro is expanded during the normal Rust compilation process, so no
+special build steps are required there.
+
+But the C++ side of the bindings needs to be generated. Your options are:
+
+- Use the `cxxbridge` command, which is a standalone command line interface to
+  the CXX C++ code generator. Wire up your build system to compile and invoke
+  this tool.
+
+  ```console
+  $  cxxbridge src/bridge.rs --header > path/to/bridge.rs.h
+  $  cxxbridge src/bridge.rs > path/to/bridge.rs.cc
+  ```
+
+  It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from
+  the *gen/cmd/* directory of the CXX GitHub repo.
+
+- Or, build your own code generator frontend on top of the [cxx-gen] crate. This
+  is currently unofficial and unsupported.
+
+[cxx-gen]: https://docs.rs/cxx-gen
+
+### Compiling C++
+
+However you like. We can provide no guidance.
+
+### Linking the C++ and Rust together
+
+When linking a binary which contains mixed Rust and C++ code, you will have to
+choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you
+may already have extensively tuned.
+
+Rust does not generate simple standalone `.o` files, so you can't just throw the
+Rust-generated code into your existing C++ toolchain linker. Instead you need to
+choose one of these options:
+
+* Use `rustc` as the final linker. Pass any non-Rust libraries using `-L
+  <directory>` and `-l<library>` rustc arguments, and/or `#[link]` directives in
+  your Rust code. If you need to link against C/C++ `.o` files you can use
+  `-Clink-arg=file.o`.
+
+* Use your C++ linker. In this case, you first need to use `rustc` and/or
+  `cargo` to generate a _single_ Rust `staticlib` target and pass that into your
+  foreign linker invocation.
+
+  * If you need to link multiple Rust subsystems, you will need to generate a
+    _single_ `staticlib` perhaps using lots of `extern crate` statements to
+    include multiple Rust `rlib`s.  Multiple Rust `staticlib` files are likely
+    to conflict.
+
+Passing Rust `rlib`s directly into your non-Rust linker is not supported (but
+apparently sometimes works).
+
+See the [Rust reference's *Linkage*][linkage] page for some general information
+here.
+
+[linkage]: https://doc.rust-lang.org/reference/linkage.html
+
+The following open rust-lang issues might hold more recent guidance or
+inspiration: [rust-lang/rust#73632], [rust-lang/rust#73295].
+
+[rust-lang/rust#73632]: https://github.com/rust-lang/rust/issues/73632
+[rust-lang/rust#73295]: https://github.com/rust-lang/rust/issues/73295
diff --git a/book/src/building.md b/book/src/building.md
new file mode 100644
index 0000000..c75939e
--- /dev/null
+++ b/book/src/building.md
@@ -0,0 +1,20 @@
+{{#title Multi-language build system options — Rust ♡ C++}}
+# Multi-language build system options
+
+CXX is designed to be convenient to integrate into a variety of build systems.
+
+If you are working in a project that does not already have a preferred build
+system for its C++ code *or* which will be relying heavily on open source
+libraries from the Rust package registry, you're likely to have the easiest
+experience with Cargo which is the build system commonly used by open source
+Rust projects. Refer to the ***[Cargo](build/cargo.md)*** chapter about CXX's
+Cargo support.
+
+Among build systems designed for first class multi-language support, Bazel is a
+solid choice. Refer to the ***[Bazel](build/bazel.md)*** chapter.
+
+If your codebase is already invested in CMake, refer to the
+***[CMake](build/cmake.md)*** chapter.
+
+If you have some other build system that you'd like to try to make work with
+CXX, see [this page](build/other.md) for notes.
diff --git a/book/src/concepts.md b/book/src/concepts.md
new file mode 100644
index 0000000..75daedd
--- /dev/null
+++ b/book/src/concepts.md
@@ -0,0 +1,85 @@
+{{#title Core concepts — Rust ♡ C++}}
+# Core concepts
+
+This page is a brief overview of the major concepts of CXX, enough so that you
+recognize the shape of things as you read the tutorial and following chapters.
+
+In CXX, the language of the FFI boundary involves 3 kinds of items:
+
+- **Shared structs** &mdash; data structures whose fields are made visible to
+  both languages. The definition written within cxx::bridge in Rust is usually
+  the single source of truth, though there are ways to do sharing based on a
+  bindgen-generated definition with C++ as source of truth.
+
+- **Opaque types** &mdash; their fields are secret from the other language.
+  These cannot be passed across the FFI by value but only behind an indirection,
+  such as a reference `&`, a Rust `Box`, or a C++ `unique_ptr`. Can be a type
+  alias for an arbitrarily complicated generic language-specific type depending
+  on your use case.
+
+- **Functions** &mdash; implemented in either language, callable from the other
+  language.
+
+```rust,noplayground,focuscomment
+# #[cxx::bridge]
+# mod ffi {
+    // Any shared structs, whose fields will be visible to both languages.
+#     struct BlobMetadata {
+#         size: usize,
+#         tags: Vec<String>,
+#     }
+#
+#     extern "Rust" {
+        // Zero or more opaque types which both languages can pass around
+        // but only Rust can see the fields.
+#         type MultiBuf;
+#
+        // Functions implemented in Rust.
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+        // One or more headers with the matching C++ declarations for the
+        // enclosing extern "C++" block. Our code generators don't read it
+        // but it gets #include'd and used in static assertions to ensure
+        // our picture of the FFI boundary is accurate.
+#         include!("demo/include/blobstore.h");
+#
+        // Zero or more opaque types which both languages can pass around
+        // but only C++ can see the fields.
+#         type BlobstoreClient;
+#
+        // Functions implemented in C++.
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#         fn tag(&self, blobid: u64, tag: &str);
+#         fn metadata(&self, blobid: u64) -> BlobMetadata;
+#     }
+# }
+```
+
+Within the `extern "Rust"` part of the CXX bridge we list the types and
+functions for which Rust is the source of truth. These all implicitly refer to
+the `super` module, the parent module of the CXX bridge. You can think of the
+two items listed in the example above as being like `use super::MultiBuf` and
+`use super::next_chunk` except re-exported to C++. The parent module will either
+contain the definitions directly for simple things, or contain the relevant
+`use` statements to bring them into scope from elsewhere.
+
+Within the `extern "C++"` part, we list types and functions for which C++ is the
+source of truth, as well as the header(s) that declare those APIs. In the future
+it's possible that this section could be generated bindgen-style from the
+headers but for now we need the signatures written out; static assertions verify
+that they are accurate.
+
+<br><br>
+
+Be aware that the design of this library is intentionally restrictive and
+opinionated! It isn't a goal to be flexible enough to handle an arbitrary
+signature in either language. Instead this project is about carving out a highly
+expressive set of functionality about which we can make powerful safety
+guarantees today and extend over time. You may find that it takes some practice
+to use CXX bridge effectively as it won't work in all the ways that you may be
+used to.
+
+<br>
diff --git a/book/src/context.md b/book/src/context.md
new file mode 100644
index 0000000..516ee91
--- /dev/null
+++ b/book/src/context.md
@@ -0,0 +1,118 @@
+{{#title Other Rust–C++ interop tools — Rust ♡ C++}}
+# Context: other Rust&ndash;C++ interop tools
+
+When it comes to interacting with an idiomatic Rust API or idiomatic C++ API
+from the other language, the generally applicable approaches outside of the CXX
+crate are:
+
+- Build a C-compatible wrapper around the code (expressed using `extern "C"`
+  signatures, primitives, C-compatible structs, raw pointers). Translate that
+  manually to equivalent `extern "C"` declarations in the other language and
+  keep them in sync. Preferably, build a safe/idiomatic wrapper around the
+  translated `extern "C"` signatures for callers to use.
+
+- Build a C wrapper around the C++ code and use **[bindgen]** to translate that
+  programmatically to `extern "C"` Rust signatures. Preferably, build a
+  safe/idiomatic Rust wrapper on top.
+
+- Build a C-compatible Rust wrapper around the Rust code and use **[cbindgen]**
+  to translate that programmatically to an `extern "C"` C++ header. Preferably,
+  build an idiomatic C++ wrapper.
+
+**If the code you are binding is already *"effectively C"*, the above has you
+covered.** You should use bindgen or cbindgen, or manually translated C
+signatures if there aren't too many and they seldom change.
+
+[bindgen]: https://github.com/rust-lang/rust-bindgen
+[cbindgen]: https://github.com/eqrion/cbindgen
+
+## C++ vs C
+
+Bindgen has some basic support for C++. It can reason about classes, member
+functions, and the layout of templated types. However, everything it does
+related to C++ is best-effort only. Bindgen starts from a point of wanting to
+generate declarations for everything, so any C++ detail that it hasn't
+implemented will cause a crash if you are lucky ([bindgen#388]) or more likely
+silently emit an incompatible signature ([bindgen#380], [bindgen#607],
+[bindgen#652], [bindgen#778], [bindgen#1194]) which will do arbitrary
+memory-unsafe things at runtime whenever called.
+
+[bindgen#388]: https://github.com/rust-lang/rust-bindgen/issues/388
+[bindgen#380]: https://github.com/rust-lang/rust-bindgen/issues/380
+[bindgen#607]: https://github.com/rust-lang/rust-bindgen/issues/607
+[bindgen#652]: https://github.com/rust-lang/rust-bindgen/issues/652
+[bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778
+[bindgen#1194]: https://github.com/rust-lang/rust-bindgen/issues/1194
+
+Thus using bindgen correctly requires not just juggling all your pointers
+correctly at the language boundary, but also understanding ABI details and their
+workarounds and reliably applying them. For example, the programmer will
+discover that their program sometimes segfaults if they call a function that
+returns std::unique\_ptr\<T\> through bindgen. Why? Because unique\_ptr, despite
+being "just a pointer", has a different ABI than a pointer or a C struct
+containing a pointer ([bindgen#778]) and is not directly expressible in Rust.
+Bindgen emitted something that *looks* reasonable and you will have a hell of a
+time in gdb working out what went wrong. Eventually people learn to avoid
+anything involving a non-trivial copy constructor, destructor, or inheritance,
+and instead stick to raw pointers and primitives and trivial structs only
+&mdash; in other words C.
+
+## Geometric intuition for why there is so much opportunity for improvement
+
+The CXX project attempts a different approach to C++ FFI.
+
+Imagine Rust and C and C++ as three vertices of a scalene triangle, with length
+of the edges being related to similarity of the languages when it comes to
+library design.
+
+The most similar pair (the shortest edge) is Rust&ndash;C++. These languages
+have largely compatible concepts of things like ownership, vectors, strings,
+fallibility, etc that translate clearly from signatures in either language to
+signatures in the other language.
+
+When we make a binding for an idiomatic C++ API using bindgen, and we fall down
+to raw pointers and primitives and trivial structs as described above, what we
+are really doing is coding the two longest edges of the triangle: getting from
+C++ down to C, and C back up to Rust. The Rust&ndash;C edge always involves a
+great deal of `unsafe` code, and the C++&ndash;C edge similarly requires care
+just for basic memory safety. Something as basic as "how do I pass ownership of
+a string to the other language?" becomes a strap-yourself-in moment,
+particularly for someone not already an expert in one or both sides.
+
+You should think of the `cxx` crate as being the midpoint of the Rust&ndash;C++
+edge. Rather than coding the two long edges, you will code half the short edge
+in Rust and half the short edge in C++, in both cases with the library playing
+to the strengths of the Rust type system *and* the C++ type system to help
+assure correctness.
+
+If you've already been through the tutorial in the previous chapter, take a
+moment to appreciate that the C++ side *really* looks like we are just writing
+C++ and the Rust side *really* looks like we are just writing Rust. Anything you
+could do wrong in Rust, and almost anything you could reasonably do wrong in
+C++, will be caught by the compiler. This highlights that we are on the "short
+edge of the triangle".
+
+But it all still boils down to the same things: it's still FFI from one piece of
+native code to another, nothing is getting serialized or allocated or
+runtime-checked in between.
+
+## Role of CXX
+
+The role of CXX is to capture the language boundary with more fidelity than what
+`extern "C"` is able to represent. You can think of CXX as being a replacement
+for `extern "C"` in a sense.
+
+From this perspective, CXX is a lower level tool than the bindgens. Just as
+bindgen and cbindgen are built on top of `extern "C"`, it makes sense to think
+about higher level tools built on top of CXX. Such a tool might consume a C++
+header and/or Rust module (and/or IDL like Thrift) and emit the corresponding
+safe cxx::bridge language boundary, leveraging CXX's static analysis and
+underlying implementation of that boundary. We are beginning to see this space
+explored by the [autocxx] tool, though nothing yet ready for broad use in the
+way that CXX on its own is.
+
+[autocxx]: https://github.com/google/autocxx
+
+But note in other ways CXX is higher level than the bindgens, with rich support
+for common standard library types. CXX's types serve as an intuitive vocabulary
+for designing a good boundary between components in different languages.
diff --git a/book/src/extern-c++.md b/book/src/extern-c++.md
new file mode 100644
index 0000000..c015b03
--- /dev/null
+++ b/book/src/extern-c++.md
@@ -0,0 +1,315 @@
+{{#title extern "C++" — Rust ♡ C++}}
+# extern "C++"
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        include!("path/to/header.h");
+        include!("path/to/another.h");
+
+        ...
+    }
+}
+```
+
+The `extern "C++"` section of a CXX bridge declares C++ types and signatures to
+be made available to Rust, and gives the paths of the header(s) which contain
+the corresponding C++ declarations.
+
+A bridge module may contain zero or more extern "C++" blocks.
+
+## Opaque C++ types
+
+Type defined in C++ that are made available to Rust, but only behind an
+indirection.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "C++" {
+        # include!("path/to/header.h");
+        #
+        type MyType;
+        type MyOtherType;
+    }
+# }
+```
+
+For example in the ***[Tutorial](tutorial.md)*** we saw `BlobstoreClient`
+implemented as an opaque C++ type. The blobstore client was created in C++ and
+returned to Rust by way of a UniquePtr.
+
+**Mutability:** Unlike extern Rust types and shared types, an extern C++ type is
+not permitted to be passed by plain mutable reference `&mut MyType` across the
+FFI bridge. For mutation support, the bridge is required to use `Pin<&mut
+MyType>`. This is to safeguard against things like mem::swap-ing the contents of
+two mutable references, given that Rust doesn't have information about the size
+of the underlying object and couldn't invoke an appropriate C++ move constructor
+anyway.
+
+**Thread safety:** Be aware that CXX does not assume anything about the thread
+safety of your extern C++ types. In other words the `MyType` etc bindings which
+CXX produces for you in Rust *do not* come with `Send` and `Sync` impls. If you
+are sure that your C++ type satisfies the requirements of `Send` and/or `Sync`
+and need to leverage that fact from Rust, you must provide your own unsafe
+marker trait impls.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+#     extern "C++" {
+#         include!("path/to/header.h");
+#
+#         type MyType;
+#     }
+# }
+#
+/// The C++ implementation of MyType is thread safe.
+unsafe impl Send for ffi::MyType {}
+unsafe impl Sync for ffi::MyType {}
+```
+
+Take care in doing this because thread safety in C++ can be extremely tricky to
+assess if you are coming from a Rust background. For example the
+`BlobstoreClient` type in the tutorial is *not thread safe* despite doing only
+completely innocuous things in its implementation. Concurrent calls to the `tag`
+member function trigger a data race on the `blobs` map.
+
+## Functions and member functions
+
+This largely follows the same principles as ***[extern
+"Rust"](extern-rust.md)*** functions and methods. In particular, any signature
+with a `self` parameter is interpreted as a C++ non-static member function and
+exposed to Rust as a method.
+
+The programmer **does not** need to promise that the signatures they have typed
+in are accurate; that would be unreasonable. CXX performs static assertions that
+the signatures exactly correspond with what is declared in C++. Rather, the
+programmer is only on the hook for things that C++'s static information is not
+precise enough to capture, i.e. things that would only be represented at most by
+comments in the C++ code unintelligible to a static assertion: namely whether
+the C++ function is safe or unsafe to be called from Rust.
+
+**Safety:** the extern "C++" block is responsible for deciding whether to expose
+each signature inside as safe-to-call or unsafe-to-call. If an extern block
+contains at least one safe-to-call signature, it must be written as an `unsafe
+extern` block, which serves as an item level unsafe block to indicate that an
+unchecked safety claim is being made about the contents of the block.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        # include!("path/to/header.h");
+        #
+        fn f();  // safe to call
+    }
+
+    extern "C++" {
+        unsafe fn g();  // unsafe to call
+    }
+}
+```
+
+
+## Reusing existing binding types
+
+Extern C++ types support a syntax for declaring that a Rust binding of the
+correct C++ type already exists outside of the current bridge module. This
+avoids generating a fresh new binding which Rust's type system would consider
+non-interchangeable with the first.
+
+```rust,noplayground
+#[cxx::bridge(namespace = "path::to")]
+mod ffi {
+    extern "C++" {
+        type MyType = crate::existing::MyType;
+    }
+
+    extern "Rust" {
+        fn f(x: &MyType) -> usize;
+    }
+}
+```
+
+In this case rather than producing a unique new Rust type `ffi::MyType` for the
+Rust binding of C++'s `::path::to::MyType`, CXX will reuse the already existing
+binding at `crate::existing::MyType` in expressing the signature of `f` and any
+other uses of `MyType` within the bridge module.
+
+CXX safely validates that `crate::existing::MyType` is in fact a binding for the
+right C++ type `::path::to::MyType` by generating a static assertion based on
+`crate::existing::MyType`'s implementation of [`ExternType`], which is a trait
+automatically implemented by CXX for bindings that it generates but can also be
+manually implemented as described below.
+
+[`ExternType`]: https://docs.rs/cxx/*/cxx/trait.ExternType.html
+
+`ExternType` serves the following two related use cases.
+
+#### Safely unifying occurrences of an extern type across bridges
+
+In the following snippet, two #\[cxx::bridge\] invocations in different files
+(possibly different crates) both contain function signatures involving the same
+C++ type `example::Demo`. If both were written just containing `type Demo;`,
+then both macro expansions would produce their own separate Rust type called
+`Demo` and thus the compiler wouldn't allow us to take the `Demo` returned by
+`file1::ffi::create_demo` and pass it as the `Demo` argument accepted by
+`file2::ffi::take_ref_demo`. Instead, one of the two `Demo`s has been defined as
+an extern type alias of the other, making them the same type in Rust.
+
+```rust,noplayground
+// file1.rs
+#[cxx::bridge(namespace = "example")]
+pub mod ffi {
+    unsafe extern "C++" {
+        type Demo;
+
+        fn create_demo() -> UniquePtr<Demo>;
+    }
+}
+```
+
+```rust,noplayground
+// file2.rs
+#[cxx::bridge(namespace = "example")]
+pub mod ffi {
+    unsafe extern "C++" {
+        type Demo = crate::file1::ffi::Demo;
+
+        fn take_ref_demo(demo: &Demo);
+    }
+}
+```
+
+#### Integrating with bindgen-generated or handwritten unsafe bindings
+
+Handwritten `ExternType` impls make it possible to plug in a data structure
+emitted by bindgen as the definition of a C++ type emitted by CXX.
+
+By writing the unsafe `ExternType` impl, the programmer asserts that the C++
+namespace and type name given in the type id refers to a C++ type that is
+equivalent to Rust type that is the `Self` type of the impl.
+
+```rust,noplayground
+mod folly_sys;  // the bindgen-generated bindings
+
+use cxx::{type_id, ExternType};
+
+unsafe impl ExternType for folly_sys::StringPiece {
+    type Id = type_id!("folly::StringPiece");
+    type Kind = cxx::kind::Opaque;
+}
+
+#[cxx::bridge(namespace = "folly")]
+pub mod ffi {
+    unsafe extern "C++" {
+        include!("rust_cxx_bindings.h");
+
+        type StringPiece = crate::folly_sys::StringPiece;
+
+        fn print_string_piece(s: &StringPiece);
+    }
+}
+
+// Now if we construct a StringPiece or obtain one through one
+// of the bindgen-generated signatures, we are able to pass it
+// along to ffi::print_string_piece.
+```
+
+The `ExternType::Id` associated type encodes a type-level representation of the
+type's C++ namespace and type name. It will always be defined using the
+`type_id!` macro exposed in the cxx crate.
+
+The `ExternType::Kind` associated type will always be either
+[`cxx::kind::Opaque`] or [`cxx::kind::Trivial`] identifying whether a C++ type
+is soundly relocatable by Rust's move semantics. A C++ type is only okay to hold
+and pass around by value in Rust if its [move constructor is trivial] and it has
+no destructor. In CXX, these are called Trivial extern C++ types, while types
+with nontrivial move behavior or a destructor must be considered Opaque and
+handled by Rust only behind an indirection, such as a reference or UniquePtr.
+
+[`cxx::kind::Opaque`]: https://docs.rs/cxx/*/cxx/kind/enum.Opaque.html
+[`cxx::kind::Trivial`]: https://docs.rs/cxx/*/cxx/kind/enum.Trivial.html
+[move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible
+
+If you believe your C++ type reflected by the ExternType impl is indeed fine to
+hold by value and move in Rust, you can specify:
+
+```rust,noplayground
+# unsafe impl cxx::ExternType for TypeName {
+#     type Id = cxx::type_id!("name::space::of::TypeName");
+    type Kind = cxx::kind::Trivial;
+# }
+```
+
+which will enable you to pass it into C++ functions by value, return it by
+value, and include it in `struct`s that you have declared to `cxx::bridge`. Your
+claim about the triviality of the C++ type will be checked by a `static_assert`
+in the generated C++ side of the binding.
+
+## Explicit shim trait impls
+
+This is a somewhat niche feature, but important when you need it.
+
+CXX's support for C++'s std::unique\_ptr and std::vector is built on a set of
+internal trait impls connecting the Rust API of UniquePtr and CxxVector to
+underlying template instantiations performed by the C++ compiler.
+
+When reusing a binding type across multiple bridge modules as described in the
+previous section, you may find that your code needs some trait impls which CXX
+hasn't decided to generate.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        include!("path/to/header.h");
+
+        type A;
+        type B;
+
+        // Okay: CXX sees UniquePtr<B> using a type B defined within the same
+        // bridge, and automatically emits the right template instantiations
+        // corresponding to std::unique_ptr<B>.
+        fn get_b() -> UniquePtr<B>;
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    extern "C++" {
+        type A = crate::ffi1::A;
+
+        // Rust trait error: CXX processing this module has no visibility into
+        // whether template instantiations corresponding to std::unique_ptr<A>
+        // have already been emitted by the upstream library, so it does not
+        // emit them here. If the upstream library does not have any signatures
+        // involving UniquePtr<A>, an explicit instantiation of the template
+        // needs to be requested in one module or the other.
+        fn get_a() -> UniquePtr<A>;
+    }
+}
+```
+
+You can request a specific template instantiation at a particular location in
+the Rust crate hierarchy by writing `impl UniquePtr<A> {}` inside of the bridge
+module which defines `A` but does not otherwise contain any use of
+`UniquePtr<A>`.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        include!("path/to/header.h");
+
+        type A;
+        type B;
+
+        fn get_b() -> UniquePtr<B>;
+    }
+
+    impl UniquePtr<A> {}  // explicit instantiation
+}
+```
diff --git a/book/src/extern-rust.md b/book/src/extern-rust.md
new file mode 100644
index 0000000..a9ad8b6
--- /dev/null
+++ b/book/src/extern-rust.md
@@ -0,0 +1,165 @@
+{{#title extern "Rust" — Rust ♡ C++}}
+# extern "Rust"
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+
+    }
+}
+```
+
+The `extern "Rust"` section of a CXX bridge declares Rust types and signatures
+to be made available to C++.
+
+The CXX code generator uses your extern "Rust" section(s) to produce a C++
+header file containing the corresponding C++ declarations. The generated header
+has the same path as the Rust source file containing the bridge, except with a
+`.rs.h` file extension.
+
+A bridge module may contain zero or more extern "Rust" blocks.
+
+## Opaque Rust types
+
+Types defined in Rust that are made available to C++, but only behind an
+indirection.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type MyType;
+        type MyOtherType;
+        type OneMoreType;
+    }
+# }
+```
+
+For example in the ***[Tutorial](tutorial.md)*** we saw `MultiBuf` used in this
+way. Rust code created the `MultiBuf`, passed a `&mut MultiBuf` to C++, and C++
+later passed a `&mut MultiBuf` back across the bridge to Rust.
+
+Another example is the one on the ***[Box\<T\>](binding/box.md)*** page, which
+exposes the Rust standard library's `std::fs::File` to C++ as an opaque type in
+a similar way but with Box as the indirection rather than &mut.
+
+The types named as opaque types (`MyType` etc) refer to types in the `super`
+module, the parent module of the CXX bridge. You can think of an opaque type `T`
+as being like a re-export `use super::T` made available to C++ via the generated
+header.
+
+Opaque types are currently required to be [`Sized`] and [`Unpin`]. In
+particular, a trait object `dyn MyTrait` or slice `[T]` may not be used for an
+opaque Rust type. These restrictions may be lifted in the future.
+
+[`Sized`]: https://doc.rust-lang.org/std/marker/trait.Sized.html
+[`Unpin`]: https://doc.rust-lang.org/std/marker/trait.Unpin.html
+
+For now, types used as extern Rust types are required to be defined by the same
+crate that contains the bridge using them. This restriction may be lifted in the
+future.
+
+The bridge's parent module will contain the appropriate imports or definitions
+for these types.
+
+```rust,noplayground
+use path::to::MyType;
+
+pub struct MyOtherType {
+    ...
+}
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MyType;
+#         type MyOtherType;
+#     }
+# }
+```
+
+## Functions
+
+Rust functions made callable to C++.
+
+Just like for opaque types, these functions refer implicitly to something in
+scope in the `super` module, whether defined there or imported by some `use`
+statement.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        struct MyType;
+        fn f() -> Box<MyType>;
+    }
+}
+
+struct MyType(i32);
+
+fn f() -> Box<MyType> {
+    return Box::new(MyType(1));
+}
+```
+
+Extern Rust function signature may consist of types defined in the bridge,
+primitives, and [any of these additional bindings](bindings.md).
+
+## Methods
+
+Any signature with a `self` parameter is interpreted as a Rust method and
+exposed to C++ as a non-static member function.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type MyType;
+        fn f(&self) -> usize;
+    }
+# }
+```
+
+The `self` parameter may be a shared reference `&self`, an exclusive reference
+`&mut self`, or a pinned reference `self: Pin<&mut Self>`. A by-value `self` is
+not currently supported.
+
+If the surrounding `extern "Rust"` block contains exactly one extern type, that
+type is implicitly the receiver for a `&self` or `&mut self` method. If the
+surrounding block contains *more than one* extern type, a receiver type must be
+provided explicitly for the self parameter, or you can consider splitting into
+multiple extern blocks.
+
+```rust,noplayground
+# #[cxx::bridge]
+# mod ffi {
+    extern "Rust" {
+        type First;
+        type Second;
+        fn bar(self: &First);
+        fn foo(self: &mut Second);
+    }
+# }
+```
+
+## Functions with explicit lifetimes
+
+An extern Rust function signature is allowed to contain explicit lifetimes but
+in this case the function must be declared unsafe-to-call. This is pretty
+meaningless given we're talking about calls from C++, but at least it draws some
+extra attention from the caller that they may be responsible for upholding some
+atypical lifetime relationship.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MyType;
+        unsafe fn f<'a>(&'a self, s: &str) -> &'a str;
+    }
+}
+```
+
+Bounds on a lifetime (like `<'a, 'b: 'a>`) are not currently supported. Nor are
+type parameters or where-clauses.
diff --git a/book/src/index.md b/book/src/index.md
new file mode 100644
index 0000000..7b03e7e
--- /dev/null
+++ b/book/src/index.md
@@ -0,0 +1,83 @@
+<div class="badges">
+<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" alt="docs-rs" height="28" class="badge"></a>
+</div>
+
+# CXX — safe interop between Rust and C++
+
+This library provides a safe mechanism for calling C++ code from Rust and Rust
+code from C++. It carves out a regime of commonality where Rust and C++ are
+semantically very similar and guides the programmer to express their language
+boundary effectively within this regime. CXX fills in the low level stuff so
+that you get a safe binding, preventing the pitfalls of doing a foreign function
+interface over unsafe C-style signatures.
+
+<div style="height:226px;padding:34px 0 24px">
+<object type="image/svg+xml" data="overview.svg"></object>
+</div>
+
+From a high level description of the language boundary, CXX uses static analysis
+of the types and function signatures to protect both Rust's and C++'s
+invariants. Then it uses a pair of code generators to implement the boundary
+efficiently on both sides together with any necessary static assertions for
+later in the build process to verify correctness.
+
+The resulting FFI bridge operates at zero or negligible overhead, i.e. no
+copying, no serialization, no memory allocation, no runtime checks needed.
+
+The FFI signatures are able to use native data structures from whichever side
+they please. In addition, CXX provides builtin bindings for key standard library
+types like strings, vectors, Box, unique\_ptr, etc to expose an idiomatic API on
+those types to the other language.
+
+## Example
+
+In this example we are writing a Rust application that calls a C++ client of a
+large-file blobstore service. The blobstore supports a `put` operation for a
+discontiguous buffer upload. For example we might be uploading snapshots of a
+circular buffer which would tend to consist of 2 pieces, or fragments of a file
+spread across memory for some other reason (like a rope data structure).
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MultiBuf;
+
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        include!("example/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
+    }
+}
+```
+
+Now we simply provide Rust definitions of all the things in the `extern "Rust"`
+block and C++ definitions of all the things in the `extern "C++"` block, and get
+to call back and forth safely.
+
+The [***Tutorial***](tutorial.md) chapter walks through a fleshed out version of
+this blobstore example in full detail, including all of the Rust code and all of
+the C++ code. The code is also provided in runnable form in the *demo* directory
+of <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that
+directory.
+
+- [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs)
+- [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h)
+- [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc)
+
+The key takeaway, which is enabled by the CXX library, is that the Rust code in
+main.rs is 100% ordinary safe Rust code working idiomatically with Rust types
+while the C++ code in blobstore.cc is 100% ordinary C++ code working
+idiomatically with C++ types. The Rust code feels like Rust and the C++ code
+feels like C++, not like C-style "FFI glue".
+
+<br>
+
+***Chapter outline:** See the hamburger menu in the top left if you are on a
+small screen and it didn't open with a sidebar by default.*
diff --git a/book/src/overview.svg b/book/src/overview.svg
new file mode 100644
index 0000000..850e034
--- /dev/null
+++ b/book/src/overview.svg
@@ -0,0 +1,131 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="696" height="224">
+    <style>line, path, circle,rect,polygon {
+                          stroke: black;
+                          stroke-width: 2;
+                          stroke-opacity: 1;
+                          fill-opacity: 1;
+                          stroke-linecap: round;
+                          stroke-linejoin: miter;
+                        }
+
+                    text {
+                        fill: black;
+                        }
+                        rect.backdrop{
+                            stroke: none;
+                            fill: white;
+                            fill-opacity: 0;
+                        }
+                        .broken{
+                            stroke-dasharray: 8;
+                        }
+                        .filled{
+                            fill: black;
+                        }
+                        .bg_filled{
+                            fill: white;
+                        }
+                        .nofill{
+                            fill: white;
+                            fill-opacity: 0;
+                        }
+
+                        text {
+                         font-family: monospace;
+                         font-size: 14px;
+                        }
+
+                        .end_marked_arrow{
+                            marker-end: url(#arrow);
+                         }
+                        .start_marked_arrow{
+                            marker-start: url(#arrow);
+                         }
+
+                        .end_marked_diamond{
+                            marker-end: url(#diamond);
+                         }
+                        .start_marked_diamond{
+                            marker-start: url(#diamond);
+                         }
+
+                        .end_marked_circle{
+                            marker-end: url(#circle);
+                         }
+                        .start_marked_circle{
+                            marker-start: url(#circle);
+                         }
+
+                        .end_marked_open_circle{
+                            marker-end: url(#open_circle);
+                         }
+                        .start_marked_open_circle{
+                            marker-start: url(#open_circle);
+                         }
+
+                        .end_marked_big_open_circle{
+                            marker-end: url(#big_open_circle);
+                         }
+                        .start_marked_big_open_circle{
+                            marker-start: url(#big_open_circle);
+                         }
+
+                         
+                        </style>
+    <defs>
+        <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,0 0,4 4,2 0,0"></polygon>
+        </marker>
+        <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon>
+        </marker>
+        <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="filled"></circle>
+        </marker>
+        <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="2" class="bg_filled"></circle>
+        </marker>
+        <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
+            <circle cx="4" cy="4" r="3" class="bg_filled"></circle>
+        </marker>
+    </defs>
+    <rect class="backdrop" x="0" y="0" width="696" height="224"></rect>
+    <rect x="148" y="168" width="136" height="32" class="solid nofill" rx="4"></rect>
+    <text x="162" y="188" >Rust bindings</text>
+    <rect x="412" y="168" width="128" height="32" class="solid nofill" rx="4"></rect>
+    <text x="426" y="188" >C++ bindings</text>
+    <text x="272" y="28" >#[cxx::bridge] mod</text>
+    <text x="250" y="44" >description of boundary</text>
+    <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
+    <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
+    <text x="74" y="140" >Safe</text>
+    <text x="34" y="156" >straightforward</text>
+    <text x="530" y="156" >Straightforward</text>
+    <polygon points="48,180 40,184 48,188" class="filled"></polygon>
+    <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line>
+    <polygon points="296,180 288,184 296,188" class="filled"></polygon>
+    <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line>
+    <polygon points="552,180 544,184 552,188" class="filled"></polygon>
+    <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line>
+    <text x="2" y="188" >Rust</text>
+    <text x="2" y="204" >code</text>
+    <text x="658" y="204" >code</text>
+    <text x="202" y="108" >Macro expansion</text>
+    <text x="370" y="108" >Code generation</text>
+    <text x="58" y="172" >Rust APIs</text>
+    <text x="298" y="172" >Hidden C ABI</text>
+    <text x="562" y="172" >C++ APIs</text>
+    <text x="658" y="188" >C++</text>
+    <g>
+        <path d="M 228,8 A 8,8 0,0,0 220,16" class="nofill"></path>
+        <line x1="228" y1="8" x2="468" y2="8" class="solid"></line>
+        <path d="M 468,8 A 8,8 0,0,1 476,16" class="nofill"></path>
+        <line x1="220" y1="16" x2="220" y2="48" class="solid"></line>
+        <line x1="476" y1="16" x2="476" y2="48" class="solid"></line>
+        <path d="M 220,48 A 8,8 0,0,0 228,56" class="nofill"></path>
+        <line x1="228" y1="56" x2="468" y2="56" class="solid"></line>
+        <line x1="348" y1="56" x2="348" y2="120" class="solid"></line>
+        <path d="M 476,48 A 8,8 0,0,1 468,56" class="nofill"></path>
+        <line x1="220" y1="120" x2="476" y2="120" class="solid"></line>
+    </g>
+</svg>
diff --git a/book/src/reference.md b/book/src/reference.md
new file mode 100644
index 0000000..62ca35c
--- /dev/null
+++ b/book/src/reference.md
@@ -0,0 +1,29 @@
+{{#title The bridge module — Rust ♡ C++}}
+# The bridge module reference
+
+The ***[Core concepts](concepts.md)*** in chapter 2 covered the high level model
+that CXX uses to represent a language boundary. This chapter builds on that one
+to document an exhaustive reference on the syntax and functionality of
+\#\[cxx::bridge\].
+
+- ***[extern "Rust"](extern-rust.md)*** &mdash; exposing opaque Rust types, Rust
+  functions, Rust methods to C++; functions with lifetimes.
+
+- ***[extern "C++"](extern-c++.md)*** &mdash; binding opaque C++ types, C++
+  functions, C++ member functions; sharing an opaque type definition across
+  multiple bridge modules or different crates; using bindgen-generated data
+  structures across a CXX bridge; Rust orphan-rule-compatible way to request
+  that particular glue code be emitted in a specific bridge module.
+
+- ***[Shared types](shared.md)*** &mdash; shared structs; shared enums; using
+  Rust as source of truth vs C++ as source of truth.
+
+- ***[Attributes](attributes.md)*** &mdash; working with namespaces; giving
+  functions a different name in their non-native language.
+
+- ***[Async functions](async.md)*** &mdash; integrating async C++ with async
+  Rust.
+
+- ***[Error handling](binding/result.md)*** &mdash; representing fallibility on
+  the language boundary; accessing a Rust error message from C++; customizing
+  the set of caught exceptions and their conversion to a Rust error message.
diff --git a/book/src/shared.md b/book/src/shared.md
new file mode 100644
index 0000000..09465fe
--- /dev/null
+++ b/book/src/shared.md
@@ -0,0 +1,181 @@
+{{#title Shared types — Rust ♡ C++}}
+# Shared types
+
+Shared types enable *both* languages to have visibility into the internals of a
+type. This is in contrast to opaque Rust types and opaque C++ types, for which
+only one side gets to manipulate the internals.
+
+Unlike opaque types, the FFI bridge is allowed to pass and return shared types
+by value.
+
+The order in which shared types are written is not important. C++ is order
+sensitive but CXX will topologically sort and forward-declare your types as
+necessary.
+
+## Shared structs and enums
+
+For enums, only C-like a.k.a. unit variants are currently supported.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    struct PlayingCard {
+        suit: Suit,
+        value: u8,  // A=1, J=11, Q=12, K=13
+    }
+
+    enum Suit {
+        Clubs,
+        Diamonds,
+        Hearts,
+        Spades,
+    }
+
+    unsafe extern "C++" {
+        fn deck() -> Vec<PlayingCard>;
+        fn sort(cards: &mut Vec<PlayingCard>);
+    }
+}
+```
+
+## The generated data structures
+
+Shared structs compile to an aggregate-initialization compatible C++ struct.
+
+Shared enums compile to a C++ `enum class` with a sufficiently sized integral
+base type decided by CXX.
+
+```cpp
+// generated header
+
+struct PlayingCard final {
+  Suit suit;
+  uint8_t value;
+};
+
+enum class Suit : uint8_t {
+  Clubs = 0,
+  Diamonds = 1,
+  Hearts = 2,
+  Spades = 3,
+};
+```
+
+Because it is not UB in C++ for an `enum class` to hold a value different from
+all of the listed variants, we use a Rust representation for shared enums that
+is compatible with this. The API you'll get is something like:
+
+```rust,noplayground
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[repr(transparent)]
+pub struct Suit {
+    pub repr: u8,
+}
+#[allow(non_upper_case_globals)]
+impl Suit {
+    pub const Clubs: Self = Suit { repr: 0 };
+    pub const Diamonds: Self = Suit { repr: 1 };
+    pub const Hearts: Self = Suit { repr: 2 };
+    pub const Spades: Self = Suit { repr: 3 };
+}
+```
+
+Notice you're free to treat the enum as an integer in Rust code via the public
+`repr` field.
+
+Pattern matching with `match` still works but will require you to write wildcard
+arms to handle the situation of an enum value that is not one of the listed
+variants.
+
+```rust,noplayground
+fn main() {
+    let suit: Suit = /*...*/;
+    match suit {
+        Suit::Clubs => ...,
+        Suit::Diamonds => ...,
+        Suit::Hearts => ...,
+        Suit::Spades => ...,
+        _ => ...,  // fallback arm
+    }
+}
+```
+
+## Enum discriminants
+
+You may provide explicit discriminants for some or all of the enum variants, in
+which case those numbers will be propagated into the generated C++ `enum class`.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    enum SmallPrime {
+        Two = 2,
+        Three = 3,
+        Five = 5,
+        Seven = 7,
+    }
+}
+```
+
+Variants without an explicit discriminant are assigned the previous discriminant
+plus 1. If the first variant has not been given an explicit discriminant, it is
+assigned discriminant 0.
+
+By default CXX represents your enum using the smallest integer type capable of
+fitting all the discriminants (whether explicit or implicit). If you need a
+different representation for reasons, provide a `repr` attribute.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    #[repr(i32)]
+    enum Enum {
+        Zero,
+        One,
+        Five = 5,
+        Six,
+    }
+}
+```
+
+```cpp
+// generated header
+
+enum class Enum : int32_t {
+  Zero = 0,
+  One = 1,
+  Five = 5,
+  Six = 6,
+};
+```
+
+## Extern enums
+
+If you need to interoperate with an already existing enum for which an existing
+C++ definition is the source of truth, make sure that definition is provided by
+some header in the bridge and then declare your enum *additionally* as an extern
+C++ type.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    enum Enum {
+        Yes,
+        No,
+    }
+
+    extern "C++" {
+        include!("path/to/the/header.h");
+        type Enum;
+    }
+}
+```
+
+CXX will recognize this pattern and, instead of generating a C++ definition of
+the enum, will instead generate C++ static assertions asserting that the
+variants and discriminant values and integer representation written in Rust all
+correctly match the existing C++ enum definition.
+
+Extern enums support all the same features as ordinary shared enums (explicit
+discriminants, repr). Again, CXX will static assert that all of those things you
+wrote are correct.
diff --git a/book/src/tutorial.md b/book/src/tutorial.md
new file mode 100644
index 0000000..a375ea0
--- /dev/null
+++ b/book/src/tutorial.md
@@ -0,0 +1,687 @@
+{{#title Tutorial — Rust ♡ C++}}
+# Tutorial: CXX blobstore client
+
+This example walks through a Rust application that calls into a C++ client of a
+blobstore service. In fact we'll see calls going in both directions: Rust to C++
+as well as C++ to Rust. For your own use case it may be that you need just one
+of these directions.
+
+All of the code involved in the example is shown on this page, but it's also
+provided in runnable form in the *demo* directory of
+<https://github.com/dtolnay/cxx>. To try it out directly, run `cargo run` from
+that directory.
+
+This tutorial assumes you've read briefly about **shared structs**, **opaque
+types**, and **functions** in the [*Core concepts*](concepts.md) page.
+
+## Creating the project
+
+We'll use Cargo, which is the build system commonly used by open source Rust
+projects. (CXX works with other build systems too; refer to chapter 5.)
+
+Create a blank Cargo project: `mkdir cxx-demo`; `cd cxx-demo`; `cargo init`.
+
+Edit the Cargo.toml to add a dependency on the `cxx` crate:
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "cxx-demo"
+# version = "0.1.0"
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+```
+
+We'll revisit this Cargo.toml later when we get to compiling some C++ code.
+
+## Defining the language boundary
+
+CXX relies on a description of the function signatures that will be exposed from
+each language to the other. You provide this description using `extern` blocks
+in a Rust module annotated with the `#[cxx::bridge]` attribute macro.
+
+We'll open with just the following at the top of src/main.rs and walk through
+each item in detail.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+
+}
+#
+# fn main() {}
+```
+
+The contents of this module will be everything that needs to be agreed upon by
+both sides of the FFI boundary.
+
+## Calling a C++ function from Rust
+
+Let's obtain an instance of the C++ blobstore client, a class `BlobstoreClient`
+defined in C++.
+
+We'll treat `BlobstoreClient` as an *opaque type* in CXX's classification so
+that Rust does not need to assume anything about its implementation, not even
+its size or alignment. In general, a C++ type might have a move-constructor
+which is incompatible with Rust's move semantics, or may hold internal
+references which cannot be modeled by Rust's borrowing system. Though there are
+alternatives, the easiest way to not care about any such thing on an FFI
+boundary is to require no knowledge about a type by treating it as opaque.
+
+Opaque types may only be manipulated behind an indirection such as a reference
+`&`, a Rust `Box`, or a `UniquePtr` (Rust binding of `std::unique_ptr`). We'll
+add a function through which C++ can return a `std::unique_ptr<BlobstoreClient>`
+to Rust.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("cxx-demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+    }
+}
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+}
+```
+
+The nature of `unsafe` extern blocks is clarified in more detail in the
+[*extern "C++"*](extern-c++.md) chapter. In brief: the programmer is **not**
+promising that the signatures they have typed in are accurate; that would be
+unreasonable. CXX performs static assertions that the signatures exactly match
+what is declared in C++. Rather, the programmer is only on the hook for things
+that C++'s semantics are not precise enough to capture, i.e. things that would
+only be represented at most by comments in the C++ code. In this case, it's
+whether `new_blobstore_client` is safe or unsafe to call. If that function said
+something like "must be called at most once or we'll stomp yer memery", Rust
+would instead want to expose it as `unsafe fn new_blobstore_client`, this time
+inside a safe `extern "C++"` block because the programmer is no longer on the
+hook for any safety claim about the signature.
+
+If you build this file right now with `cargo build`, it won't build because we
+haven't written a C++ implementation of `new_blobstore_client` nor instructed
+Cargo about how to link it into the resulting binary. You'll see an error from
+the linker like this:
+
+```console
+error: linking with `cc` failed: exit code: 1
+ |
+ = /bin/ld: target/debug/deps/cxx-demo-7cb7fddf3d67d880.rcgu.o: in function `cxx_demo::ffi::new_blobstore_client':
+   src/main.rs:1: undefined reference to `cxxbridge1$new_blobstore_client'
+   collect2: error: ld returned 1 exit status
+```
+
+## Adding in the C++ code
+
+In CXX's integration with Cargo, all #include paths begin with a crate name by
+default (when not explicitly selected otherwise by a crate; see
+`CFG.include_prefix` in chapter 5). That's why we see
+`include!("cxx-demo/include/blobstore.h")` above &mdash; we'll be putting the
+C++ header at relative path `include/blobstore.h` within the Rust crate. If your
+crate is named something other than `cxx-demo` according to the `name` field in
+Cargo.toml, you will need to use that name everywhere in place of `cxx-demo`
+throughout this tutorial.
+
+```cpp
+// include/blobstore.h
+
+#pragma once
+#include <memory>
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+};
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp
+// src/blobstore.cc
+
+#include "cxx-demo/include/blobstore.h"
+
+BlobstoreClient::BlobstoreClient() {}
+
+std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+  return std::unique_ptr<BlobstoreClient>(new BlobstoreClient());
+}
+```
+
+Using `std::make_unique` would work too, as long as you pass `-std=c++14` to the
+C++ compiler as described later on.
+
+The placement in *include/* and *src/* is not significant; you can place C++
+code anywhere else in the crate as long as you use the right paths throughout
+the tutorial.
+
+Be aware that *CXX does not look at any of these files.* You're free to put
+arbitrary C++ code in here, #include your own libraries, etc. All we do is emit
+static assertions against what you provide in the headers.
+
+## Compiling the C++ code with Cargo
+
+Cargo has a [build scripts] feature suitable for compiling non-Rust code.
+
+We need to introduce a new build-time dependency on CXX's C++ code generator in
+Cargo.toml:
+
+```toml,hidelines
+## Cargo.toml
+# [package]
+# name = "cxx-demo"
+# version = "0.1.0"
+# edition = "2018"
+
+[dependencies]
+cxx = "1.0"
+
+[build-dependencies]
+cxx-build = "1.0"
+```
+
+Then add a build.rs build script adjacent to Cargo.toml to run the cxx-build
+code generator and C++ compiler. The relevant arguments are the path to the Rust
+source file containing the cxx::bridge language boundary definition, and the
+paths to any additional C++ source files to be compiled during the Rust crate's
+build.
+
+```rust,noplayground
+// build.rs
+
+fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/blobstore.cc")
+        .compile("cxx-demo");
+}
+```
+
+This build.rs would also be where you set up C++ compiler flags, for example if
+you'd like to have access to `std::make_unique` from C++14. See the page on
+***[Cargo-based builds](build/cargo.md)*** for more details about CXX's Cargo
+integration.
+
+```rust,noplayground
+# // build.rs
+#
+# fn main() {
+    cxx_build::bridge("src/main.rs")
+        .file("src/blobstore.cc")
+        .flag_if_supported("-std=c++14")
+        .compile("cxx-demo");
+# }
+```
+
+[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html
+
+The project should now build and run successfully, though not do anything useful
+yet.
+
+```console
+cxx-demo$  cargo run
+  Compiling cxx-demo v0.1.0
+  Finished dev [unoptimized + debuginfo] target(s) in 0.34s
+  Running `target/debug/cxx-demo`
+
+cxx-demo$
+```
+
+## Calling a Rust function from C++
+
+Our C++ blobstore supports a `put` operation for a discontiguous buffer upload.
+For example we might be uploading snapshots of a circular buffer which would
+tend to consist of 2 pieces, or fragments of a file spread across memory for
+some other reason (like a rope data structure).
+
+We'll express this by handing off an iterator over contiguous borrowed chunks.
+This loosely resembles the API of the widely used `bytes` crate's `Buf` trait.
+During a `put`, we'll make C++ call back into Rust to obtain contiguous chunks
+of the upload (all with no copying or allocation on the language boundary). In
+reality the C++ client might contain some sophisticated batching of chunks
+and/or parallel uploading that all of this ties into.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type MultiBuf;
+
+        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        include!("cxx-demo/include/blobstore.h");
+
+        type BlobstoreClient;
+
+        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+        fn put(&self, parts: &mut MultiBuf) -> u64;
+    }
+}
+#
+# fn main() {
+#     let client = ffi::new_blobstore_client();
+# }
+```
+
+Any signature having a `self` parameter (the Rust name for C++'s `this`) is
+considered a method / non-static member function. If there is only one `type` in
+the surrounding extern block, it'll be a method of that type. If there is more
+than one `type`, you can disambiguate which one a method belongs to by writing
+`self: &BlobstoreClient` in the argument list.
+
+As usual, now we need to provide Rust definitions of everything declared by the
+`extern "Rust"` block and a C++ definition of the new signature declared by the
+`extern "C++"` block.
+
+```rust,noplayground
+// src/main.rs
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#     }
+# }
+
+// An iterator over contiguous chunks of a discontiguous file object. Toy
+// implementation uses a Vec<Vec<u8>> but in reality this might be iterating
+// over some more complex Rust data structure like a rope, or maybe loading
+// chunks lazily from somewhere.
+pub struct MultiBuf {
+    chunks: Vec<Vec<u8>>,
+    pos: usize,
+}
+
+pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+    let next = buf.chunks.get(buf.pos);
+    buf.pos += 1;
+    next.map(Vec::as_slice).unwrap_or(&[])
+}
+#
+# fn main() {
+#     let client = ffi::new_blobstore_client();
+# }
+```
+
+```cpp,hidelines
+// include/blobstore.h
+
+# #pragma once
+# #include <memory>
+#
+struct MultiBuf;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+};
+#
+#std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+In blobstore.cc we're able to call the Rust `next_chunk` function, exposed to
+C++ by a header `main.rs.h` generated by the CXX code generator. In CXX's Cargo
+integration this generated header has a path containing the crate name, the
+relative path of the Rust source file within the crate, and a `.rs.h` extension.
+
+```cpp,hidelines
+// src/blobstore.cc
+
+##include "cxx-demo/include/blobstore.h"
+##include "cxx-demo/src/main.rs.h"
+##include <functional>
+#
+# BlobstoreClient::BlobstoreClient() {}
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+#   return std::make_unique<BlobstoreClient>();
+# }
+
+// Upload a new blob and return a blobid that serves as a handle to the blob.
+uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+  // Traverse the caller's chunk iterator.
+  std::string contents;
+  while (true) {
+    auto chunk = next_chunk(buf);
+    if (chunk.size() == 0) {
+      break;
+    }
+    contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+  }
+
+  // Pretend we did something useful to persist the data.
+  auto blobid = std::hash<std::string>{}(contents);
+  return blobid;
+}
+```
+
+This is now ready to use. :)
+
+```rust,noplayground
+// src/main.rs
+#
+# #[cxx::bridge]
+# mod ffi {
+#     extern "Rust" {
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+#     }
+#
+#     unsafe extern "C++" {
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+#     }
+# }
+#
+# pub struct MultiBuf {
+#     chunks: Vec<Vec<u8>>,
+#     pos: usize,
+# }
+# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+#     let next = buf.chunks.get(buf.pos);
+#     buf.pos += 1;
+#     next.map(Vec::as_slice).unwrap_or(&[])
+# }
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+}
+```
+
+```console
+cxx-demo$  cargo run
+  Compiling cxx-demo v0.1.0
+  Finished dev [unoptimized + debuginfo] target(s) in 0.41s
+  Running `target/debug/cxx-demo`
+
+blobid = 9851996977040795552
+```
+
+## Interlude: What gets generated?
+
+For the curious, it's easy to look behind the scenes at what CXX has done to
+make these function calls work. You shouldn't need to do this during normal
+usage of CXX, but for the purpose of this tutorial it can be educative.
+
+CXX comprises *two* code generators: a Rust one (which is the cxx::bridge
+attribute procedural macro) and a C++ one.
+
+### Rust generated code
+
+It's easiest to view the output of the procedural macro by installing
+[cargo-expand]. Then run `cargo expand ::ffi` to macro-expand the `mod ffi`
+module.
+
+[cargo-expand]: https://github.com/dtolnay/cargo-expand
+
+```console
+cxx-demo$  cargo install cargo-expand
+cxx-demo$  cargo expand ::ffi
+```
+
+You'll see some deeply unpleasant code involving `#[repr(C)]`, `#[link_name]`,
+and `#[export_name]`.
+
+### C++ generated code
+
+For debugging convenience, `cxx_build` links all generated C++ code into Cargo's
+target directory under *target/cxxbridge/*.
+
+```console
+cxx-demo$  exa -T target/cxxbridge/
+target/cxxbridge
+├── cxx-demo
+│  └── src
+│     ├── main.rs.cc -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/sources/cxx-demo/src/main.rs.cc
+│     └── main.rs.h -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/include/cxx-demo/src/main.rs.h
+└── rust
+   └── cxx.h -> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cxx-1.0.0/include/cxx.h
+```
+
+In those files you'll see declarations or templates of any CXX Rust types
+present in your language boundary (like `rust::Slice<T>` for `&[T]`) and `extern
+"C"` signatures corresponding to your extern functions.
+
+If it fits your workflow better, the CXX C++ code generator is also available as
+a standalone executable which outputs generated code to stdout.
+
+```console
+cxx-demo$  cargo install cxxbridge-cmd
+cxx-demo$  cxxbridge src/main.rs
+```
+
+## Shared data structures
+
+So far the calls in both directions above only used **opaque types**, not
+**shared structs**.
+
+Shared structs are data structures whose complete definition is visible to both
+languages, making it possible to pass them by value across the language
+boundary. Shared structs translate to a C++ aggregate-initialization compatible
+struct exactly matching the layout of the Rust one.
+
+As the last step of this demo, we'll use a shared struct `BlobMetadata` to pass
+metadata about blobs between our Rust application and C++ blobstore client.
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    struct BlobMetadata {
+        size: usize,
+        tags: Vec<String>,
+    }
+
+    extern "Rust" {
+        // ...
+#         type MultiBuf;
+#
+#         fn next_chunk(buf: &mut MultiBuf) -> &[u8];
+    }
+
+    unsafe extern "C++" {
+        // ...
+#         include!("cxx-demo/include/blobstore.h");
+#
+#         type BlobstoreClient;
+#
+#         fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
+#         fn put(&self, parts: &mut MultiBuf) -> u64;
+        fn tag(&self, blobid: u64, tag: &str);
+        fn metadata(&self, blobid: u64) -> BlobMetadata;
+    }
+}
+#
+# pub struct MultiBuf {
+#     chunks: Vec<Vec<u8>>,
+#     pos: usize,
+# }
+# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
+#     let next = buf.chunks.get(buf.pos);
+#     buf.pos += 1;
+#     next.map(Vec::as_slice).unwrap_or(&[])
+# }
+
+fn main() {
+    let client = ffi::new_blobstore_client();
+
+    // Upload a blob.
+    let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()];
+    let mut buf = MultiBuf { chunks, pos: 0 };
+    let blobid = client.put(&mut buf);
+    println!("blobid = {}", blobid);
+
+    // Add a tag.
+    client.tag(blobid, "rust");
+
+    // Read back the tags.
+    let metadata = client.metadata(blobid);
+    println!("tags = {:?}", metadata.tags);
+}
+```
+
+```cpp,hidelines
+// include/blobstore.h
+#
+# #pragma once
+# #include "rust/cxx.h"
+# #include <memory>
+
+struct MultiBuf;
+struct BlobMetadata;
+
+class BlobstoreClient {
+public:
+  BlobstoreClient();
+  uint64_t put(MultiBuf &buf) const;
+  void tag(uint64_t blobid, rust::Str tag) const;
+  BlobMetadata metadata(uint64_t blobid) const;
+
+private:
+  class impl;
+  std::shared_ptr<impl> impl;
+};
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client();
+```
+
+```cpp,hidelines
+// src/blobstore.cc
+
+##include "cxx-demo/include/blobstore.h"
+##include "cxx-demo/src/main.rs.h"
+##include <algorithm>
+##include <functional>
+##include <set>
+##include <string>
+##include <unordered_map>
+
+// Toy implementation of an in-memory blobstore.
+//
+// In reality the implementation of BlobstoreClient could be a large
+// complex C++ library.
+class BlobstoreClient::impl {
+  friend BlobstoreClient;
+  using Blob = struct {
+    std::string data;
+    std::set<std::string> tags;
+  };
+  std::unordered_map<uint64_t, Blob> blobs;
+};
+
+BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {}
+#
+# // Upload a new blob and return a blobid that serves as a handle to the blob.
+# uint64_t BlobstoreClient::put(MultiBuf &buf) const {
+#   // Traverse the caller's chunk iterator.
+#   std::string contents;
+#   while (true) {
+#     auto chunk = next_chunk(buf);
+#     if (chunk.size() == 0) {
+#       break;
+#     }
+#     contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size());
+#   }
+#
+#   // Insert into map and provide caller the handle.
+#   auto blobid = std::hash<std::string>{}(contents);
+#   impl->blobs[blobid] = {std::move(contents), {}};
+#   return blobid;
+# }
+
+// Add tag to an existing blob.
+void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const {
+  impl->blobs[blobid].tags.emplace(tag);
+}
+
+// Retrieve metadata about a blob.
+BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const {
+  BlobMetadata metadata{};
+  auto blob = impl->blobs.find(blobid);
+  if (blob != impl->blobs.end()) {
+    metadata.size = blob->second.data.size();
+    std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(),
+                  [&](auto &t) { metadata.tags.emplace_back(t); });
+  }
+  return metadata;
+}
+#
+# std::unique_ptr<BlobstoreClient> new_blobstore_client() {
+#   return std::make_unique<BlobstoreClient>();
+# }
+```
+
+```console
+cxx-demo$  cargo run
+  Running `target/debug/cxx-demo`
+
+blobid = 9851996977040795552
+tags = ["rust"]
+```
+
+*You've now seen all the code involved in the tutorial. It's available all
+together in runnable form in the* demo *directory of
+<https://github.com/dtolnay/cxx>. You can run it directly without stepping
+through the steps above by running `cargo run` from that directory.*
+
+<br>
+
+# Takeaways
+
+The key contribution of CXX is it gives you Rust&ndash;C++ interop in which
+*all* of the Rust side of the code you write *really* looks like you are just
+writing normal Rust, and the C++ side *really* looks like you are just writing
+normal C++.
+
+You've seen in this tutorial that none of the code involved feels like C or like
+the usual perilous "FFI glue" prone to leaks or memory safety flaws.
+
+An expressive system of opaque types, shared types, and key standard library
+type bindings enables API design on the language boundary that captures the
+proper ownership and borrowing contracts of the interface.
+
+CXX plays to the strengths of the Rust type system *and* C++ type system *and*
+the programmer's intuitions. An individual working on the C++ side without a
+Rust background, or the Rust side without a C++ background, will be able to
+apply all their usual intuitions and best practices about development in their
+language to maintain a correct FFI.
+
+<br><br>

From 0f0162f37da0a34981acc66fd7e4dafe682f9789 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:30:10 +0000
Subject: [PATCH 1444/2232] Bump namespace to 1


---

diff --git a/Cargo.toml b/Cargo.toml
index 1bede61..a9e8644 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "cxx"
 version = "0.5.10" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
-links = "cxxbridge05"
+links = "cxxbridge1"
 license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
diff --git a/build.rs b/build.rs
index ae3ef67..aec0dc9 100644
--- a/build.rs
+++ b/build.rs
@@ -8,7 +8,7 @@ fn main() {
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
-        .compile("cxxbridge05");
+        .compile("cxxbridge1");
 
     println!("cargo:rerun-if-changed=src/cxx.cc");
     println!("cargo:rerun-if-changed=include/cxx.h");
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index d2a0458..b290058 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -357,7 +357,7 @@ fn make_include_dir(prj: &Project) -> Result<PathBuf> {
     let include_dir = prj.out_dir.join("cxxbridge").join("include");
     let cxx_h = include_dir.join("rust").join("cxx.h");
     let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
-    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE05_HEADER") {
+    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE1_HEADER") {
         out::symlink_file(original, cxx_h)?;
         out::symlink_file(original, shared_cxx_h)?;
     } else {
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 41d037a..9c5f4fd 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -92,10 +92,10 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     out.begin_block(Block::Namespace("rust"));
-    out.begin_block(Block::InlineNamespace("cxxbridge05"));
+    out.begin_block(Block::InlineNamespace("cxxbridge1"));
     writeln!(out, "// #include \"rust/cxx.h\"");
 
-    ifndef::write(out, builtin.panic, "CXXBRIDGE05_PANIC");
+    ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
 
     if builtin.rust_string {
         out.next_section();
@@ -109,16 +109,16 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::AnonymousNamespace);
     }
 
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE05_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE05_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE05_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE05_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE05_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE05_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE05_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE05_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE05_RUST_ISIZE");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE05_RELOCATABLE");
+    ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
+    ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
+    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
+    ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
+    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
+    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
+    ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
+    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
     if builtin.manually_drop {
         out.next_section();
@@ -221,7 +221,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     out.end_block(Block::AnonymousNamespace);
-    out.end_block(Block::InlineNamespace("cxxbridge05"));
+    out.end_block(Block::InlineNamespace("cxxbridge1"));
 
     if builtin.trycatch {
         out.begin_block(Block::Namespace("behavior"));
@@ -252,7 +252,7 @@ pub(super) fn write(out: &mut OutFile) {
         out.begin_block(Block::ExternC);
         writeln!(
             out,
-            "const char *cxxbridge05$exception(const char *, size_t);",
+            "const char *cxxbridge1$exception(const char *, size_t);",
         );
         out.end_block(Block::ExternC);
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a014e63..71d6163 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -179,7 +179,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
     out.set_namespace(&strct.name.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", strct.name.to_symbol());
+    let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in strct.doc.to_string().lines() {
@@ -225,7 +225,7 @@ fn write_struct_with_methods<'a>(
     methods: &[&ExternFn],
 ) {
     out.set_namespace(&ety.name.namespace);
-    let guard = format!("CXXBRIDGE05_STRUCT_{}", ety.name.to_symbol());
+    let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in ety.doc.to_string().lines() {
@@ -251,7 +251,7 @@ fn write_struct_with_methods<'a>(
 
 fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     out.set_namespace(&enm.name.namespace);
-    let guard = format!("CXXBRIDGE05_ENUM_{}", enm.name.to_symbol());
+    let guard = format!("CXXBRIDGE1_ENUM_{}", enm.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
     writeln!(out, "#define {}", guard);
     for line in enm.doc.to_string().lines() {
@@ -501,7 +501,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = ::cxxbridge05$exception(catch$, throw$.len);",
+            "        throw$.ptr = ::cxxbridge1$exception(catch$, throw$.len);",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -1012,7 +1012,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.end_block(Block::ExternC);
 
     out.begin_block(Block::Namespace("rust"));
-    out.begin_block(Block::InlineNamespace("cxxbridge05"));
+    out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(inner) = &ty.inner {
@@ -1026,7 +1026,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             }
         }
     }
-    out.end_block(Block::InlineNamespace("cxxbridge05"));
+    out.end_block(Block::InlineNamespace("cxxbridge1"));
     out.end_block(Block::Namespace("rust"));
 }
 
@@ -1034,19 +1034,19 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     let inner = ident.to_fully_qualified();
     let instance = ident.to_symbol();
 
-    writeln!(out, "#ifndef CXXBRIDGE05_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE05_RUST_BOX_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE1_RUST_BOX_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge05$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge1$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge05$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
+        "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE1_RUST_BOX_{}", instance);
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
@@ -1054,44 +1054,44 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
     let inner = to_typename(&element, out.types);
     let instance = to_mangled(&element, out.types);
 
-    writeln!(out, "#ifndef CXXBRIDGE05_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE05_RUST_VEC_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(
         out,
-        "void cxxbridge05$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge1$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge05$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
+        "void cxxbridge1$rust_vec${}$drop(::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge05$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        "size_t cxxbridge1$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "const {} *cxxbridge05$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
+        "const {} *cxxbridge1$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
     writeln!(
         out,
-        "void cxxbridge05$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
+        "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge05$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
+        "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge05$rust_vec${}$stride() noexcept;",
+        "size_t cxxbridge1$rust_vec${}$stride() noexcept;",
         instance,
     );
-    writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
@@ -1100,12 +1100,12 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge05$box${}$uninit(this);", instance);
+    writeln!(out, "  cxxbridge1$box${}$uninit(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
-    writeln!(out, "  cxxbridge05$box${}$drop(this);", instance);
+    writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
     writeln!(out, "}}");
 }
 
@@ -1116,30 +1116,22 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
-    writeln!(out, "  cxxbridge05$rust_vec${}$new(this);", instance);
+    writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge05$rust_vec${}$drop(this);",
-        instance,
-    );
+    writeln!(out, "  return cxxbridge1$rust_vec${}$drop(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
-    writeln!(out, "  return cxxbridge05$rust_vec${}$len(this);", instance);
+    writeln!(out, "  return cxxbridge1$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
-    writeln!(
-        out,
-        "  return cxxbridge05$rust_vec${}$data(this);",
-        instance,
-    );
+    writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
@@ -1150,7 +1142,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     );
     writeln!(
         out,
-        "  return cxxbridge05$rust_vec${}$reserve_total(this, cap);",
+        "  return cxxbridge1$rust_vec${}$reserve_total(this, cap);",
         instance,
     );
     writeln!(out, "}}");
@@ -1159,14 +1151,14 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
     writeln!(
         out,
-        "  return cxxbridge05$rust_vec${}$set_len(this, len);",
+        "  return cxxbridge1$rust_vec${}$set_len(this, len);",
         instance,
     );
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge05$rust_vec${}$stride();", instance);
+    writeln!(out, "  return cxxbridge1$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
 }
 
@@ -1174,12 +1166,12 @@ fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
     let ty = Type::Ident(ident.clone());
     let instance = to_mangled(&ty, out.types);
 
-    writeln!(out, "#ifndef CXXBRIDGE05_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE05_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE1_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 
     write_unique_ptr_common(out, &ty);
 
-    writeln!(out, "#endif // CXXBRIDGE05_UNIQUE_PTR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
@@ -1213,7 +1205,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     );
     writeln!(
         out,
-        "void cxxbridge05$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
@@ -1221,7 +1213,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     if can_construct_from_value {
         writeln!(
             out,
-            "void cxxbridge05$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
+            "void cxxbridge1$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
             instance, inner, inner,
         );
         writeln!(
@@ -1233,28 +1225,28 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     }
     writeln!(
         out,
-        "void cxxbridge05$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
+        "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge05$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
+        "const {} *cxxbridge1$unique_ptr${}$get(const ::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.get();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "{} *cxxbridge05$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
+        "{} *cxxbridge1$unique_ptr${}$release(::std::unique_ptr<{}>& ptr) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return ptr.release();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "void cxxbridge05$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
+        "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  ptr->~unique_ptr();");
@@ -1266,18 +1258,18 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableNam
     let inner = to_typename(&element, out.types);
     let instance = to_mangled(&element, out.types);
 
-    writeln!(out, "#ifndef CXXBRIDGE05_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE05_VECTOR_{}", instance);
+    writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge05$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        "size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge05$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return &s[pos];");
@@ -1285,5 +1277,5 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableNam
 
     write_unique_ptr_common(out, vector_ty);
 
-    writeln!(out, "#endif // CXXBRIDGE05_VECTOR_{}", instance);
+    writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
 }
diff --git a/include/cxx.h b/include/cxx.h
index 3c84330..24a5292 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,7 +15,7 @@
 #endif
 
 namespace rust {
-inline namespace cxxbridge05 {
+inline namespace cxxbridge1 {
 
 struct unsafe_bitcopy_t;
 
@@ -24,8 +24,8 @@ template <typename T>
 class impl;
 }
 
-#ifndef CXXBRIDGE05_RUST_STRING
-#define CXXBRIDGE05_RUST_STRING
+#ifndef CXXBRIDGE1_RUST_STRING
+#define CXXBRIDGE1_RUST_STRING
 class String final {
 public:
   String() noexcept;
@@ -54,9 +54,9 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE05_RUST_STRING
+#endif // CXXBRIDGE1_RUST_STRING
 
-#ifndef CXXBRIDGE05_RUST_STR
+#ifndef CXXBRIDGE1_RUST_STR
 class Str final {
 public:
   Str() noexcept;
@@ -85,9 +85,9 @@ private:
   const char *ptr;
   size_t len;
 };
-#endif // CXXBRIDGE05_RUST_STR
+#endif // CXXBRIDGE1_RUST_STR
 
-#ifndef CXXBRIDGE05_RUST_SLICE
+#ifndef CXXBRIDGE1_RUST_SLICE
 template <typename T>
 class Slice final {
   static_assert(std::is_const<T>::value,
@@ -114,9 +114,9 @@ private:
   T *ptr;
   size_t len;
 };
-#endif // CXXBRIDGE05_RUST_SLICE
+#endif // CXXBRIDGE1_RUST_SLICE
 
-#ifndef CXXBRIDGE05_RUST_BOX
+#ifndef CXXBRIDGE1_RUST_BOX
 template <typename T>
 class Box final {
 public:
@@ -155,9 +155,9 @@ private:
   void drop() noexcept;
   T *ptr;
 };
-#endif // CXXBRIDGE05_RUST_BOX
+#endif // CXXBRIDGE1_RUST_BOX
 
-#ifndef CXXBRIDGE05_RUST_VEC
+#ifndef CXXBRIDGE1_RUST_VEC
 template <typename T>
 class Vec final {
 public:
@@ -224,9 +224,9 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<uintptr_t, 3> repr;
 };
-#endif // CXXBRIDGE05_RUST_VEC
+#endif // CXXBRIDGE1_RUST_VEC
 
-#ifndef CXXBRIDGE05_RUST_FN
+#ifndef CXXBRIDGE1_RUST_FN
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -243,10 +243,10 @@ private:
 
 template <typename Signature>
 using TryFn = Fn<Signature, true>;
-#endif // CXXBRIDGE05_RUST_FN
+#endif // CXXBRIDGE1_RUST_FN
 
-#ifndef CXXBRIDGE05_RUST_ERROR
-#define CXXBRIDGE05_RUST_ERROR
+#ifndef CXXBRIDGE1_RUST_ERROR
+#define CXXBRIDGE1_RUST_ERROR
 class Error final : public std::exception {
 public:
   Error(const Error &);
@@ -264,16 +264,16 @@ private:
   const char *msg;
   size_t len;
 };
-#endif // CXXBRIDGE05_RUST_ERROR
+#endif // CXXBRIDGE1_RUST_ERROR
 
-#ifndef CXXBRIDGE05_RUST_ISIZE
-#define CXXBRIDGE05_RUST_ISIZE
+#ifndef CXXBRIDGE1_RUST_ISIZE
+#define CXXBRIDGE1_RUST_ISIZE
 #if defined(_WIN32)
 using isize = SSIZE_T;
 #else
 using isize = ssize_t;
 #endif
-#endif // CXXBRIDGE05_RUST_ISIZE
+#endif // CXXBRIDGE1_RUST_ISIZE
 
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
@@ -321,14 +321,14 @@ using is_relocatable = IsRelocatable<T>;
 ////////////////////////////////////////////////////////////////////////////////
 /// end public API, begin implementation details
 
-#ifndef CXXBRIDGE05_PANIC
-#define CXXBRIDGE05_PANIC
+#ifndef CXXBRIDGE1_PANIC
+#define CXXBRIDGE1_PANIC
 template <typename Exception>
 void panic [[noreturn]] (const char *msg);
-#endif // CXXBRIDGE05_PANIC
+#endif // CXXBRIDGE1_PANIC
 
-#ifndef CXXBRIDGE05_RUST_FN
-#define CXXBRIDGE05_RUST_FN
+#ifndef CXXBRIDGE1_RUST_FN
+#define CXXBRIDGE1_RUST_FN
 template <typename Ret, typename... Args, bool Throws>
 Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
   return (*this->trampoline)(std::move(args)..., this->fn);
@@ -338,28 +338,28 @@ template <typename Ret, typename... Args, bool Throws>
 Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
   return *this;
 }
-#endif // CXXBRIDGE05_RUST_FN
+#endif // CXXBRIDGE1_RUST_FN
 
-#ifndef CXXBRIDGE05_RUST_BITCOPY
-#define CXXBRIDGE05_RUST_BITCOPY
+#ifndef CXXBRIDGE1_RUST_BITCOPY
+#define CXXBRIDGE1_RUST_BITCOPY
 struct unsafe_bitcopy_t final {
   explicit unsafe_bitcopy_t() = default;
 };
 
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
-#endif // CXXBRIDGE05_RUST_BITCOPY
+#endif // CXXBRIDGE1_RUST_BITCOPY
 
-#ifndef CXXBRIDGE05_RUST_STR
-#define CXXBRIDGE05_RUST_STR
+#ifndef CXXBRIDGE1_RUST_STR
+#define CXXBRIDGE1_RUST_STR
 inline const char *Str::data() const noexcept { return this->ptr; }
 
 inline size_t Str::size() const noexcept { return this->len; }
 
 inline size_t Str::length() const noexcept { return this->len; }
-#endif // CXXBRIDGE05_RUST_STR
+#endif // CXXBRIDGE1_RUST_STR
 
-#ifndef CXXBRIDGE05_RUST_SLICE
-#define CXXBRIDGE05_RUST_SLICE
+#ifndef CXXBRIDGE1_RUST_SLICE
+#define CXXBRIDGE1_RUST_SLICE
 template <typename T>
 Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(this)), len(0) {}
 
@@ -380,10 +380,10 @@ template <typename T>
 size_t Slice<T>::length() const noexcept {
   return this->len;
 }
-#endif // CXXBRIDGE05_RUST_SLICE
+#endif // CXXBRIDGE1_RUST_SLICE
 
-#ifndef CXXBRIDGE05_RUST_BOX
-#define CXXBRIDGE05_RUST_BOX
+#ifndef CXXBRIDGE1_RUST_BOX
+#define CXXBRIDGE1_RUST_BOX
 template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
@@ -479,10 +479,10 @@ T *Box<T>::into_raw() noexcept {
 
 template <typename T>
 Box<T>::Box() noexcept {}
-#endif // CXXBRIDGE05_RUST_BOX
+#endif // CXXBRIDGE1_RUST_BOX
 
-#ifndef CXXBRIDGE05_RUST_VEC
-#define CXXBRIDGE05_RUST_VEC
+#ifndef CXXBRIDGE1_RUST_VEC
+#define CXXBRIDGE1_RUST_VEC
 template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept {
   this->repr = other.repr;
@@ -618,10 +618,10 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 // Internal API only intended for the cxxbridge code generator.
 template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
-#endif // CXXBRIDGE05_RUST_VEC
+#endif // CXXBRIDGE1_RUST_VEC
 
-#ifndef CXXBRIDGE05_RELOCATABLE
-#define CXXBRIDGE05_RELOCATABLE
+#ifndef CXXBRIDGE1_RELOCATABLE
+#define CXXBRIDGE1_RELOCATABLE
 namespace detail {
 template <typename... Ts>
 struct make_void {
@@ -655,7 +655,7 @@ struct IsRelocatable
           std::integral_constant<
               bool, std::is_trivially_move_constructible<T>::value &&
                         std::is_trivially_destructible<T>::value>>::type {};
-#endif // CXXBRIDGE05_RELOCATABLE
+#endif // CXXBRIDGE1_RELOCATABLE
 
-} // namespace cxxbridge05
+} // namespace cxxbridge1
 } // namespace rust
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 36ba6f2..f29c4cc 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -796,7 +796,7 @@ fn type_id(name: &Pair) -> TokenStream {
 }
 
 fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$box${}$", types.resolve(ident).to_symbol());
+    let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
@@ -825,7 +825,7 @@ fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
 }
 
 fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
-    let link_prefix = format!("cxxbridge05$rust_vec${}$", elem.to_symbol(types));
+    let link_prefix = format!("cxxbridge1$rust_vec${}$", elem.to_symbol(types));
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -889,7 +889,7 @@ fn expand_unique_ptr(
     explicit_impl: Option<&Impl>,
 ) -> TokenStream {
     let name = ident.rust.to_string();
-    let prefix = format!("cxxbridge05$unique_ptr${}$", ident.to_symbol(types));
+    let prefix = format!("cxxbridge1$unique_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
     let link_new = format!("{}new", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -973,11 +973,11 @@ fn expand_cxx_vector(
 ) -> TokenStream {
     let _ = explicit_impl;
     let name = elem.rust.to_string();
-    let prefix = format!("cxxbridge05$std$vector${}$", elem.to_symbol(types));
+    let prefix = format!("cxxbridge1$std$vector${}$", elem.to_symbol(types));
     let link_size = format!("{}size", prefix);
     let link_get_unchecked = format!("{}get_unchecked", prefix);
     let unique_ptr_prefix = format!(
-        "cxxbridge05$unique_ptr$std$vector${}$",
+        "cxxbridge1$unique_ptr$std$vector${}$",
         elem.to_symbol(types)
     );
     let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
diff --git a/src/cxx.cc b/src/cxx.cc
index 423f72e..ecc3668 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -9,45 +9,45 @@
 #include <vector>
 
 extern "C" {
-void cxxbridge05$cxx_string$init(std::string *s, const uint8_t *ptr,
-                                 size_t len) noexcept {
+void cxxbridge1$cxx_string$init(std::string *s, const uint8_t *ptr,
+                                size_t len) noexcept {
   new (s) std::string(reinterpret_cast<const char *>(ptr), len);
 }
 
-void cxxbridge05$cxx_string$destroy(std::string *s) noexcept {
+void cxxbridge1$cxx_string$destroy(std::string *s) noexcept {
   using std::string;
   s->~string();
 }
 
-const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
+const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
+size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
-void cxxbridge05$cxx_string$push(std::string &s, const uint8_t *ptr,
-                                 size_t len) noexcept {
+void cxxbridge1$cxx_string$push(std::string &s, const uint8_t *ptr,
+                                size_t len) noexcept {
   s.append(reinterpret_cast<const char *>(ptr), len);
 }
 
 // rust::String
-void cxxbridge05$string$new(rust::String *self) noexcept;
-void cxxbridge05$string$clone(rust::String *self,
-                              const rust::String &other) noexcept;
-bool cxxbridge05$string$from(rust::String *self, const char *ptr,
-                             size_t len) noexcept;
-void cxxbridge05$string$drop(rust::String *self) noexcept;
-const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge05$string$len(const rust::String *self) noexcept;
+void cxxbridge1$string$new(rust::String *self) noexcept;
+void cxxbridge1$string$clone(rust::String *self,
+                             const rust::String &other) noexcept;
+bool cxxbridge1$string$from(rust::String *self, const char *ptr,
+                            size_t len) noexcept;
+void cxxbridge1$string$drop(rust::String *self) noexcept;
+const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
+size_t cxxbridge1$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge1$str$valid(const char *ptr, size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge05 {
+inline namespace cxxbridge1 {
 
 template <typename Exception>
 void panic [[noreturn]] (const char *msg) {
@@ -61,21 +61,21 @@ void panic [[noreturn]] (const char *msg) {
 
 template void panic<std::out_of_range>[[noreturn]] (const char *msg);
 
-String::String() noexcept { cxxbridge05$string$new(this); }
+String::String() noexcept { cxxbridge1$string$new(this); }
 
 String::String(const String &other) noexcept {
-  cxxbridge05$string$clone(this, other);
+  cxxbridge1$string$clone(this, other);
 }
 
 String::String(String &&other) noexcept {
   this->repr = other.repr;
-  cxxbridge05$string$new(&other);
+  cxxbridge1$string$new(&other);
 }
 
-String::~String() noexcept { cxxbridge05$string$drop(this); }
+String::~String() noexcept { cxxbridge1$string$drop(this); }
 
 static void initString(String *self, const char *s, size_t len) {
-  if (!cxxbridge05$string$from(self, s, len)) {
+  if (!cxxbridge1$string$from(self, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
 }
@@ -96,17 +96,17 @@ String::String(const char *s, size_t len) {
 
 String &String::operator=(const String &other) noexcept {
   if (this != &other) {
-    cxxbridge05$string$drop(this);
-    cxxbridge05$string$clone(this, other);
+    cxxbridge1$string$drop(this);
+    cxxbridge1$string$clone(this, other);
   }
   return *this;
 }
 
 String &String::operator=(String &&other) noexcept {
   if (this != &other) {
-    cxxbridge05$string$drop(this);
+    cxxbridge1$string$drop(this);
     this->repr = other.repr;
-    cxxbridge05$string$new(&other);
+    cxxbridge1$string$new(&other);
   }
   return *this;
 }
@@ -116,12 +116,12 @@ String::operator std::string() const {
 }
 
 const char *String::data() const noexcept {
-  return cxxbridge05$string$ptr(this);
+  return cxxbridge1$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge05$string$len(this); }
+size_t String::size() const noexcept { return cxxbridge1$string$len(this); }
 
-size_t String::length() const noexcept { return cxxbridge05$string$len(this); }
+size_t String::length() const noexcept { return cxxbridge1$string$len(this); }
 
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
@@ -134,7 +134,7 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
 static void initStr(const char *ptr, size_t len) {
-  if (!cxxbridge05$str$valid(ptr, len)) {
+  if (!cxxbridge1$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
@@ -171,7 +171,7 @@ static_assert(std::is_trivially_copy_assignable<Str>::value,
 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
 
 extern "C" {
-const char *cxxbridge05$error(const char *ptr, size_t len) {
+const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];
   std::strncpy(copy, ptr, len);
   return copy;
@@ -179,7 +179,7 @@ const char *cxxbridge05$error(const char *ptr, size_t len) {
 } // extern "C"
 
 Error::Error(const Error &other)
-    : std::exception(other), msg(cxxbridge05$error(other.msg, other.len)),
+    : std::exception(other), msg(cxxbridge1$error(other.msg, other.len)),
       len(other.len) {}
 
 Error::Error(Error &&other) noexcept
@@ -195,7 +195,7 @@ Error &Error::operator=(const Error &other) {
     std::exception::operator=(other);
     delete[] this->msg;
     this->msg = nullptr;
-    this->msg = cxxbridge05$error(other.msg, other.len);
+    this->msg = cxxbridge1$error(other.msg, other.len);
     this->len = other.len;
   }
   return *this;
@@ -214,27 +214,27 @@ Error &Error::operator=(Error &&other) noexcept {
 
 const char *Error::what() const noexcept { return this->msg; }
 
-} // namespace cxxbridge05
+} // namespace cxxbridge1
 } // namespace rust
 
 extern "C" {
-void cxxbridge05$unique_ptr$std$string$null(
+void cxxbridge1$unique_ptr$std$string$null(
     std::unique_ptr<std::string> *ptr) noexcept {
   new (ptr) std::unique_ptr<std::string>();
 }
-void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
-                                           std::string *raw) noexcept {
+void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
+                                          std::string *raw) noexcept {
   new (ptr) std::unique_ptr<std::string>(raw);
 }
-const std::string *cxxbridge05$unique_ptr$std$string$get(
+const std::string *cxxbridge1$unique_ptr$std$string$get(
     const std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.get();
 }
-std::string *cxxbridge05$unique_ptr$std$string$release(
+std::string *cxxbridge1$unique_ptr$std$string$release(
     std::unique_ptr<std::string> &ptr) noexcept {
   return ptr.release();
 }
-void cxxbridge05$unique_ptr$std$string$drop(
+void cxxbridge1$unique_ptr$std$string$drop(
     std::unique_ptr<std::string> *ptr) noexcept {
   ptr->~unique_ptr();
 }
@@ -246,81 +246,81 @@ static_assert(sizeof(std::string) <= 8 * sizeof(void *),
               "unexpectedly large std::string size");
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
+  size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                             \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked(          \
+  const CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(           \
       const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
     return &s[pos];                                                            \
   }                                                                            \
-  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
+  void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
   }                                                                            \
-  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
+  void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw(                     \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
       std::vector<CXX_TYPE> *raw) noexcept {                                   \
     new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
   }                                                                            \
   const std::vector<CXX_TYPE>                                                  \
-      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
+      *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get(                     \
           const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
     return ptr.get();                                                          \
   }                                                                            \
   std::vector<CXX_TYPE>                                                        \
-      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release(                \
+      *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release(                 \
           std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
     return ptr.release();                                                      \
   }                                                                            \
-  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
+  void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
     ptr->~unique_ptr();                                                        \
   }
 
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
-  void cxxbridge05$rust_vec$##RUST_TYPE##$new(                                 \
+  void cxxbridge1$rust_vec$##RUST_TYPE##$new(                                  \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  void cxxbridge05$rust_vec$##RUST_TYPE##$drop(                                \
+  void cxxbridge1$rust_vec$##RUST_TYPE##$drop(                                 \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  size_t cxxbridge05$rust_vec$##RUST_TYPE##$len(                               \
+  size_t cxxbridge1$rust_vec$##RUST_TYPE##$len(                                \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
+  const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data(                      \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  void cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(                       \
+  void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
       rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept;                          \
-  void cxxbridge05$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,    \
-                                                  size_t len) noexcept;        \
-  size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;
+  void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,     \
+                                                 size_t len) noexcept;         \
+  size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
   Vec<CXX_TYPE>::Vec() noexcept {                                              \
-    cxxbridge05$rust_vec$##RUST_TYPE##$new(this);                              \
+    cxxbridge1$rust_vec$##RUST_TYPE##$new(this);                               \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::drop() noexcept {                                        \
-    return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this);                      \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this);                       \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::size() const noexcept {                                \
-    return cxxbridge05$rust_vec$##RUST_TYPE##$len(this);                       \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$len(this);                        \
   }                                                                            \
   template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
-    return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$data(this);                       \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept {                     \
-    cxxbridge05$rust_vec$##RUST_TYPE##$reserve_total(this, cap);               \
+    cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, cap);                \
   }                                                                            \
   template <>                                                                  \
   void Vec<CXX_TYPE>::set_len(size_t len) noexcept {                           \
-    cxxbridge05$rust_vec$##RUST_TYPE##$set_len(this, len);                     \
+    cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len);                      \
   }                                                                            \
   template <>                                                                  \
   size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
-    return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
 // Usize and isize are the same type as one of the below.
@@ -353,7 +353,7 @@ FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
-inline namespace cxxbridge05 {
+inline namespace cxxbridge1 {
 FOR_EACH_RUST_VEC(RUST_VEC_OPS)
-} // namespace cxxbridge05
+} // namespace cxxbridge1
 } // namespace rust
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 7a66b47..a2bd72b 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -9,15 +9,15 @@ use core::slice;
 use core::str::{self, Utf8Error};
 
 extern "C" {
-    #[link_name = "cxxbridge05$cxx_string$init"]
+    #[link_name = "cxxbridge1$cxx_string$init"]
     fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize);
-    #[link_name = "cxxbridge05$cxx_string$destroy"]
+    #[link_name = "cxxbridge1$cxx_string$destroy"]
     fn string_destroy(this: &mut MaybeUninit<CxxString>);
-    #[link_name = "cxxbridge05$cxx_string$data"]
+    #[link_name = "cxxbridge1$cxx_string$data"]
     fn string_data(this: &CxxString) -> *const u8;
-    #[link_name = "cxxbridge05$cxx_string$length"]
+    #[link_name = "cxxbridge1$cxx_string$length"]
     fn string_length(this: &CxxString) -> usize;
-    #[link_name = "cxxbridge05$cxx_string$push"]
+    #[link_name = "cxxbridge1$cxx_string$push"]
     fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize);
 }
 
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index e495a97..d1611db 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -163,7 +163,7 @@ macro_rules! impl_vector_element {
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$std$vector$", $segment, "$size")]
+                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -172,7 +172,7 @@ macro_rules! impl_vector_element {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$std$vector$", $segment, "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -181,7 +181,7 @@ macro_rules! impl_vector_element {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$null")]
+                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -192,7 +192,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$raw")]
+                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -203,7 +203,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$get")]
+                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -212,7 +212,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$release")]
+                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -221,7 +221,7 @@ macro_rules! impl_vector_element {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge05$unique_ptr$std$vector$", $segment, "$drop")]
+                        #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
diff --git a/src/result.rs b/src/result.rs
index fcced76..29c5d67 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -34,7 +34,7 @@ unsafe fn to_c_error(msg: String) -> Result {
     let len = msg.len();
 
     extern "C" {
-        #[link_name = "cxxbridge05$error"]
+        #[link_name = "cxxbridge1$error"]
         fn error(ptr: *const u8, len: usize) -> *const u8;
     }
 
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index b408f25..0c1bb87 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -2,7 +2,7 @@ use alloc::boxed::Box;
 use alloc::string::String;
 use core::slice;
 
-#[export_name = "cxxbridge05$exception"]
+#[export_name = "cxxbridge1$exception"]
 unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
     let slice = slice::from_raw_parts(ptr, len);
     let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index b655381..041147d 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,7 +1,7 @@
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge05$str$valid"]
+#[export_name = "cxxbridge1$str$valid"]
 unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
     str::from_utf8(slice).is_ok()
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index e5ab9ea..944aec4 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -5,17 +5,17 @@ use core::ptr;
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge05$string$new"]
+#[export_name = "cxxbridge1$string$new"]
 unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) {
     ptr::write(this.as_mut_ptr(), String::new());
 }
 
-#[export_name = "cxxbridge05$string$clone"]
+#[export_name = "cxxbridge1$string$clone"]
 unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) {
     ptr::write(this.as_mut_ptr(), other.clone());
 }
 
-#[export_name = "cxxbridge05$string$from"]
+#[export_name = "cxxbridge1$string$from"]
 unsafe extern "C" fn string_from(
     this: &mut MaybeUninit<String>,
     ptr: *const u8,
@@ -31,17 +31,17 @@ unsafe extern "C" fn string_from(
     }
 }
 
-#[export_name = "cxxbridge05$string$drop"]
+#[export_name = "cxxbridge1$string$drop"]
 unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
     ManuallyDrop::drop(this);
 }
 
-#[export_name = "cxxbridge05$string$ptr"]
+#[export_name = "cxxbridge1$string$ptr"]
 unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
     this.as_ptr()
 }
 
-#[export_name = "cxxbridge05$string$len"]
+#[export_name = "cxxbridge1$string$len"]
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 90fbc54..df6dec6 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -11,43 +11,43 @@ macro_rules! rust_vec_shims {
 
         const _: () = {
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$new")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$new")]
                 unsafe extern "C" fn __new(this: *mut RustVec<$ty>) {
                     ptr::write(this, RustVec { repr: Vec::new() });
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$drop")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$drop")]
                 unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) {
                     ptr::drop_in_place(this);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$len")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$len")]
                 unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize {
                     (*this).repr.len()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$data")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$reserve_total")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$reserve_total")]
                 unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, cap: usize) {
                     (*this).reserve_total(cap);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$set_len")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$set_len")]
                 unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) {
                     (*this).repr.set_len(len);
                 }
             }
             attr! {
-                #[export_name = concat!("cxxbridge05$rust_vec$", $segment, "$stride")]
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$stride")]
                 unsafe extern "C" fn __stride() -> usize {
                     mem::size_of::<$ty>()
                 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index baba32e..c4d436e 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -171,15 +171,15 @@ pub unsafe trait UniquePtrTarget {
 }
 
 extern "C" {
-    #[link_name = "cxxbridge05$unique_ptr$std$string$null"]
+    #[link_name = "cxxbridge1$unique_ptr$std$string$null"]
     fn unique_ptr_std_string_null(this: *mut *mut c_void);
-    #[link_name = "cxxbridge05$unique_ptr$std$string$raw"]
+    #[link_name = "cxxbridge1$unique_ptr$std$string$raw"]
     fn unique_ptr_std_string_raw(this: *mut *mut c_void, raw: *mut CxxString);
-    #[link_name = "cxxbridge05$unique_ptr$std$string$get"]
+    #[link_name = "cxxbridge1$unique_ptr$std$string$get"]
     fn unique_ptr_std_string_get(this: *const *mut c_void) -> *const CxxString;
-    #[link_name = "cxxbridge05$unique_ptr$std$string$release"]
+    #[link_name = "cxxbridge1$unique_ptr$std$string$release"]
     fn unique_ptr_std_string_release(this: *mut *mut c_void) -> *mut CxxString;
-    #[link_name = "cxxbridge05$unique_ptr$std$string$drop"]
+    #[link_name = "cxxbridge1$unique_ptr$std$string$drop"]
     fn unique_ptr_std_string_drop(this: *mut *mut c_void);
 }
 
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index cc5115a..84e3398 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -2,7 +2,7 @@ use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::{ExternFn, Types};
 use proc_macro2::Ident;
 
-const CXXBRIDGE: &str = "cxxbridge05";
+const CXXBRIDGE: &str = "cxxbridge1";
 
 macro_rules! join {
     ($($segment:expr),*) => {
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 253f57d..9a0a4a1 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -5,7 +5,7 @@ use quote::ToTokens;
 use std::fmt::{self, Display, Write};
 
 // A mangled symbol consisting of segments separated by '$'.
-// For example: cxxbridge05$string$new
+// For example: cxxbridge1$string$new
 pub struct Symbol(String);
 
 impl Display for Symbol {
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index a0c9ff4..d33092c 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -20,7 +20,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge05$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
 }
 
 #[test]
@@ -30,5 +30,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge05$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
 }

From 6a936b31174ce812bddb5f99ce9e63a92545530e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:33:33 +0000
Subject: [PATCH 1445/2232] Add link to website


---

diff --git a/Cargo.toml b/Cargo.toml
index a9e8644..fff332c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
+website = "https://cxx.rs"
 readme = "README.md"
 exclude = ["/demo", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
diff --git a/README.md b/README.md
index 0263f6e..a4f3b9c 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,13 @@ cxx-build = "0.5"
 
 <br>
 
+## Guide
+
+Please see **<https://cxx.rs>** for a tutorial, reference material, and example
+code.
+
+<br>
+
 ## Overview
 
 The idea is that we define the signatures of both sides of our FFI boundary
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 0fc2004..337fafd 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+website = "https://cxx.rs"
 exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 8fbef1e..c3a8927 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
 repository = "https://github.com/dtolnay/cxx"
+website = "https://cxx.rs"
 exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 5ba8478..36e8d9f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
+website = "https://cxx.rs"
 exclude = ["build.rs", "README.md"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
diff --git a/src/lib.rs b/src/lib.rs
index e4431ac..f114ab3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -23,6 +23,13 @@
 //!
 //! <br>
 //!
+//! # Guide
+//!
+//! Please see **<https://cxx.rs>** for a tutorial, reference material, and
+//! example code.
+//!
+//! <br>
+//!
 //! # Overview
 //!
 //! The idea is that we define the signatures of both sides of our FFI boundary

From 1964acdfcda6b537240f41f9d8a50f82d24e4928 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:35:27 +0000
Subject: [PATCH 1446/2232] Fix Cargo.toml manifest homepage metadata


---

diff --git a/Cargo.toml b/Cargo.toml
index fff332c..7e65237 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
 description = "Safe interop between Rust and C++"
 repository = "https://github.com/dtolnay/cxx"
 documentation = "https://docs.rs/cxx"
-website = "https://cxx.rs"
+homepage = "https://cxx.rs"
 readme = "README.md"
 exclude = ["/demo", "/gen", "/syntax", "/third-party"]
 keywords = ["ffi"]
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 337fafd..fa5a1f1 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a Cargo build."
 repository = "https://github.com/dtolnay/cxx"
-website = "https://cxx.rs"
+homepage = "https://cxx.rs"
 exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index c3a8927..c930b7e 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "C++ code generator for integrating `cxx` crate into a non-Cargo build."
 repository = "https://github.com/dtolnay/cxx"
-website = "https://cxx.rs"
+homepage = "https://cxx.rs"
 exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 36e8d9f..21ea513 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2018"
 license = "MIT OR Apache-2.0"
 description = "Implementation detail of the `cxx` crate."
 repository = "https://github.com/dtolnay/cxx"
-website = "https://cxx.rs"
+homepage = "https://cxx.rs"
 exclude = ["build.rs", "README.md"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]

From bf1000f40e3755a2cebfcd59b35f30b591765749 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 17 2020 16:35:42 +0000
Subject: [PATCH 1447/2232] Release 1.0.0


---

diff --git a/Cargo.toml b/Cargo.toml
index 7e65237..4fad728 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "0.5.10" # remember to update html_root_url
+version = "1.0.0" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,16 +21,16 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=0.5.10", path = "macro" }
+cxxbridge-macro = { version = "=1.0.0", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=0.5.10", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.0", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=0.5.10", path = "gen/build" }
-cxx-gen = { version = "0.6", path = "gen/lib" }
+cxx-build = { version = "=1.0.0", path = "gen/build" }
+cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/README.md b/README.md
index a4f3b9c..bc76006 100644
--- a/README.md
+++ b/README.md
@@ -18,10 +18,10 @@ can be 100% safe.
 
 ```toml
 [dependencies]
-cxx = "0.5"
+cxx = "1.0"
 
 [build-dependencies]
-cxx-build = "0.5"
+cxx-build = "1.0"
 ```
 
 *Compiler support: requires rustc 1.48+ and c++11 or newer*<br>
@@ -235,7 +235,7 @@ set up any additional source files and compiler flags as normal.
 # Cargo.toml
 
 [build-dependencies]
-cxx-build = "0.5"
+cxx-build = "1.0"
 ```
 
 ```rust
@@ -323,11 +323,11 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
-<tr><td><a href="https://docs.rs/cxx/0.5/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index cd9072e..2d21aa1 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "0.5.10"
+version = "1.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index fa5a1f1..b232919 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "0.5.10"
+version = "1.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -21,7 +21,7 @@ scratch = "1.0"
 syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
-cxx-gen = { version = "0.6", path = "../lib" }
+cxx-gen = { version = "0.7", path = "../lib" }
 pkg-config = "0.3"
 
 [package.metadata.docs.rs]
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index c930b7e..b38aa68 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "0.5.10"
+version = "1.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index c1af1c2..250fa3f 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.6.7"
+version = "0.7.0"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 21ea513..61c8b14 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "0.5.10"
+version = "1.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -20,7 +20,7 @@ quote = "1.0.4"
 syn = { version = "1.0.20", features = ["full"] }
 
 [dev-dependencies]
-cxx = { version = "0.5", path = ".." }
+cxx = { version = "1.0", path = ".." }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/src/lib.rs b/src/lib.rs
index f114ab3..cf9212c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -242,7 +242,7 @@
 //! # Cargo.toml
 //!
 //! [build-dependencies]
-//! cxx-build = "0.5"
+//! cxx-build = "1.0"
 //! ```
 //!
 //! ```no_run
@@ -361,7 +361,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/0.5.10")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.0")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b074415..5f35669 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "0.5.10"
+version = "1.0.0"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "0.5.10"
+version = "1.0.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.6.7"
+version = "0.7.0"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "0.5.10"
+version = "1.0.0"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "0.5.10"
+version = "1.0.0"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "0.5.10"
+version = "1.0.0"
 dependencies = [
  "cxx",
  "proc-macro2",

From 841c75176491abc38340791d979a3b1ae89b18ab Mon Sep 17 00:00:00 2001
From: Iulian Radu <iulian.radu67@gmail.com>
Date: Nov 18 2020 21:28:02 +0000
Subject: [PATCH 1448/2232] Add clang-tidy CI check


---

diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..597fa6c
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,2 @@
+Checks: clang-diagnostic-*,clang-analyzer-*,modernize-*,cppcoreguidelines-*,
+    -modernize-use-trailing-return-type,-cppcoreguidelines-pro-type-reinterpret-cast
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a633fd8..209ced5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,3 +94,13 @@ jobs:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
       - run: cargo clippy --workspace --tests -- -Dclippy::all
+
+    clang-tidy:
+      name: Clang Tidy
+      runs-on: ubuntu-latest
+      steps:
+        - uses: actions/checkout@v2
+        - name: Install clang-tidy
+          run: sudo apt install clang-tidy-10
+        - name: Run clang-tidy
+          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h' -- -Iinclude -xc++ -std=c++11

From 7c5c7bef34a9d09b0637b2e22015f7f8b79538e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 21:41:01 +0000
Subject: [PATCH 1449/2232] Add ui test of async extern fn


---

diff --git a/tests/ui/async_fn.rs b/tests/ui/async_fn.rs
new file mode 100644
index 0000000..69f2642
--- /dev/null
+++ b/tests/ui/async_fn.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        async fn f();
+    }
+}
+
+async fn f() {}
+
+fn main() {}
diff --git a/tests/ui/async_fn.stderr b/tests/ui/async_fn.stderr
new file mode 100644
index 0000000..63e3666
--- /dev/null
+++ b/tests/ui/async_fn.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+ --> $DIR/async_fn.rs:4:18
+  |
+4 |         async fn f();
+  |                  ^
+  |                  |
+  |                  expected `()`, found opaque type
+  |                  possibly return type missing here?
+...
+8 | async fn f() {}
+  |              - the `Output` of this `async fn`'s found opaque type
+  |
+  = note: expected unit type `()`
+           found opaque type `impl Future`
+help: consider `await`ing on the `Future`
+  |
+4 |         async fn f.await();
+  |                   ^^^^^^
+help: try adding a semicolon
+  |
+4 |         async fn f;();
+  |                   ^

From 8de461f44aed5df8a5ff04d446a135ad38c29bda Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 21:46:14 +0000
Subject: [PATCH 1450/2232] Improve async fn error message with link to workaround


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index ec89cbb..78e6a3f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -373,6 +373,12 @@ fn parse_extern_fn(
             "variadic function is not supported yet",
         ));
     }
+    if foreign_fn.sig.asyncness.is_some() {
+        return Err(Error::new_spanned(
+            foreign_fn,
+            "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
+        ));
+    }
 
     let mut doc = Doc::new();
     let mut cxx_name = None;
diff --git a/tests/ui/async_fn.stderr b/tests/ui/async_fn.stderr
index 63e3666..dedec7b 100644
--- a/tests/ui/async_fn.stderr
+++ b/tests/ui/async_fn.stderr
@@ -1,22 +1,5 @@
-error[E0308]: mismatched types
- --> $DIR/async_fn.rs:4:18
+error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach
+ --> $DIR/async_fn.rs:4:9
   |
 4 |         async fn f();
-  |                  ^
-  |                  |
-  |                  expected `()`, found opaque type
-  |                  possibly return type missing here?
-...
-8 | async fn f() {}
-  |              - the `Output` of this `async fn`'s found opaque type
-  |
-  = note: expected unit type `()`
-           found opaque type `impl Future`
-help: consider `await`ing on the `Future`
-  |
-4 |         async fn f.await();
-  |                   ^^^^^^
-help: try adding a semicolon
-  |
-4 |         async fn f;();
-  |                   ^
+  |         ^^^^^^^^^^^^^

From c39925db538f29ea66fe1bfdae043c15aa5b1cff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 21:54:44 +0000
Subject: [PATCH 1451/2232] Merge pull request #488 from dtolnay/async


Improve async fn error message with link to workaround
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index ec89cbb..78e6a3f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -373,6 +373,12 @@ fn parse_extern_fn(
             "variadic function is not supported yet",
         ));
     }
+    if foreign_fn.sig.asyncness.is_some() {
+        return Err(Error::new_spanned(
+            foreign_fn,
+            "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
+        ));
+    }
 
     let mut doc = Doc::new();
     let mut cxx_name = None;
diff --git a/tests/ui/async_fn.rs b/tests/ui/async_fn.rs
new file mode 100644
index 0000000..69f2642
--- /dev/null
+++ b/tests/ui/async_fn.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        async fn f();
+    }
+}
+
+async fn f() {}
+
+fn main() {}
diff --git a/tests/ui/async_fn.stderr b/tests/ui/async_fn.stderr
new file mode 100644
index 0000000..dedec7b
--- /dev/null
+++ b/tests/ui/async_fn.stderr
@@ -0,0 +1,5 @@
+error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach
+ --> $DIR/async_fn.rs:4:9
+  |
+4 |         async fn f();
+  |         ^^^^^^^^^^^^^

From 80ef068ea0e6576af9b17094bd343ae85b41dba2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 21:57:42 +0000
Subject: [PATCH 1452/2232] Produce error message for a few more unsupported signatures


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 78e6a3f..25d95e6 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -379,6 +379,18 @@ fn parse_extern_fn(
             "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
         ));
     }
+    if foreign_fn.sig.constness.is_some() {
+        return Err(Error::new_spanned(
+            foreign_fn,
+            "const extern function is not supported",
+        ));
+    }
+    if let Some(abi) = &foreign_fn.sig.abi {
+        return Err(Error::new_spanned(
+            abi,
+            "explicit ABI on extern function is not supported",
+        ));
+    }
 
     let mut doc = Doc::new();
     let mut cxx_name = None;
diff --git a/tests/ui/const_fn.rs b/tests/ui/const_fn.rs
new file mode 100644
index 0000000..1ad4894
--- /dev/null
+++ b/tests/ui/const_fn.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        const fn f();
+    }
+}
+
+const fn f() {}
+
+fn main() {}
diff --git a/tests/ui/const_fn.stderr b/tests/ui/const_fn.stderr
new file mode 100644
index 0000000..a62ca83
--- /dev/null
+++ b/tests/ui/const_fn.stderr
@@ -0,0 +1,5 @@
+error: const extern function is not supported
+ --> $DIR/const_fn.rs:4:9
+  |
+4 |         const fn f();
+  |         ^^^^^^^^^^^^^
diff --git a/tests/ui/extern_fn_abi.rs b/tests/ui/extern_fn_abi.rs
new file mode 100644
index 0000000..1f93338
--- /dev/null
+++ b/tests/ui/extern_fn_abi.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        extern "Java" fn f();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_fn_abi.stderr b/tests/ui/extern_fn_abi.stderr
new file mode 100644
index 0000000..3abf47a
--- /dev/null
+++ b/tests/ui/extern_fn_abi.stderr
@@ -0,0 +1,5 @@
+error: explicit ABI on extern function is not supported
+ --> $DIR/extern_fn_abi.rs:4:9
+  |
+4 |         extern "Java" fn f();
+  |         ^^^^^^^^^^^^^

From b2bf244a90feeccc764335c568577ff239fa7ff5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:00:38 +0000
Subject: [PATCH 1453/2232] No longer need rustfmt::skip when using extern type alias


---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 8ca5e57..51d21cc 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -5,9 +5,6 @@
 // for testing aliasing between cxx::bridge mods, so we'll keep it that way and
 // start a new mod here.
 
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi2 {
     impl UniquePtr<D> {}
@@ -43,7 +40,7 @@ pub mod ffi2 {
         fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
         fn c_return_trivial_ns() -> G;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
-        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
         fn c_return_ns_unique_ptr() -> UniquePtr<H>;
         fn c_take_ref_ns_c(h: &H);
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index aff1b1c..1952885 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,6 +1,3 @@
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     unsafe extern "C++" {

From e7d30cb4a1bdcefa86c2c6dfbc5ca4cb97cdd127 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:22:17 +0000
Subject: [PATCH 1454/2232] Merge pull request #489 from dtolnay/rustfmt


No longer need rustfmt::skip when using extern type alias
---

diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
index 8ca5e57..51d21cc 100644
--- a/tests/ffi/extra.rs
+++ b/tests/ffi/extra.rs
@@ -5,9 +5,6 @@
 // for testing aliasing between cxx::bridge mods, so we'll keep it that way and
 // start a new mod here.
 
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi2 {
     impl UniquePtr<D> {}
@@ -43,7 +40,7 @@ pub mod ffi2 {
         fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
         fn c_return_trivial_ns() -> G;
         fn c_return_opaque_ptr() -> UniquePtr<E>;
-        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
         fn c_return_ns_unique_ptr() -> UniquePtr<H>;
         fn c_take_ref_ns_c(h: &H);
 
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index aff1b1c..1952885 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,6 +1,3 @@
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     unsafe extern "C++" {

From fbd0a8de264529fa562981b14e1e388750bf6eda Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:22:59 +0000
Subject: [PATCH 1455/2232] Combine 'extra' and 'module' modules in test suite


---

diff --git a/tests/BUCK b/tests/BUCK
index 5bbe500..4bdcc46 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -12,7 +12,6 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
-        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -28,7 +27,6 @@ cxx_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":extra/source",
         ":module/source",
     ],
     headers = {
@@ -44,11 +42,6 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
-)
-
-rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 57ffab9..b255a3c 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -15,7 +15,6 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
-        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -30,7 +29,6 @@ cc_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":extra/source",
         ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
@@ -47,12 +45,6 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
-    deps = [":impl"],
-)
-
-rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
     deps = [":impl"],
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 4b2cbdf..e583944 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
+    let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
deleted file mode 100644
index 51d21cc..0000000
--- a/tests/ffi/extra.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Separate mod so that &self in the lib.rs mod has an unambiguous receiver. At
-// the moment, the cxx C++ codegen can't convert more than one cxx::bridge mod
-// per file, so that's why we need to put this outside of lib.rs. All of this
-// could go into module.rs instead, but for now its purpose is narrowly scoped
-// for testing aliasing between cxx::bridge mods, so we'll keep it that way and
-// start a new mod here.
-
-#[cxx::bridge(namespace = "tests")]
-pub mod ffi2 {
-    impl UniquePtr<D> {}
-    impl UniquePtr<E> {}
-    impl UniquePtr<F> {}
-    impl UniquePtr<G> {}
-
-    unsafe extern "C++" {
-        include!("tests/ffi/tests.h");
-
-        type D = crate::other::D;
-        type E = crate::other::E;
-        #[namespace = "F"]
-        type F = crate::other::f::F;
-        #[namespace = "G"]
-        type G = crate::other::G;
-
-        #[namespace = "H"]
-        type H;
-
-        fn c_take_trivial_ptr(d: UniquePtr<D>);
-        fn c_take_trivial_ref(d: &D);
-        fn c_take_trivial(d: D);
-        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
-        fn c_take_trivial_ns_ref(g: &G);
-        fn c_take_trivial_ns(g: G);
-        fn c_take_opaque_ptr(e: UniquePtr<E>);
-        fn c_take_opaque_ref(e: &E);
-        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
-        fn c_take_opaque_ns_ref(e: &F);
-        fn c_return_trivial_ptr() -> UniquePtr<D>;
-        fn c_return_trivial() -> D;
-        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
-        fn c_return_trivial_ns() -> G;
-        fn c_return_opaque_ptr() -> UniquePtr<E>;
-        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
-        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
-        fn c_take_ref_ns_c(h: &H);
-
-        #[namespace = "other"]
-        fn ns_c_take_trivial(d: D);
-        #[namespace = "other"]
-        fn ns_c_return_trivial() -> D;
-
-        #[namespace = "I"]
-        type I;
-
-        fn get(self: &I) -> u32;
-
-        #[namespace = "I"]
-        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
-    }
-}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5844bd1..c408fb0 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -5,7 +5,6 @@
     clippy::trivially_copy_pass_by_ref
 )]
 
-pub mod extra;
 pub mod module;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 1952885..5846e11 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -8,3 +8,57 @@ pub mod ffi {
         fn c_take_unique_ptr(c: UniquePtr<C>);
     }
 }
+
+#[cxx::bridge(namespace = "tests")]
+pub mod ffi2 {
+    unsafe extern "C++" {
+        include!("tests/ffi/tests.h");
+
+        type D = crate::other::D;
+        type E = crate::other::E;
+        #[namespace = "F"]
+        type F = crate::other::f::F;
+        #[namespace = "G"]
+        type G = crate::other::G;
+
+        #[namespace = "H"]
+        type H;
+
+        fn c_take_trivial_ptr(d: UniquePtr<D>);
+        fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial(d: D);
+        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
+        fn c_take_trivial_ns_ref(g: &G);
+        fn c_take_trivial_ns(g: G);
+        fn c_take_opaque_ptr(e: UniquePtr<E>);
+        fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
+        fn c_take_opaque_ns_ref(e: &F);
+        fn c_return_trivial_ptr() -> UniquePtr<D>;
+        fn c_return_trivial() -> D;
+        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
+        fn c_return_trivial_ns() -> G;
+        fn c_return_opaque_ptr() -> UniquePtr<E>;
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
+        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
+        fn c_take_ref_ns_c(h: &H);
+
+        #[namespace = "other"]
+        fn ns_c_take_trivial(d: D);
+        #[namespace = "other"]
+        fn ns_c_return_trivial() -> D;
+
+        #[namespace = "I"]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace = "I"]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
+    }
+
+    impl UniquePtr<D> {}
+    impl UniquePtr<E> {}
+    impl UniquePtr<F> {}
+    impl UniquePtr<G> {}
+}
diff --git a/tests/test.rs b/tests/test.rs
index e5e1373..bf69379 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
-use cxx_test_suite::extra::ffi2;
+use cxx_test_suite::module::ffi2;
 use cxx_test_suite::{ffi, R};
 use std::cell::Cell;
 use std::ffi::CStr;

From 70e5bfb03548c513ef0ba39bd4f6644d6d184ee0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:45:36 +0000
Subject: [PATCH 1456/2232] Perform exhaustive type matching for is_unsized check


This way we won't forget to touch this code when introducing some new
binding.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 53dd843..b0ac66e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -402,12 +402,20 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 }
 
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
-    let ident = match ty {
-        Type::Ident(ident) => &ident.rust,
+    match ty {
+        Type::Ident(ident) => {
+            let ident = &ident.rust;
+            ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+        }
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
-        _ => return false,
-    };
-    ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+        Type::RustBox(_)
+        | Type::RustVec(_)
+        | Type::UniquePtr(_)
+        | Type::Ref(_)
+        | Type::Str(_)
+        | Type::Fn(_)
+        | Type::SliceRefU8(_) => return false,
+    }
 }
 
 fn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool {

From 4de3481d47b048c5704126a8b84734cd01eeb98b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:48:55 +0000
Subject: [PATCH 1457/2232] Catch str as a reserved type name


---

diff --git a/syntax/check.rs b/syntax/check.rs
index b0ac66e..f029e0a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -395,6 +395,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
         || ident == "UniquePtr"
         || ident == "Vec"
         || ident == "CxxVector"
+        || ident == "str"
         || Atom::from(ident).is_some()
     {
         cx.error(ident, "reserved name");

From f35a22d1199a2485cfd8b712545fa5a7b639e862 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:56:50 +0000
Subject: [PATCH 1458/2232] Resolve clippy needless_return lint


---

diff --git a/syntax/check.rs b/syntax/check.rs
index f029e0a..0e603a6 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -408,14 +408,14 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
             let ident = &ident.rust;
             ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
         }
-        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
+        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => true,
         Type::RustBox(_)
         | Type::RustVec(_)
         | Type::UniquePtr(_)
         | Type::Ref(_)
         | Type::Str(_)
         | Type::Fn(_)
-        | Type::SliceRefU8(_) => return false,
+        | Type::SliceRefU8(_) => false,
     }
 }
 

From 468063fb6998d66b98095fd1c113929c7b2e4b7d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:56:58 +0000
Subject: [PATCH 1459/2232] Add failing test of extern enum used as struct field


Currently fails with:

    error[cxxbridge]: needs a cxx::ExternType impl in order to be used as a field of `Second`
        ┌─ lib.rs:222:9
        │
    222 │         type COwnedEnum;
        │         ^^^^^^^^^^^^^^^ needs a cxx::ExternType impl in order to be used as a field of `Second`

which is wrong because the bridge should know it's producing a
compatible ExternType impl for this type.

---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c408fb0..032adc4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -113,6 +113,7 @@ pub mod ffi {
     #[namespace = "second"]
     struct Second {
         i: i32,
+        e: COwnedEnum,
     }
 
     unsafe extern "C++" {

From 295b106b74a4df7480d6bfd3ea669d577d650403 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 19 2020 22:57:04 +0000
Subject: [PATCH 1460/2232] Skip ExternType::Kind check if type is known trivial


---

diff --git a/syntax/types.rs b/syntax/types.rs
index 92c9a75..f57b61b 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -170,7 +170,10 @@ impl<'a> Types<'a> {
         let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust) {
+                if cxx.contains(&ident.rust)
+                    && !structs.contains_key(&ident.rust)
+                    && !enums.contains_key(&ident.rust)
+                {
                     required_trivial.entry(&ident.rust).or_insert(reason);
                 }
             }

From 51e81b20834d645ba7233b6813fa81c9558f686c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 03:22:53 +0000
Subject: [PATCH 1461/2232] Merge pull request #490 from dtolnay/externstruct


Skip ExternType::Kind check if type is known trivial
---

diff --git a/syntax/types.rs b/syntax/types.rs
index 92c9a75..f57b61b 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -170,7 +170,10 @@ impl<'a> Types<'a> {
         let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust) {
+                if cxx.contains(&ident.rust)
+                    && !structs.contains_key(&ident.rust)
+                    && !enums.contains_key(&ident.rust)
+                {
                     required_trivial.entry(&ident.rust).or_insert(reason);
                 }
             }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c408fb0..032adc4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -113,6 +113,7 @@ pub mod ffi {
     #[namespace = "second"]
     struct Second {
         i: i32,
+        e: COwnedEnum,
     }
 
     unsafe extern "C++" {

From 06711bc251b4b2e5895fe5a4647cf1f782dcfc9d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 03:29:58 +0000
Subject: [PATCH 1462/2232] Check std::is_enum on extern enum


Without this, something that is not an enum could have been able to pass
our assertions, resulting in unpredictable behavior.

    // rust
    enum FakeEnum { K = 1usize }
    extern "C++" { type FakeEnum; }

    // c++
    struct FakeEnum {
      static const int K = 1;
      const char *x;
    };

There may be valid reasons to want something of this sort to work, but
forbid for now and someone will need to bring forward a concrete use
case for consideration.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 71d6163..d997786 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -269,6 +269,12 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     out.set_namespace(&enm.name.namespace);
+    out.include.type_traits = true;
+    writeln!(
+        out,
+        "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
+        enm.name.cxx,
+    );
     write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");

From 2a686910ec0ac4c8173b9b1bb9de0bcc0c59edfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 03:39:49 +0000
Subject: [PATCH 1463/2232] Merge pull request #491 from dtolnay/externenum


Check std::is_enum on extern enum
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 71d6163..d997786 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -269,6 +269,12 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     out.set_namespace(&enm.name.namespace);
+    out.include.type_traits = true;
+    writeln!(
+        out,
+        "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
+        enm.name.cxx,
+    );
     write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");

From ced2adc9c79cea1c930201abd56b2186cd6a7b2a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 03:57:58 +0000
Subject: [PATCH 1464/2232] Remove check for duplicated discriminants


C++ enum and enum class are allowed to contain multiple enumerator
definitions with the same value. Our enum representation in Rust is
compatible with this too, so there is no need to error on such enums.

    enum class Enum {
      A = 5,
      B = 4,
      C = 4, // dup
      D, // = 5 dup
    };

---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 6a04d88..5e39f63 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -133,13 +133,9 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
             }
         }
     }
-    if set.values.insert(discriminant) {
-        set.previous = Some(discriminant);
-        Ok(discriminant)
-    } else {
-        let msg = format!("discriminant value `{}` already exists", discriminant);
-        Err(Error::new(Span::call_site(), msg))
-    }
+    set.values.insert(discriminant);
+    set.previous = Some(discriminant);
+    Ok(discriminant)
 }
 
 impl Discriminant {
diff --git a/tests/ui/duplicate_enum_discriminants.rs b/tests/ui/duplicate_enum_discriminants.rs
deleted file mode 100644
index ec3d61a..0000000
--- a/tests/ui/duplicate_enum_discriminants.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    enum A {
-        V1 = 10,
-        V2 = 10,
-    }
-
-    enum B {
-        V1 = 10,
-        V2,
-        V3 = 11,
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
deleted file mode 100644
index 14505e3..0000000
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:5:9
-  |
-5 |         V2 = 10,
-  |         ^^^^^^^
-
-error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:11:9
-   |
-11 |         V3 = 11,
-   |         ^^^^^^^

From 25ddb143ac5f372d087fc0947330d19797ebd7b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:09:57 +0000
Subject: [PATCH 1465/2232] Merge pull request #492 from dtolnay/enumdup


Remove check for duplicated discriminants
---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 6a04d88..5e39f63 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -133,13 +133,9 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
             }
         }
     }
-    if set.values.insert(discriminant) {
-        set.previous = Some(discriminant);
-        Ok(discriminant)
-    } else {
-        let msg = format!("discriminant value `{}` already exists", discriminant);
-        Err(Error::new(Span::call_site(), msg))
-    }
+    set.values.insert(discriminant);
+    set.previous = Some(discriminant);
+    Ok(discriminant)
 }
 
 impl Discriminant {
diff --git a/tests/ui/duplicate_enum_discriminants.rs b/tests/ui/duplicate_enum_discriminants.rs
deleted file mode 100644
index ec3d61a..0000000
--- a/tests/ui/duplicate_enum_discriminants.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    enum A {
-        V1 = 10,
-        V2 = 10,
-    }
-
-    enum B {
-        V1 = 10,
-        V2,
-        V3 = 11,
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
deleted file mode 100644
index 14505e3..0000000
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:5:9
-  |
-5 |         V2 = 10,
-  |         ^^^^^^^
-
-error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:11:9
-   |
-11 |         V3 = 11,
-   |         ^^^^^^^

From da5576343445e47d1db53b702722a9f7a3fd9c52 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:21:32 +0000
Subject: [PATCH 1466/2232] Add UniquePtr deref mut ui test


---

diff --git a/tests/ui/unique_ptr_as_mut.rs b/tests/ui/unique_ptr_as_mut.rs
new file mode 100644
index 0000000..d2c758a
--- /dev/null
+++ b/tests/ui/unique_ptr_as_mut.rs
@@ -0,0 +1,23 @@
+use cxx::UniquePtr;
+
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        x: i32,
+    }
+
+    extern "C++" {
+        type Opaque;
+    }
+
+    impl UniquePtr<Shared> {}
+    impl UniquePtr<Opaque> {}
+}
+
+fn main() {
+    let mut shared = UniquePtr::<ffi::Shared>::null();
+    let _: &mut ffi::Shared = &mut shared;
+
+    let mut opaque = UniquePtr::<ffi::Opaque>::null();
+    let _: &mut ffi::Opaque = &mut opaque;
+}
diff --git a/tests/ui/unique_ptr_as_mut.stderr b/tests/ui/unique_ptr_as_mut.stderr
new file mode 100644
index 0000000..6b43299
--- /dev/null
+++ b/tests/ui/unique_ptr_as_mut.stderr
@@ -0,0 +1,15 @@
+error[E0596]: cannot borrow data in a dereference of `UniquePtr<Shared>` as mutable
+  --> $DIR/unique_ptr_as_mut.rs:19:31
+   |
+19 |     let _: &mut ffi::Shared = &mut shared;
+   |                               ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<Shared>`
+
+error[E0596]: cannot borrow data in a dereference of `UniquePtr<ffi::Opaque>` as mutable
+  --> $DIR/unique_ptr_as_mut.rs:22:31
+   |
+22 |     let _: &mut ffi::Opaque = &mut opaque;
+   |                               ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<ffi::Opaque>`

From 300ef4a0f46164a5054a65ec09ceaa564de9be22 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:28:29 +0000
Subject: [PATCH 1467/2232] Add conditional DerefMut for UniquePtr


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index c4d436e..5a095ff 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -6,7 +6,7 @@ use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
 use core::pin::Pin;
 use core::ptr;
 
@@ -119,6 +119,18 @@ where
     }
 }
 
+impl<T> DerefMut for UniquePtr<T>
+where
+    T: UniquePtrTarget + Unpin,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => Pin::into_inner(target),
+            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+}
+
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,
diff --git a/tests/ui/unique_ptr_as_mut.stderr b/tests/ui/unique_ptr_as_mut.stderr
index 6b43299..a41f716 100644
--- a/tests/ui/unique_ptr_as_mut.stderr
+++ b/tests/ui/unique_ptr_as_mut.stderr
@@ -1,11 +1,3 @@
-error[E0596]: cannot borrow data in a dereference of `UniquePtr<Shared>` as mutable
-  --> $DIR/unique_ptr_as_mut.rs:19:31
-   |
-19 |     let _: &mut ffi::Shared = &mut shared;
-   |                               ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<Shared>`
-
 error[E0596]: cannot borrow data in a dereference of `UniquePtr<ffi::Opaque>` as mutable
   --> $DIR/unique_ptr_as_mut.rs:22:31
    |

From 2af198a41faa7bb0df312bfc1d3e21791ac9f471 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:35:42 +0000
Subject: [PATCH 1468/2232] Merge pull request #493 from dtolnay/derefunique


Add conditional DerefMut for UniquePtr
---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index c4d436e..5a095ff 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -6,7 +6,7 @@ use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
 use core::pin::Pin;
 use core::ptr;
 
@@ -119,6 +119,18 @@ where
     }
 }
 
+impl<T> DerefMut for UniquePtr<T>
+where
+    T: UniquePtrTarget + Unpin,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => Pin::into_inner(target),
+            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+}
+
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,
diff --git a/tests/ui/unique_ptr_as_mut.stderr b/tests/ui/unique_ptr_as_mut.stderr
index 6b43299..a41f716 100644
--- a/tests/ui/unique_ptr_as_mut.stderr
+++ b/tests/ui/unique_ptr_as_mut.stderr
@@ -1,11 +1,3 @@
-error[E0596]: cannot borrow data in a dereference of `UniquePtr<Shared>` as mutable
-  --> $DIR/unique_ptr_as_mut.rs:19:31
-   |
-19 |     let _: &mut ffi::Shared = &mut shared;
-   |                               ^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<Shared>`
-
 error[E0596]: cannot borrow data in a dereference of `UniquePtr<ffi::Opaque>` as mutable
   --> $DIR/unique_ptr_as_mut.rs:22:31
    |

From 345a68f243eb0ab0af2224021c2140d94a66d1e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:39:54 +0000
Subject: [PATCH 1469/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5f35669..87c40d3 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.62"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
+checksum = "ad9c6140b5a2c7db40ea56eb1821245e5362b44385c05b76288b1a599934ac87"
 
 [[package]]
 name = "clap"
@@ -280,9 +280,9 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.1.0"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
 dependencies = [
  "winapi-util",
 ]

From ecd81934640d45835eb91d32ad071bf8a3619b37 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:40:07 +0000
Subject: [PATCH 1470/2232] Release 1.0.1


---

diff --git a/Cargo.toml b/Cargo.toml
index 4fad728..f5e8ac5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.0" # remember to update html_root_url
+version = "1.0.1" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.0", path = "macro" }
+cxxbridge-macro = { version = "=1.0.1", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.0", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.1", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.0", path = "gen/build" }
+cxx-build = { version = "=1.0.1", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 2d21aa1..601fff7 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.0"
+version = "1.0.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b232919..25ebabd 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.0"
+version = "1.0.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b38aa68..9d819d2 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.0"
+version = "1.0.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 250fa3f..3708bf3 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.0"
+version = "0.7.1"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 61c8b14..e8ce47d 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.0"
+version = "1.0.1"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index cf9212c..d921a54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -361,7 +361,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.0")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.1")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 87c40d3..97d6a1d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.0"
+version = "1.0.1"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.0"
+version = "1.0.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.0"
+version = "0.7.1"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.0"
+version = "1.0.1"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.0"
+version = "1.0.1"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.0"
+version = "1.0.1"
 dependencies = [
  "cxx",
  "proc-macro2",

From 9904d5c88edb898ed7cfbf1218c05acd84ecf347 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 20 2020 04:46:32 +0000
Subject: [PATCH 1471/2232] Fix buck/bazel third party deps


---

diff --git a/third-party/BUCK b/third-party/BUCK
index a9a3913..06227df 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.62/src/**"]),
+    srcs = glob(["vendor/cc-1.0.63/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -91,7 +91,7 @@ rust_library(
 
 rust_library(
     name = "termcolor",
-    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+    srcs = glob(["vendor/termcolor-1.1.2/src/**"]),
 )
 
 rust_library(
diff --git a/third-party/BUILD b/third-party/BUILD
index d72b083..521d7ad 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -13,7 +13,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.62/src/**"]),
+    srcs = glob(["vendor/cc-1.0.63/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -97,7 +97,7 @@ rust_library(
 
 rust_library(
     name = "termcolor",
-    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+    srcs = glob(["vendor/termcolor-1.1.2/src/**"]),
 )
 
 rust_library(

From a8abe460dc6c13b7cfc8d0dafedaee57af43d19c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 21 2020 04:33:08 +0000
Subject: [PATCH 1472/2232] Neg/Pos enum for discriminant sign


---

diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 5e39f63..80f7c0b 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -16,10 +16,16 @@ pub struct DiscriminantSet {
 
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Discriminant {
-    negative: bool,
+    sign: Sign,
     magnitude: u64,
 }
 
+#[derive(Copy, Clone, Eq, PartialEq)]
+enum Sign {
+    Negative,
+    Positive,
+}
+
 impl DiscriminantSet {
     pub fn new(repr: Option<Atom>) -> Self {
         DiscriminantSet {
@@ -59,21 +65,23 @@ impl DiscriminantSet {
     pub fn insert_next(&mut self) -> Result<Discriminant> {
         let discriminant = match self.previous {
             None => Discriminant::zero(),
-            Some(mut discriminant) if discriminant.negative => {
-                discriminant.magnitude -= 1;
-                if discriminant.magnitude == 0 {
-                    discriminant.negative = false;
+            Some(mut discriminant) => match discriminant.sign {
+                Sign::Negative => {
+                    discriminant.magnitude -= 1;
+                    if discriminant.magnitude == 0 {
+                        discriminant.sign = Sign::Positive;
+                    }
+                    discriminant
                 }
-                discriminant
-            }
-            Some(mut discriminant) => {
-                if discriminant.magnitude == u64::MAX {
-                    let msg = format!("discriminant overflow on value after {}", u64::MAX);
-                    return Err(Error::new(Span::call_site(), msg));
+                Sign::Positive => {
+                    if discriminant.magnitude == u64::MAX {
+                        let msg = format!("discriminant overflow on value after {}", u64::MAX);
+                        return Err(Error::new(Span::call_site(), msg));
+                    }
+                    discriminant.magnitude += 1;
+                    discriminant
                 }
-                discriminant.magnitude += 1;
-                discriminant
-            }
+            },
         };
         insert(self, discriminant)
     }
@@ -109,7 +117,10 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
         Expr::Unary(unary) => {
             if let UnOp::Neg(_) = unary.op {
                 let (mut discriminant, repr) = expr_to_discriminant(&unary.expr)?;
-                discriminant.negative ^= true;
+                discriminant.sign = match discriminant.sign {
+                    Sign::Positive => Sign::Negative,
+                    Sign::Negative => Sign::Positive,
+                };
                 return Ok((discriminant, repr));
             }
         }
@@ -141,21 +152,25 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
 impl Discriminant {
     const fn zero() -> Self {
         Discriminant {
-            negative: false,
+            sign: Sign::Positive,
             magnitude: 0,
         }
     }
 
     const fn pos(u: u64) -> Self {
         Discriminant {
-            negative: false,
+            sign: Sign::Positive,
             magnitude: u,
         }
     }
 
     const fn neg(i: i64) -> Self {
         Discriminant {
-            negative: i < 0,
+            sign: if i < 0 {
+                Sign::Negative
+            } else {
+                Sign::Positive
+            },
             // This is `i.abs() as u64` but without overflow on MIN. Uses the
             // fact that MIN.wrapping_abs() wraps back to MIN whose binary
             // representation is 1<<63, and thus the `as u64` conversion
@@ -168,7 +183,7 @@ impl Discriminant {
 
 impl Display for Discriminant {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.negative {
+        if self.sign == Sign::Negative {
             f.write_str("-")?;
         }
         Display::fmt(&self.magnitude, f)
@@ -177,7 +192,7 @@ impl Display for Discriminant {
 
 impl ToTokens for Discriminant {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if self.negative {
+        if self.sign == Sign::Negative {
             Token![-](Span::call_site()).to_tokens(tokens);
         }
         Literal::u64_unsuffixed(self.magnitude).to_tokens(tokens);
@@ -188,15 +203,14 @@ impl FromStr for Discriminant {
     type Err = Error;
 
     fn from_str(mut s: &str) -> Result<Self> {
-        let negative = s.starts_with('-');
-        if negative {
+        let sign = if s.starts_with('-') {
             s = &s[1..];
-        }
+            Sign::Negative
+        } else {
+            Sign::Positive
+        };
         match s.parse::<u64>() {
-            Ok(magnitude) => Ok(Discriminant {
-                negative,
-                magnitude,
-            }),
+            Ok(magnitude) => Ok(Discriminant { sign, magnitude }),
             Err(_) => Err(Error::new(
                 Span::call_site(),
                 "discriminant value outside of supported range",
@@ -207,11 +221,12 @@ impl FromStr for Discriminant {
 
 impl Ord for Discriminant {
     fn cmp(&self, other: &Self) -> Ordering {
-        match (self.negative, other.negative) {
-            (true, true) => self.magnitude.cmp(&other.magnitude).reverse(),
-            (true, false) => Ordering::Less, // negative < positive
-            (false, true) => Ordering::Greater, // positive > negative
-            (false, false) => self.magnitude.cmp(&other.magnitude),
+        use self::Sign::{Negative, Positive};
+        match (self.sign, other.sign) {
+            (Negative, Negative) => self.magnitude.cmp(&other.magnitude).reverse(),
+            (Negative, Positive) => Ordering::Less, // negative < positive
+            (Positive, Negative) => Ordering::Greater, // positive > negative
+            (Positive, Positive) => self.magnitude.cmp(&other.magnitude),
         }
     }
 }

From 58eee39e609b72a1c0461e37fab85da6b942c3ab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 21 2020 04:37:58 +0000
Subject: [PATCH 1473/2232] Allow enum with undeclared variants as long as it has explicit repr


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0e603a6..0e8c469 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -221,9 +221,9 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
     check_reserved_name(cx, &enm.name.rust);
 
-    if enm.variants.is_empty() {
+    if enm.variants.is_empty() && !enm.explicit_repr {
         let span = span_for_enum_error(enm);
-        cx.error(span, "enums without any variants are not supported");
+        cx.error(span, "explicit #[repr(...)] is required for enum without any variants");
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2a3790c..475cec1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -91,6 +91,7 @@ pub struct Enum {
     pub variants: Vec<Variant>,
     pub repr: Atom,
     pub repr_type: Type,
+    pub explicit_repr: bool,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 25d95e6..38b3dcc 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -170,6 +170,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
+    let explicit_repr = repr.is_some();
     let mut repr = U8;
     match discriminants.inferred_repr() {
         Ok(inferred) => repr = inferred,
@@ -191,6 +192,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         variants,
         repr,
         repr_type,
+        explicit_repr,
     }))
 }
 
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
index 7f35019..0556da9 100644
--- a/tests/ui/empty_enum.stderr
+++ b/tests/ui/empty_enum.stderr
@@ -1,4 +1,4 @@
-error: enums without any variants are not supported
+error: explicit #[repr(...)] is required for enum without any variants
  --> $DIR/empty_enum.rs:3:5
   |
 3 |     enum A {}

From 30501b6befb56e8599fe021cea2955c73f9f1031 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 21 2020 04:49:20 +0000
Subject: [PATCH 1474/2232] Merge pull request #494 from dtolnay/enum


Allow enum with undeclared variants as long as it has explicit repr
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0e603a6..0e8c469 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -221,9 +221,9 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
     check_reserved_name(cx, &enm.name.rust);
 
-    if enm.variants.is_empty() {
+    if enm.variants.is_empty() && !enm.explicit_repr {
         let span = span_for_enum_error(enm);
-        cx.error(span, "enums without any variants are not supported");
+        cx.error(span, "explicit #[repr(...)] is required for enum without any variants");
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2a3790c..475cec1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -91,6 +91,7 @@ pub struct Enum {
     pub variants: Vec<Variant>,
     pub repr: Atom,
     pub repr_type: Type,
+    pub explicit_repr: bool,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 25d95e6..38b3dcc 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -170,6 +170,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
+    let explicit_repr = repr.is_some();
     let mut repr = U8;
     match discriminants.inferred_repr() {
         Ok(inferred) => repr = inferred,
@@ -191,6 +192,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         variants,
         repr,
         repr_type,
+        explicit_repr,
     }))
 }
 
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
index 7f35019..0556da9 100644
--- a/tests/ui/empty_enum.stderr
+++ b/tests/ui/empty_enum.stderr
@@ -1,4 +1,4 @@
-error: enums without any variants are not supported
+error: explicit #[repr(...)] is required for enum without any variants
  --> $DIR/empty_enum.rs:3:5
   |
 3 |     enum A {}

From 733cd260f0e2f46a74c674c0b6b1ec95fcf6491c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 21 2020 19:57:59 +0000
Subject: [PATCH 1475/2232] Remove deletion of Str(std::string &&) constructor


---

diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 2774754..7d7d6e8 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -20,7 +20,6 @@ public:
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
-  Str(std::string &&) = delete;
 
   Str &operator=(const Str &) noexcept;
 
diff --git a/include/cxx.h b/include/cxx.h
index 24a5292..4ed3302 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -63,7 +63,6 @@ public:
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
-  Str(std::string &&) = delete;
 
   Str &operator=(const Str &) noexcept = default;
 

From b4f4facb864a4db78f05523dee28f09715fbbc01 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 08:26:58 +0000
Subject: [PATCH 1476/2232] Format with rustfmt 1.4.27-nightly


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0e8c469..2e94f4d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -223,7 +223,10 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 
     if enm.variants.is_empty() && !enm.explicit_repr {
         let span = span_for_enum_error(enm);
-        cx.error(span, "explicit #[repr(...)] is required for enum without any variants");
+        cx.error(
+            span,
+            "explicit #[repr(...)] is required for enum without any variants",
+        );
     }
 }
 

From 0c4f92b040ef97d4ce9685aae2f48f5f169896a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 08:26:58 +0000
Subject: [PATCH 1477/2232] Add a target/../Cargo.toml condition for finding target dir


---

diff --git a/gen/build/src/target.rs b/gen/build/src/target.rs
index 58ada3a..4c9a9f3 100644
--- a/gen/build/src/target.rs
+++ b/gen/build/src/target.rs
@@ -1,4 +1,5 @@
 use std::env;
+use std::ffi::OsStr;
 use std::path::{Path, PathBuf};
 
 pub(crate) enum TargetDir {
@@ -24,7 +25,13 @@ pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
 
     let mut dir = out_dir.to_owned();
     loop {
-        if dir.join(".rustc_info.json").exists() || dir.join("CACHEDIR.TAG").exists() {
+        if dir.join(".rustc_info.json").exists()
+            || dir.join("CACHEDIR.TAG").exists()
+            || dir.file_name() == Some(OsStr::new("target"))
+                && dir
+                    .parent()
+                    .map_or(false, |parent| parent.join("Cargo.toml").exists())
+        {
             return TargetDir::Path(dir);
         }
         if dir.pop() {

From 1a003e5e5a1c650186656ba9f18833f2ba76d892 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 19:15:46 +0000
Subject: [PATCH 1478/2232] Make demo publishable from source tree ('cxx-demo' on crates.io)


---

diff --git a/demo/Cargo.toml b/demo/Cargo.toml
index dc94861..8328cde 100644
--- a/demo/Cargo.toml
+++ b/demo/Cargo.toml
@@ -2,11 +2,14 @@
 name = "demo"
 version = "0.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
+license = "MIT OR Apache-2.0"
+description = "Toy project from https://github.com/dtolnay/cxx"
+repository = "https://github.com/dtolnay/cxx"
 edition = "2018"
 publish = false
 
 [dependencies]
-cxx = { path = ".." }
+cxx = { version = "1.0", path = ".." }
 
 [build-dependencies]
-cxx-build = { path = "../gen/build" }
+cxx-build = { version = "1.0", path = "../gen/build" }

From 227ff0cbf587711ab7d2de5f261ea573e6b4a43a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 20:04:19 +0000
Subject: [PATCH 1479/2232] Fix test suite panic message forward compatibility lint


    warning: panic message contains braces
       --> tests/test.rs:21:9
        |
    21  |         assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
        |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...
    106 |     check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
        |     ---------------------------------------------------- in this macro invocation
        |
        = note: `#[warn(panic_fmt)]` on by default
        = note: this message is not used as a format string, but will be in a future Rust edition
        = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
    help: add a "{}" format string to use the message literally
        |
    21  |         assert!(CORRECT.with(|correct| correct.get()), "{}", stringify!($run));
        |                                                        ^^^^^

---

diff --git a/tests/test.rs b/tests/test.rs
index bf69379..2940b6e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -18,7 +18,7 @@ macro_rules! check {
     ($run:expr) => {{
         CORRECT.with(|correct| correct.set(false));
         $run;
-        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
+        assert!(CORRECT.with(|correct| correct.get()), "{}", stringify!($run));
     }};
 }
 

From 09a3086b456f8e3a5b90500ac63a0316462586cc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 20:04:38 +0000
Subject: [PATCH 1480/2232] Add UniquePtr::pin_mut


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 5a095ff..3655a7a 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -68,6 +68,19 @@ where
         }
     }
 
+    /// Returns a mutable pinned reference to the object owned by this
+    /// UniquePtr.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the UniquePtr holds a null pointer.
+    pub fn pin_mut(&mut self) -> Pin<&mut T> {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called pin_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+
     /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
     ///
     /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
diff --git a/tests/test.rs b/tests/test.rs
index 2940b6e..40004d1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -188,14 +188,11 @@ fn test_c_method_calls() {
 
     let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
+    assert_eq!(2021, unique_ptr.pin_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
-    assert_eq!(
-        2022,
-        unique_ptr.as_mut().unwrap().set_succeed(2022).unwrap(),
-    );
-    assert!(unique_ptr.as_mut().unwrap().get_fail().is_err());
+    assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap(),);
+    assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 }
 

From 8988a75049467317b71e5e2d17f09ad00ef66017 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 20:05:51 +0000
Subject: [PATCH 1481/2232] Format with rustfmt 1.4.27-nightly


---

diff --git a/tests/test.rs b/tests/test.rs
index 40004d1..24fa97f 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -18,7 +18,11 @@ macro_rules! check {
     ($run:expr) => {{
         CORRECT.with(|correct| correct.set(false));
         $run;
-        assert!(CORRECT.with(|correct| correct.get()), "{}", stringify!($run));
+        assert!(
+            CORRECT.with(|correct| correct.get()),
+            "{}",
+            stringify!($run),
+        );
     }};
 }
 

From 6bfc5b2bbcf2eed18f813a12ff0f00df743b1a8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 20:07:55 +0000
Subject: [PATCH 1482/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 06227df..d156717 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.63/src/**"]),
+    srcs = glob(["vendor/cc-1.0.65/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.48/src/**"]),
+    srcs = glob(["vendor/syn-1.0.50/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 521d7ad..bc46ed2 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -13,7 +13,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.63/src/**"]),
+    srcs = glob(["vendor/cc-1.0.65/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.48/src/**"]),
+    srcs = glob(["vendor/syn-1.0.50/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 97d6a1d..172d9c8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.63"
+version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad9c6140b5a2c7db40ea56eb1821245e5362b44385c05b76288b1a599934ac87"
+checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
 
 [[package]]
 name = "clap"
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.48"
+version = "1.0.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
+checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6"
 dependencies = [
  "proc-macro2",
  "quote",

From 9754dafe8a1e6f40785ae69dd32e20ed7384fa20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 22 2020 20:10:18 +0000
Subject: [PATCH 1483/2232] Release 1.0.2


---

diff --git a/Cargo.toml b/Cargo.toml
index f5e8ac5..8179f2a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.1" # remember to update html_root_url
+version = "1.0.2" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.1", path = "macro" }
+cxxbridge-macro = { version = "=1.0.2", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.1", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.2", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.1", path = "gen/build" }
+cxx-build = { version = "=1.0.2", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 601fff7..157eb9e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.1"
+version = "1.0.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 25ebabd..2588f7e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.1"
+version = "1.0.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 9d819d2..6e31687 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.1"
+version = "1.0.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 3708bf3..b7d1a3a 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.1"
+version = "0.7.2"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e8ce47d..8de2acd 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.1"
+version = "1.0.2"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index d921a54..0427af6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -361,7 +361,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.1")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.2")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 172d9c8..4ed4821 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.1"
+version = "1.0.2"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.1"
+version = "1.0.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.1"
+version = "0.7.2"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.1"
+version = "1.0.2"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.1"
+version = "1.0.2"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.1"
+version = "1.0.2"
 dependencies = [
  "cxx",
  "proc-macro2",

From 87cf418307db7ae1e2d96d080dfddcf18217d9ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:12:52 +0000
Subject: [PATCH 1484/2232] Switch apt to apt-get in CI


> WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a633fd8..b07df63 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -64,7 +64,7 @@ jobs:
           chmod +x bin/buck
           echo bin >> $GITHUB_PATH
       - name: Install lld
-        run: sudo apt install lld
+        run: sudo apt-get install lld
       - name: Vendor dependencies
         run: |
           cp third-party/Cargo.lock .

From 7b22c9f4f3b89aa2ac10717c6f8ba5e4a360e05a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:17:07 +0000
Subject: [PATCH 1485/2232] Update CI to use stable 1.48.0 compiler


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b07df63..02b22e5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
         include:
           - rust: nightly
           - rust: beta
-          #- rust: stable
-          #- rust: 1.48.0
+          - rust: stable
+          - rust: 1.48.0
           - name: macOS
             rust: nightly
             os: macos
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@beta
+      - uses: dtolnay/rust-toolchain@stable
       - uses: actions/setup-java@v1
         with:
           java-version: 11
diff --git a/WORKSPACE b/WORKSPACE
index 3fc2f90..039237b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -25,17 +25,15 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_48_beta_linux",
+    name = "rust_1_48_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 rust_repository_set(
-    name = "rust_1_48_beta_darwin",
+    name = "rust_1_48_darwin",
     exec_triple = "x86_64-apple-darwin",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 vendor(

From 7e8907a8450f529cd9846b9cca568a1e752e970e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:23:48 +0000
Subject: [PATCH 1486/2232] Merge pull request #499 from dtolnay/stable


Update CI to use stable 1.48.0 compiler
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b07df63..02b22e5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
         include:
           - rust: nightly
           - rust: beta
-          #- rust: stable
-          #- rust: 1.48.0
+          - rust: stable
+          - rust: 1.48.0
           - name: macOS
             rust: nightly
             os: macos
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@beta
+      - uses: dtolnay/rust-toolchain@stable
       - uses: actions/setup-java@v1
         with:
           java-version: 11
diff --git a/WORKSPACE b/WORKSPACE
index 3fc2f90..039237b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -25,17 +25,15 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_48_beta_linux",
+    name = "rust_1_48_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 rust_repository_set(
-    name = "rust_1_48_beta_darwin",
+    name = "rust_1_48_darwin",
     exec_triple = "x86_64-apple-darwin",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 vendor(

From 2580f7aa1072753859428d1aa5a750eb765f24ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:39 +0000
Subject: [PATCH 1487/2232] Remove unneeded flags from clang-tidy command in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 209ced5..dbe083d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -103,4 +103,4 @@ jobs:
         - name: Install clang-tidy
           run: sudo apt install clang-tidy-10
         - name: Run clang-tidy
-          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h' -- -Iinclude -xc++ -std=c++11
+          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h' -- -std=c++11

From 094adfafb02667a0b123301d67fbfc46fd36ce82 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:41 +0000
Subject: [PATCH 1488/2232] Move clang-tidy std flag to compilation database file


https://clang.llvm.org/docs/JSONCompilationDatabase.html#alternatives

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dbe083d..a78ecc5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -103,4 +103,4 @@ jobs:
         - name: Install clang-tidy
           run: sudo apt install clang-tidy-10
         - name: Run clang-tidy
-          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h' -- -std=c++11
+          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h'
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..c24e3b5
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1 @@
+-std=c++11

From 6f2a126c866db191ec277c5c52678faa92c90c48 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:42 +0000
Subject: [PATCH 1489/2232] Move header filter to clang-tidy config file


---

diff --git a/.clang-tidy b/.clang-tidy
index 597fa6c..55455e5 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,2 +1,3 @@
 Checks: clang-diagnostic-*,clang-analyzer-*,modernize-*,cppcoreguidelines-*,
     -modernize-use-trailing-return-type,-cppcoreguidelines-pro-type-reinterpret-cast
+HeaderFilterRegex: cxx\.h
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a78ecc5..0557c5d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -103,4 +103,4 @@ jobs:
         - name: Install clang-tidy
           run: sudo apt install clang-tidy-10
         - name: Run clang-tidy
-          run: clang-tidy-10 src/cxx.cc --header-filter='cxx\.h'
+          run: clang-tidy-10 src/cxx.cc

From 141052b0e8a1870ad316dcc14014583b22cfc964 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:43 +0000
Subject: [PATCH 1490/2232] Switch apt to apt-get in clang-tidy installation


> WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0557c5d..11df259 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -101,6 +101,6 @@ jobs:
       steps:
         - uses: actions/checkout@v2
         - name: Install clang-tidy
-          run: sudo apt install clang-tidy-10
+          run: sudo apt-get install clang-tidy-10
         - name: Run clang-tidy
           run: clang-tidy-10 src/cxx.cc

From 99b1a5cef5c5d57e04cf39837a4637254b19cb13 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:43 +0000
Subject: [PATCH 1491/2232] Fix yaml indentation in clang-tidy workflow job


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 11df259..b4ba7d5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -95,12 +95,12 @@ jobs:
       - uses: dtolnay/rust-toolchain@clippy
       - run: cargo clippy --workspace --tests -- -Dclippy::all
 
-    clang-tidy:
-      name: Clang Tidy
-      runs-on: ubuntu-latest
-      steps:
-        - uses: actions/checkout@v2
-        - name: Install clang-tidy
-          run: sudo apt-get install clang-tidy-10
-        - name: Run clang-tidy
-          run: clang-tidy-10 src/cxx.cc
+  clang-tidy:
+    name: Clang Tidy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install clang-tidy
+        run: sudo apt-get install clang-tidy-10
+      - name: Run clang-tidy
+        run: clang-tidy-10 src/cxx.cc

From 83bb58ce27beca0431f08ad2cbdea469872d7e77 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:44 +0000
Subject: [PATCH 1492/2232] Split clang-tidy config to one check/group per line


---

diff --git a/.clang-tidy b/.clang-tidy
index 55455e5..938acc4 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,3 +1,8 @@
-Checks: clang-diagnostic-*,clang-analyzer-*,modernize-*,cppcoreguidelines-*,
-    -modernize-use-trailing-return-type,-cppcoreguidelines-pro-type-reinterpret-cast
+Checks:
+  clang-analyzer-*,
+  clang-diagnostic-*,
+  cppcoreguidelines-*,
+  modernize-*,
+  -cppcoreguidelines-pro-type-reinterpret-cast,
+  -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h

From 1c70aca76172c65464dc2d579c07107a3fd9613c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:44 +0000
Subject: [PATCH 1493/2232] Suppress all currently triggered clang-tidy checks


---

diff --git a/.clang-tidy b/.clang-tidy
index 938acc4..b917995 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -3,6 +3,16 @@ Checks:
   clang-diagnostic-*,
   cppcoreguidelines-*,
   modernize-*,
+  -cppcoreguidelines-avoid-magic-numbers,
+  -cppcoreguidelines-macro-usage,
+  -cppcoreguidelines-owning-memory,
+  -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+  -cppcoreguidelines-pro-type-const-cast,
+  -cppcoreguidelines-pro-type-member-init,
   -cppcoreguidelines-pro-type-reinterpret-cast,
+  -cppcoreguidelines-special-member-functions,
+  -modernize-use-default-member-init,
+  -modernize-use-equals-default,
+  -modernize-use-override,
   -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h

From b5b260c2a7a3a504d28aa07496f54373cb094a53 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:40:45 +0000
Subject: [PATCH 1494/2232] Make clang-tidy fail CI on positive finding


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b4ba7d5..b47e8bc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -103,4 +103,4 @@ jobs:
       - name: Install clang-tidy
         run: sudo apt-get install clang-tidy-10
       - name: Run clang-tidy
-        run: clang-tidy-10 src/cxx.cc
+        run: clang-tidy-10 src/cxx.cc --warnings-as-errors=*

From 74c8ae42805ba15665bea845ce25c10b563fec9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 01:57:12 +0000
Subject: [PATCH 1495/2232] Merge pull request #501 from dtolnay/tidy


Run clang-tidy in CI
---

diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..b917995
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,18 @@
+Checks:
+  clang-analyzer-*,
+  clang-diagnostic-*,
+  cppcoreguidelines-*,
+  modernize-*,
+  -cppcoreguidelines-avoid-magic-numbers,
+  -cppcoreguidelines-macro-usage,
+  -cppcoreguidelines-owning-memory,
+  -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+  -cppcoreguidelines-pro-type-const-cast,
+  -cppcoreguidelines-pro-type-member-init,
+  -cppcoreguidelines-pro-type-reinterpret-cast,
+  -cppcoreguidelines-special-member-functions,
+  -modernize-use-default-member-init,
+  -modernize-use-equals-default,
+  -modernize-use-override,
+  -modernize-use-trailing-return-type,
+HeaderFilterRegex: cxx\.h
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 02b22e5..c9d60f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,3 +94,13 @@ jobs:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
       - run: cargo clippy --workspace --tests -- -Dclippy::all
+
+  clang-tidy:
+    name: Clang Tidy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install clang-tidy
+        run: sudo apt-get install clang-tidy-10
+      - name: Run clang-tidy
+        run: clang-tidy-10 src/cxx.cc --warnings-as-errors=*
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..c24e3b5
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1 @@
+-std=c++11

From 16bcd38cb905ca1c37a788e25a9b7ac8ef8cbf8c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:01:39 +0000
Subject: [PATCH 1496/2232] Link to clang-tidy lint tracking issue


---

diff --git a/.clang-tidy b/.clang-tidy
index b917995..f4a9d42 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,4 +1,6 @@
 Checks:
+  # TODO: many of these need to be resolved.
+  # https://github.com/dtolnay/cxx/issues/500
   clang-analyzer-*,
   clang-diagnostic-*,
   cppcoreguidelines-*,

From 06677b3e003a179c0fa73efa67dbfb5dce81ed99 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:07:52 +0000
Subject: [PATCH 1497/2232] Resolve cppcoreguidelines-avoid-magic-numbers


https://github.com/dtolnay/cxx/issues/500

---

diff --git a/.clang-tidy b/.clang-tidy
index f4a9d42..854e4d5 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -5,7 +5,6 @@ Checks:
   clang-diagnostic-*,
   cppcoreguidelines-*,
   modernize-*,
-  -cppcoreguidelines-avoid-magic-numbers,
   -cppcoreguidelines-macro-usage,
   -cppcoreguidelines-owning-memory,
   -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
diff --git a/src/cxx.cc b/src/cxx.cc
index ecc3668..122f6a5 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -240,10 +240,13 @@ void cxxbridge1$unique_ptr$std$string$drop(
 }
 } // extern "C"
 
+namespace {
+const size_t kMaxExpectedWordsInString = 8;
 static_assert(alignof(std::string) <= alignof(void *),
               "unexpectedly large std::string alignment");
-static_assert(sizeof(std::string) <= 8 * sizeof(void *),
+static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
               "unexpectedly large std::string size");
+}
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                             \

From 1567186114aa40923f46e1185ab6dcebdbae8b53 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:14:34 +0000
Subject: [PATCH 1498/2232] Resolve some instances of cppcoreguidelines-pro-type-member-init


https://github.com/dtolnay/cxx/issues/500

---

diff --git a/include/cxx.h b/include/cxx.h
index 4ed3302..8d7e96f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -483,8 +483,7 @@ Box<T>::Box() noexcept {}
 #ifndef CXXBRIDGE1_RUST_VEC
 #define CXXBRIDGE1_RUST_VEC
 template <typename T>
-Vec<T>::Vec(Vec &&other) noexcept {
-  this->repr = other.repr;
+Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 122f6a5..c954513 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -67,8 +67,7 @@ String::String(const String &other) noexcept {
   cxxbridge1$string$clone(this, other);
 }
 
-String::String(String &&other) noexcept {
-  this->repr = other.repr;
+String::String(String &&other) noexcept : repr(other.repr) {
   cxxbridge1$string$new(&other);
 }
 

From 79076c7b7116f91c98f3d15a60778789976c90d9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:17:01 +0000
Subject: [PATCH 1499/2232] Resolve modernize-use-equals-default


https://github.com/dtolnay/cxx/issues/500

---

diff --git a/.clang-tidy b/.clang-tidy
index 854e4d5..6e18fc8 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -13,7 +13,6 @@ Checks:
   -cppcoreguidelines-pro-type-reinterpret-cast,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
-  -modernize-use-equals-default,
   -modernize-use-override,
   -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h
diff --git a/include/cxx.h b/include/cxx.h
index 8d7e96f..f87d333 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -477,7 +477,7 @@ T *Box<T>::into_raw() noexcept {
 }
 
 template <typename T>
-Box<T>::Box() noexcept {}
+Box<T>::Box() noexcept = default;
 #endif // CXXBRIDGE1_RUST_BOX
 
 #ifndef CXXBRIDGE1_RUST_VEC

From 2714d2c98f3b3bd35ab960486058b463e67243e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:17:45 +0000
Subject: [PATCH 1500/2232] Resolve modernize-use-override


https://github.com/dtolnay/cxx/issues/500

---

diff --git a/.clang-tidy b/.clang-tidy
index 6e18fc8..9962a64 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -13,6 +13,5 @@ Checks:
   -cppcoreguidelines-pro-type-reinterpret-cast,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
-  -modernize-use-override,
   -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h
diff --git a/include/cxx.h b/include/cxx.h
index f87d333..8122786 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -250,7 +250,7 @@ class Error final : public std::exception {
 public:
   Error(const Error &);
   Error(Error &&) noexcept;
-  ~Error() noexcept;
+  ~Error() noexcept override;
 
   Error &operator=(const Error &);
   Error &operator=(Error &&) noexcept;

From c26de54e05cad447c8a012640aff938163c72255 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 02:18:19 +0000
Subject: [PATCH 1501/2232] Format with clang-format 10


---

diff --git a/src/cxx.cc b/src/cxx.cc
index c954513..4000b26 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -245,7 +245,7 @@ static_assert(alignof(std::string) <= alignof(void *),
               "unexpectedly large std::string alignment");
 static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
               "unexpectedly large std::string size");
-}
+} // namespace
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                             \

From 4092191f7398a462db83a45540ed1022cd9ae58c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 04:44:48 +0000
Subject: [PATCH 1502/2232] Add static assertions on nature of Slice special member functions


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 4000b26..923b641 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -169,6 +169,17 @@ static_assert(std::is_trivially_copy_assignable<Str>::value,
               "trivial operator=(const Str &)");
 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
 
+static_assert(std::is_trivially_copy_constructible<Slice<const uint8_t>>::value,
+              "trivial Slice(const Slice &)");
+static_assert(std::is_trivially_move_constructible<Slice<const uint8_t>>::value,
+              "trivial Slice(Slice &&)");
+static_assert(std::is_trivially_copy_assignable<Slice<const uint8_t>>::value,
+              "trivial Slice::operator=(const Slice &) for const slices");
+static_assert(std::is_trivially_move_assignable<Slice<const uint8_t>>::value,
+              "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<const uint8_t>>::value,
+              "trivial ~Slice()");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];

From 94469c2077b19a75a1dd3418cfe140f0badfd443 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 20:38:15 +0000
Subject: [PATCH 1503/2232] Move aux types lower in test suite


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 032adc4..902d3fc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -10,58 +10,6 @@ pub mod module;
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
-mod other {
-    use cxx::kind::{Opaque, Trivial};
-    use cxx::{type_id, CxxString, ExternType};
-
-    #[repr(C)]
-    pub struct D {
-        pub d: u64,
-    }
-
-    #[repr(C)]
-    pub struct E {
-        e: u64,
-        e_str: CxxString,
-    }
-
-    pub mod f {
-        use cxx::kind::Opaque;
-        use cxx::{type_id, CxxString, ExternType};
-
-        #[repr(C)]
-        pub struct F {
-            e: u64,
-            e_str: CxxString,
-        }
-
-        unsafe impl ExternType for F {
-            type Id = type_id!("F::F");
-            type Kind = Opaque;
-        }
-    }
-
-    #[repr(C)]
-    pub struct G {
-        pub g: u64,
-    }
-
-    unsafe impl ExternType for G {
-        type Id = type_id!("G::G");
-        type Kind = Trivial;
-    }
-
-    unsafe impl ExternType for D {
-        type Id = type_id!("tests::D");
-        type Kind = Trivial;
-    }
-
-    unsafe impl ExternType for E {
-        type Id = type_id!("tests::E");
-        type Kind = Opaque;
-    }
-}
-
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     #[derive(Clone)]
@@ -301,6 +249,58 @@ pub mod ffi {
     }
 }
 
+mod other {
+    use cxx::kind::{Opaque, Trivial};
+    use cxx::{type_id, CxxString, ExternType};
+
+    #[repr(C)]
+    pub struct D {
+        pub d: u64,
+    }
+
+    #[repr(C)]
+    pub struct E {
+        e: u64,
+        e_str: CxxString,
+    }
+
+    pub mod f {
+        use cxx::kind::Opaque;
+        use cxx::{type_id, CxxString, ExternType};
+
+        #[repr(C)]
+        pub struct F {
+            e: u64,
+            e_str: CxxString,
+        }
+
+        unsafe impl ExternType for F {
+            type Id = type_id!("F::F");
+            type Kind = Opaque;
+        }
+    }
+
+    #[repr(C)]
+    pub struct G {
+        pub g: u64,
+    }
+
+    unsafe impl ExternType for G {
+        type Id = type_id!("G::G");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for D {
+        type Id = type_id!("tests::D");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for E {
+        type Id = type_id!("tests::E");
+        type Kind = Opaque;
+    }
+}
+
 #[derive(PartialEq, Debug)]
 pub struct R(pub usize);
 

From cd271f2dc891cc7d836de66d219c9180adac198a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 20:38:18 +0000
Subject: [PATCH 1504/2232] Add some more slice test functions


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 902d3fc..762af4d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -186,6 +186,7 @@ pub mod ffi {
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
+        fn r_return_sliceu8(shared: &Shared) -> &[u8];
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
@@ -218,6 +219,7 @@ pub mod ffi {
         fn r_try_return_primitive() -> Result<usize>;
         fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
+        fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
 
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
@@ -364,6 +366,11 @@ fn r_return_str(shared: &ffi::Shared) -> &str {
     "2020"
 }
 
+fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
+    let _ = shared;
+    b"2020"
+}
+
 fn r_return_rust_string() -> String {
     "2020".to_owned()
 }
@@ -498,6 +505,10 @@ fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }
 
+fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
+    Ok(slice)
+}
+
 fn r_aliased_function(x: i32) -> String {
     x.to_string()
 }

From c5629f021eb64b1d451ecf8ceb9addab0e926e10 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 21:45:27 +0000
Subject: [PATCH 1505/2232] Support &mut [u8]


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 9c5f4fd..53facbf 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -149,7 +149,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.ptr_len {
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const void *ptr;");
+        writeln!(out, "  void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
         out.end_block(Block::Namespace("repr"));
@@ -173,7 +173,10 @@ pub(super) fn write(out: &mut OutFile) {
         }
         if builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(
+                out,
+                "    return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
+            );
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
@@ -189,18 +192,21 @@ pub(super) fn write(out: &mut OutFile) {
                 out,
                 "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
             );
-            writeln!(
-                out,
-                "    return {{static_cast<const T *>(repr.ptr), repr.len}};",
-            );
+            writeln!(out, "    return {{static_cast<T *>(repr.ptr), repr.len}};");
             writeln!(out, "  }}");
         }
         if builtin.rust_slice_repr {
+            include.type_traits = true;
             writeln!(
                 out,
                 "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
             );
-            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
+            writeln!(out, "    return repr::PtrLen{{");
+            writeln!(
+                out,
+                "        const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
+            );
+            writeln!(out, "        slice.len}};");
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index d997786..8b512da 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -436,9 +436,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.rust_str_repr = true;
             write!(out, "::rust::impl<::rust::Str>::repr(");
         }
-        Some(Type::SliceRefU8(_)) if !indirect_return => {
+        Some(ty @ Type::SliceRefU8(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
+            write!(out, "::rust::impl<");
+            write_type(out, ty);
+            write!(out, ">::repr(");
         }
         _ => {}
     }
@@ -474,12 +476,13 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if let Type::SliceRefU8(_) = arg.ty {
-            write!(
-                out,
-                "::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
-                arg.ident,
-            );
+        } else if let Type::SliceRefU8(slice) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(static_cast<");
+            if slice.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t *>({0}.ptr), {0}.len)", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -507,7 +510,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = ::cxxbridge1$exception(catch$, throw$.len);",
+            "        throw$.ptr = const_cast<char *>(::cxxbridge1$exception(catch$, throw$.len));",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -694,7 +697,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::slice(");
+                write!(out, "::rust::impl<");
+                write_type(out, ret);
+                write!(out, ">::slice(");
             }
             _ => {}
         }
@@ -720,7 +725,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
+                write!(out, "::rust::impl<");
+                write_type(out, &arg.ty);
+                write!(out, ">::repr(");
             }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -890,8 +897,12 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<const uint8_t>");
+        Type::SliceRefU8(ty) => {
+            write!(out, "::rust::Slice<");
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t>");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 8122786..1b30497 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -87,16 +87,28 @@ private:
 #endif // CXXBRIDGE1_RUST_STR
 
 #ifndef CXXBRIDGE1_RUST_SLICE
-template <typename T>
-class Slice final {
-  static_assert(std::is_const<T>::value,
-                "&[T] needs to be written as rust::Slice<const T> in C++");
+namespace detail {
+template <bool cond>
+struct copy_assignable_if {};
+
+template <>
+struct copy_assignable_if<false> {
+  copy_assignable_if() noexcept = default;
+  copy_assignable_if(const copy_assignable_if &) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+};
+} // namespace detail
 
+template <typename T>
+class Slice final
+    : private detail::copy_assignable_if<std::is_const<T>::value> {
 public:
   Slice() noexcept;
   Slice(T *, size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
+  Slice &operator=(Slice<T> &&) noexcept = default;
 
   T *data() const noexcept;
   size_t size() const noexcept;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f29c4cc..1fee928 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -330,7 +330,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
-            Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
+                true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
         }
@@ -423,7 +426,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRefU8(_) => quote!(#call.as_slice()),
+                Type::SliceRefU8(ty) => match ty.mutable {
+                    false => quote!(#call.as_slice()),
+                    true => quote!(#call.as_mut_slice()),
+                },
                 _ => call,
             },
         };
@@ -610,7 +616,10 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRefU8(_) => quote!(#ident.as_slice()),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(#ident.as_slice()),
+                true => quote!(#ident.as_mut_slice()),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -654,7 +663,10 @@ fn expand_rust_function_shim_impl(
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
-        Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
+            true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
+        },
         _ => None,
     });
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 923b641..28506ef 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -180,6 +180,17 @@ static_assert(std::is_trivially_move_assignable<Slice<const uint8_t>>::value,
 static_assert(std::is_trivially_destructible<Slice<const uint8_t>>::value,
               "trivial ~Slice()");
 
+static_assert(std::is_trivially_copy_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(const Slice &)");
+static_assert(std::is_trivially_move_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(Slice &&)");
+static_assert(!std::is_copy_assignable<Slice<uint8_t>>::value,
+              "delete Slice::operator=(const Slice &) for mut slices");
+static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
+              "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
+              "trivial ~Slice()");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index 32f8798..e14f988 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -11,16 +11,27 @@ pub struct RustSliceU8 {
 }
 
 impl RustSliceU8 {
-    pub fn from(s: &[u8]) -> Self {
+    pub fn from_ref(s: &[u8]) -> Self {
         RustSliceU8 {
             ptr: NonNull::from(s).cast::<u8>(),
             len: s.len(),
         }
     }
 
+    pub fn from_mut(s: &mut [u8]) -> Self {
+        RustSliceU8 {
+            len: s.len(),
+            ptr: NonNull::from(s).cast::<u8>(),
+        }
+    }
+
     pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
         slice::from_raw_parts(self.ptr.as_ptr(), self.len)
     }
+
+    pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [u8] {
+        slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
+    }
 }
 
 const_assert_eq!(
diff --git a/syntax/check.rs b/syntax/check.rs
index 2e94f4d..1ec6178 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -178,7 +178,10 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice(cx: &mut Check, ty: &Slice) {
-    cx.error(ty, "only &[u8] is supported so far, not other slice types");
+    cx.error(
+        ty,
+        "only &[u8] and &mut [u8] are supported so far, not other slice types",
+    );
 }
 
 fn check_type_fn(cx: &mut Check, ty: &Signature) {
@@ -489,7 +492,10 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
-        Type::SliceRefU8(_) => "&[u8]".to_owned(),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => "&[u8]".to_owned(),
+            true => "&mut [u8]".to_owned(),
+        },
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 38b3dcc..c6d6480 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -658,7 +658,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
             }
         }
         Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
             _ => Type::Ref,
         },
         _ => Type::Ref,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 762af4d..af72fb4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -77,6 +77,7 @@ pub mod ffi {
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
+        fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
@@ -140,6 +141,7 @@ pub mod ffi {
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
@@ -187,6 +189,7 @@ pub mod ffi {
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_sliceu8(shared: &Shared) -> &[u8];
+        fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
@@ -220,6 +223,7 @@ pub mod ffi {
         fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
         fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn r_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
 
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
@@ -371,6 +375,10 @@ fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
     b"2020"
 }
 
+fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8] {
+    slice
+}
+
 fn r_return_rust_string() -> String {
     "2020".to_owned()
 }
@@ -509,6 +517,10 @@ fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
     Ok(slice)
 }
 
+fn r_try_return_mutsliceu8(slice: &mut [u8]) -> Result<&mut [u8], Error> {
+    Ok(slice)
+}
+
 fn r_aliased_function(x: i32) -> String {
     x.to_string()
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f1c293d..238b145 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -77,6 +77,10 @@ rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
       reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
 }
 
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
+  return slice;
+}
+
 rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
@@ -435,6 +439,10 @@ rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
   return s;
 }
 
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) {
+  return s;
+}
+
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 5acf469..6c288d7 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -84,6 +84,7 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -148,6 +149,7 @@ rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
 rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();

From 5945e56497406118d58ea788f32a7ed32fdeebea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 22:03:18 +0000
Subject: [PATCH 1506/2232] Add &mut [u8] to readme and website


---

diff --git a/README.md b/README.md
index bc76006..e4ac67e 100644
--- a/README.md
+++ b/README.md
@@ -323,6 +323,7 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 31cbb46..e10c2cc 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -25,7 +25,7 @@
 - [Reference: built-in bindings](bindings.md)
     - [String &mdash; rust::String](binding/string.md)
     - [&str &mdash; rust::Str](binding/str.md)
-    - [&&#91;T&#93; &mdash; rust::Slice\<const T\>](binding/slice.md)
+    - [&&#91;T&#93;, &mut &#91;T&#93; &mdash; rust::Slice\<T\>](binding/slice.md)
     - [CxxString &mdash; std::string](binding/cxxstring.md)
     - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
     - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index aacd56b..4da7d73 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -1,5 +1,8 @@
 {{#title rust::Slice<T> — Rust ♡ C++}}
-# rust::Slice\<T\>
+# rust::Slice\<const T\>,&ensp;rust::Slice\<T\>
+
+- Rust `&[T]` is written `rust::Slice<const T>` in C++
+- Rust `&mut [T]` is written `rust::Slice<T>` in C++
 
 ### Public API:
 
@@ -15,7 +18,10 @@ public:
   Slice(const Slice<T> &) noexcept;
   Slice(T *, size_t count) noexcept;
 
+  // if std::is_const<T> {
   Slice &operator=(const Slice<T> &) noexcept;
+  // }
+  Slice &operator=(Slice<T> &&) noexcept;
 
   T *data() const noexcept;
   size_t size() const noexcept;
@@ -27,11 +33,14 @@ public:
 
 ### Restrictions:
 
-Only &amp;\[u8\] i.e. rust::Slice\<const uint8\_t\> is currently implemented.
-Support for arbitrary &amp;\[T\] is coming.
+Only T=u8 i.e. rust::Slice\<const uint8\_t\> and rust::Slice\<uint8\_t\> are
+currently implemented. Support for arbitrary T is coming.
 
 Allowed as function argument or return value. Not supported in shared structs.
-&amp;mut \[T\] is not supported yet.
+
+Only rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are
+move-assignable.) You'll need to write std::move occasionally as a reminder that
+accidentally exposing overlapping &amp;mut \[T\] to Rust is UB.
 
 ## Example
 
diff --git a/book/src/bindings.md b/book/src/bindings.md
index f19dc5d..df6a8d7 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -12,6 +12,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;mut [u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -43,7 +44,6 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/src/lib.rs b/src/lib.rs
index 0427af6..d1c894e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -332,6 +332,7 @@
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>

From 3a6044bbfc38ade8d34d51053679dece2d489944 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 22:09:43 +0000
Subject: [PATCH 1507/2232] Merge pull request #502 from dtolnay/mut


Support &mut [u8]
---

diff --git a/README.md b/README.md
index bc76006..e4ac67e 100644
--- a/README.md
+++ b/README.md
@@ -323,6 +323,7 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 31cbb46..e10c2cc 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -25,7 +25,7 @@
 - [Reference: built-in bindings](bindings.md)
     - [String &mdash; rust::String](binding/string.md)
     - [&str &mdash; rust::Str](binding/str.md)
-    - [&&#91;T&#93; &mdash; rust::Slice\<const T\>](binding/slice.md)
+    - [&&#91;T&#93;, &mut &#91;T&#93; &mdash; rust::Slice\<T\>](binding/slice.md)
     - [CxxString &mdash; std::string](binding/cxxstring.md)
     - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
     - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index aacd56b..4da7d73 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -1,5 +1,8 @@
 {{#title rust::Slice<T> — Rust ♡ C++}}
-# rust::Slice\<T\>
+# rust::Slice\<const T\>,&ensp;rust::Slice\<T\>
+
+- Rust `&[T]` is written `rust::Slice<const T>` in C++
+- Rust `&mut [T]` is written `rust::Slice<T>` in C++
 
 ### Public API:
 
@@ -15,7 +18,10 @@ public:
   Slice(const Slice<T> &) noexcept;
   Slice(T *, size_t count) noexcept;
 
+  // if std::is_const<T> {
   Slice &operator=(const Slice<T> &) noexcept;
+  // }
+  Slice &operator=(Slice<T> &&) noexcept;
 
   T *data() const noexcept;
   size_t size() const noexcept;
@@ -27,11 +33,14 @@ public:
 
 ### Restrictions:
 
-Only &amp;\[u8\] i.e. rust::Slice\<const uint8\_t\> is currently implemented.
-Support for arbitrary &amp;\[T\] is coming.
+Only T=u8 i.e. rust::Slice\<const uint8\_t\> and rust::Slice\<uint8\_t\> are
+currently implemented. Support for arbitrary T is coming.
 
 Allowed as function argument or return value. Not supported in shared structs.
-&amp;mut \[T\] is not supported yet.
+
+Only rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are
+move-assignable.) You'll need to write std::move occasionally as a reminder that
+accidentally exposing overlapping &amp;mut \[T\] to Rust is UB.
 
 ## Example
 
diff --git a/book/src/bindings.md b/book/src/bindings.md
index f19dc5d..df6a8d7 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -12,6 +12,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;mut [u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -43,7 +44,6 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 9c5f4fd..53facbf 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -149,7 +149,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.ptr_len {
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const void *ptr;");
+        writeln!(out, "  void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
         out.end_block(Block::Namespace("repr"));
@@ -173,7 +173,10 @@ pub(super) fn write(out: &mut OutFile) {
         }
         if builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(
+                out,
+                "    return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
+            );
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
@@ -189,18 +192,21 @@ pub(super) fn write(out: &mut OutFile) {
                 out,
                 "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
             );
-            writeln!(
-                out,
-                "    return {{static_cast<const T *>(repr.ptr), repr.len}};",
-            );
+            writeln!(out, "    return {{static_cast<T *>(repr.ptr), repr.len}};");
             writeln!(out, "  }}");
         }
         if builtin.rust_slice_repr {
+            include.type_traits = true;
             writeln!(
                 out,
                 "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
             );
-            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
+            writeln!(out, "    return repr::PtrLen{{");
+            writeln!(
+                out,
+                "        const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
+            );
+            writeln!(out, "        slice.len}};");
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index d997786..8b512da 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -436,9 +436,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.rust_str_repr = true;
             write!(out, "::rust::impl<::rust::Str>::repr(");
         }
-        Some(Type::SliceRefU8(_)) if !indirect_return => {
+        Some(ty @ Type::SliceRefU8(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
+            write!(out, "::rust::impl<");
+            write_type(out, ty);
+            write!(out, ">::repr(");
         }
         _ => {}
     }
@@ -474,12 +476,13 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if let Type::SliceRefU8(_) = arg.ty {
-            write!(
-                out,
-                "::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
-                arg.ident,
-            );
+        } else if let Type::SliceRefU8(slice) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(static_cast<");
+            if slice.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t *>({0}.ptr), {0}.len)", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -507,7 +510,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = ::cxxbridge1$exception(catch$, throw$.len);",
+            "        throw$.ptr = const_cast<char *>(::cxxbridge1$exception(catch$, throw$.len));",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -694,7 +697,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::slice(");
+                write!(out, "::rust::impl<");
+                write_type(out, ret);
+                write!(out, ">::slice(");
             }
             _ => {}
         }
@@ -720,7 +725,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
+                write!(out, "::rust::impl<");
+                write_type(out, &arg.ty);
+                write!(out, ">::repr(");
             }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -890,8 +897,12 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<const uint8_t>");
+        Type::SliceRefU8(ty) => {
+            write!(out, "::rust::Slice<");
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t>");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 8122786..1b30497 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -87,16 +87,28 @@ private:
 #endif // CXXBRIDGE1_RUST_STR
 
 #ifndef CXXBRIDGE1_RUST_SLICE
-template <typename T>
-class Slice final {
-  static_assert(std::is_const<T>::value,
-                "&[T] needs to be written as rust::Slice<const T> in C++");
+namespace detail {
+template <bool cond>
+struct copy_assignable_if {};
+
+template <>
+struct copy_assignable_if<false> {
+  copy_assignable_if() noexcept = default;
+  copy_assignable_if(const copy_assignable_if &) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+};
+} // namespace detail
 
+template <typename T>
+class Slice final
+    : private detail::copy_assignable_if<std::is_const<T>::value> {
 public:
   Slice() noexcept;
   Slice(T *, size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
+  Slice &operator=(Slice<T> &&) noexcept = default;
 
   T *data() const noexcept;
   size_t size() const noexcept;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f29c4cc..1fee928 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -330,7 +330,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
-            Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
+                true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
         }
@@ -423,7 +426,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRefU8(_) => quote!(#call.as_slice()),
+                Type::SliceRefU8(ty) => match ty.mutable {
+                    false => quote!(#call.as_slice()),
+                    true => quote!(#call.as_mut_slice()),
+                },
                 _ => call,
             },
         };
@@ -610,7 +616,10 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRefU8(_) => quote!(#ident.as_slice()),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(#ident.as_slice()),
+                true => quote!(#ident.as_mut_slice()),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -654,7 +663,10 @@ fn expand_rust_function_shim_impl(
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
-        Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
+            true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
+        },
         _ => None,
     });
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 923b641..28506ef 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -180,6 +180,17 @@ static_assert(std::is_trivially_move_assignable<Slice<const uint8_t>>::value,
 static_assert(std::is_trivially_destructible<Slice<const uint8_t>>::value,
               "trivial ~Slice()");
 
+static_assert(std::is_trivially_copy_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(const Slice &)");
+static_assert(std::is_trivially_move_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(Slice &&)");
+static_assert(!std::is_copy_assignable<Slice<uint8_t>>::value,
+              "delete Slice::operator=(const Slice &) for mut slices");
+static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
+              "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
+              "trivial ~Slice()");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];
diff --git a/src/lib.rs b/src/lib.rs
index 0427af6..d1c894e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -332,6 +332,7 @@
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index 32f8798..e14f988 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -11,16 +11,27 @@ pub struct RustSliceU8 {
 }
 
 impl RustSliceU8 {
-    pub fn from(s: &[u8]) -> Self {
+    pub fn from_ref(s: &[u8]) -> Self {
         RustSliceU8 {
             ptr: NonNull::from(s).cast::<u8>(),
             len: s.len(),
         }
     }
 
+    pub fn from_mut(s: &mut [u8]) -> Self {
+        RustSliceU8 {
+            len: s.len(),
+            ptr: NonNull::from(s).cast::<u8>(),
+        }
+    }
+
     pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
         slice::from_raw_parts(self.ptr.as_ptr(), self.len)
     }
+
+    pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [u8] {
+        slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
+    }
 }
 
 const_assert_eq!(
diff --git a/syntax/check.rs b/syntax/check.rs
index 2e94f4d..1ec6178 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -178,7 +178,10 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice(cx: &mut Check, ty: &Slice) {
-    cx.error(ty, "only &[u8] is supported so far, not other slice types");
+    cx.error(
+        ty,
+        "only &[u8] and &mut [u8] are supported so far, not other slice types",
+    );
 }
 
 fn check_type_fn(cx: &mut Check, ty: &Signature) {
@@ -489,7 +492,10 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
-        Type::SliceRefU8(_) => "&[u8]".to_owned(),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => "&[u8]".to_owned(),
+            true => "&mut [u8]".to_owned(),
+        },
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 38b3dcc..c6d6480 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -658,7 +658,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
             }
         }
         Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
             _ => Type::Ref,
         },
         _ => Type::Ref,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 762af4d..af72fb4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -77,6 +77,7 @@ pub mod ffi {
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
+        fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
@@ -140,6 +141,7 @@ pub mod ffi {
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
@@ -187,6 +189,7 @@ pub mod ffi {
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
         fn r_return_sliceu8(shared: &Shared) -> &[u8];
+        fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
@@ -220,6 +223,7 @@ pub mod ffi {
         fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
         fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn r_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
 
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
@@ -371,6 +375,10 @@ fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
     b"2020"
 }
 
+fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8] {
+    slice
+}
+
 fn r_return_rust_string() -> String {
     "2020".to_owned()
 }
@@ -509,6 +517,10 @@ fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
     Ok(slice)
 }
 
+fn r_try_return_mutsliceu8(slice: &mut [u8]) -> Result<&mut [u8], Error> {
+    Ok(slice)
+}
+
 fn r_aliased_function(x: i32) -> String {
     x.to_string()
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f1c293d..238b145 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -77,6 +77,10 @@ rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
       reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
 }
 
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
+  return slice;
+}
+
 rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
@@ -435,6 +439,10 @@ rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
   return s;
 }
 
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) {
+  return s;
+}
+
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 5acf469..6c288d7 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -84,6 +84,7 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -148,6 +149,7 @@ rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
 rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();

From 702434cb768b3b994b1dd1c580a10c7ee2024d12 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 22:15:18 +0000
Subject: [PATCH 1508/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index d156717..6cc37e8 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.50/src/**"]),
+    srcs = glob(["vendor/syn-1.0.51/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index bc46ed2..ef9dba1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.50/src/**"]),
+    srcs = glob(["vendor/syn-1.0.51/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4ed4821..7d60781 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.50"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "443b4178719c5a851e1bde36ce12da21d74a0e60b4d982ec3385a933c812f0f6"
+checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223"
 dependencies = [
  "proc-macro2",
  "quote",

From 0c6417f21ddec0f0804cef927aaf04106dce0785 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 24 2020 22:15:48 +0000
Subject: [PATCH 1509/2232] Release 1.0.3


---

diff --git a/Cargo.toml b/Cargo.toml
index 8179f2a..c84106d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.2" # remember to update html_root_url
+version = "1.0.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.2", path = "macro" }
+cxxbridge-macro = { version = "=1.0.3", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.2", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.3", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.2", path = "gen/build" }
+cxx-build = { version = "=1.0.3", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 157eb9e..194d53c 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.2"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 2588f7e..1b0b488 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.2"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 6e31687..ed79053 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.2"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index b7d1a3a..4bf4f2b 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.2"
+version = "0.7.3"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 8de2acd..3b86dc4 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.2"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index d1c894e..a057732 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -362,7 +362,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.2")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.3")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 7d60781..b1d1aca 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.2"
+version = "1.0.3"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.2"
+version = "1.0.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.2"
+version = "0.7.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.2"
+version = "1.0.3"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.2"
+version = "1.0.3"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.2"
+version = "1.0.3"
 dependencies = [
  "cxx",
  "proc-macro2",

From f5ead103f38080f3d91465b2679d92b7db336b39 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 01:08:05 +0000
Subject: [PATCH 1510/2232] Resolve clippy unnecessary_wraps lints


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index c6d6480..8ce767c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -236,10 +236,8 @@ fn parse_foreign_mod(
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, &namespace) {
-                    Ok(ety) => items.push(ety),
-                    Err(err) => cx.push(err),
-                }
+                let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
+                items.push(ety);
             }
             ForeignItem::Fn(foreign) => {
                 match parse_extern_fn(cx, foreign, lang, trusted, &namespace) {
@@ -322,7 +320,7 @@ fn parse_extern_type(
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
-) -> Result<Api> {
+) -> Api {
     let mut doc = Doc::new();
     let mut namespace = namespace.clone();
     attrs::parse(
@@ -341,13 +339,13 @@ fn parse_extern_type(
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
     };
-    Ok(api_type(ExternType {
+    api_type(ExternType {
         doc,
         type_token,
         name: Pair::new(namespace, ident),
         semi_token,
         trusted,
-    }))
+    })
 }
 
 fn parse_extern_fn(
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index af72fb4..aa9d3b4 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -2,7 +2,8 @@
     clippy::boxed_local,
     clippy::just_underscores_and_digits,
     clippy::ptr_arg,
-    clippy::trivially_copy_pass_by_ref
+    clippy::trivially_copy_pass_by_ref,
+    clippy::unnecessary_wraps
 )]
 
 pub mod module;

From 7876235c3f26a517f4a31ce036b23f891757c8da Mon Sep 17 00:00:00 2001
From: Xiangpeng Hao <haoxiangpeng123@gmail.com>
Date: Nov 25 2020 04:23:29 +0000
Subject: [PATCH 1511/2232] add initial array support


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 71d6163..f90a76f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -172,6 +172,9 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
             }
+            Type::Array(_) => {
+                out.include.array = true;
+            }
             Type::Ref(_) | Type::Void(_) => {}
         }
     }
@@ -902,6 +905,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             }
             write!(out, ")>");
         }
+        Type::Array(a) => {
+            write!(out, "::std::array<");
+            write_type(out, &a.inner);
+            write!(out, ", {}>", &a.len);
+        }
         Type::Void(_) => unreachable!(),
     }
 }
@@ -940,7 +948,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::CxxVector(_)
         | Type::RustVec(_)
         | Type::SliceRefU8(_)
-        | Type::Fn(_) => write!(out, " "),
+        | Type::Fn(_)
+        | Type::Array(_) => write!(out, " "),
         Type::Ref(_) => {}
         Type::Void(_) | Type::Slice(_) => unreachable!(),
     }
diff --git a/syntax/check.rs b/syntax/check.rs
index 53dd843..06e99fe 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
+    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
     Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
@@ -35,6 +35,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
+            Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
         }
@@ -181,6 +182,21 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
     cx.error(ty, "only &[u8] is supported so far, not other slice types");
 }
 
+fn check_type_array(cx: &mut Check, ty: &Array) {
+    match &ty.inner {
+        Type::Ident(ident) => {
+            if cx.types.rust.contains(&ident.rust) || cx.types.cxx.contains(&ident.rust) {
+                cx.error(ty, "Only shared structs are supported in array yet");
+            }
+        }
+        Type::RustBox(ty1) => check_type_box(cx, ty1),
+        Type::RustVec(ty1) => check_type_rust_vec(cx, ty1),
+        Type::CxxVector(ty1) => check_type_cxx_vector(cx, ty1),
+        Type::UniquePtr(ty1) => check_type_unique_ptr(cx, ty1),
+        _ => cx.error(ty, "unsupported array target type"),
+    };
+}
+
 fn check_type_fn(cx: &mut Check, ty: &Signature) {
     if ty.throws {
         cx.error(ty, "function pointer returning Result is not supported yet");
@@ -480,5 +496,6 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::SliceRefU8(_) => "&[u8]".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
+        Type::Array(_) => "array".to_owned(),
     }
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a9c48c3..6fae2f9 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{Array, ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
@@ -50,6 +50,7 @@ impl Hash for Type {
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
+            Type::Array(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -173,6 +174,37 @@ impl Hash for Slice {
     }
 }
 
+impl Eq for Array {}
+impl PartialEq for Array {
+    fn eq(&self, other: &Array) -> bool {
+        let Array {
+            bracket: _,
+            inner,
+            semi_token: _,
+            len,
+        } = self;
+        let Array {
+            bracket: _,
+            inner: inner2,
+            semi_token: _,
+            len: len2,
+        } = other;
+        inner == inner2 && len == len2
+    }
+}
+impl Hash for Array {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Array {
+            bracket: _,
+            inner,
+            semi_token: _,
+            len,
+        } = self;
+        inner.hash(state);
+        len.to_string().hash(state);
+    }
+}
+
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6fd3162..e016884 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -31,6 +31,7 @@ impl<'a> Types<'a> {
             | Type::SliceRefU8(_) => Definite(true),
             Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+            Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 2a3790c..4d65874 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -165,6 +165,7 @@ pub enum Type {
     Void(Span),
     Slice(Box<Slice>),
     SliceRefU8(Box<Ref>),
+    Array(Box<Array>),
 }
 
 pub struct Ty1 {
@@ -189,6 +190,13 @@ pub struct Slice {
     pub inner: Type,
 }
 
+pub struct Array {
+    pub bracket: Bracket,
+    pub inner: Type,
+    pub semi_token: Token![;],
+    pub len: usize,
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum Lang {
     Cxx,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index ec89cbb..0099299 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
+    attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
@@ -12,10 +12,10 @@ use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat,
-    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
-    TypeReference, TypeSlice,
+    Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
+    Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
+    TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -623,10 +623,49 @@ fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
         RustType::Slice(ty) => parse_type_slice(ty, namespace),
         RustType::BareFn(ty) => parse_type_fn(ty, namespace),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
+        RustType::Array(ty) => parse_type_array(ty, namespace),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
+fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, namespace)?;
+    match &ty.len {
+        Expr::Lit(lit) => {
+            if !lit.attrs.is_empty() {
+                return Err(Error::new_spanned(
+                    ty,
+                    "attribute not allowed in length field",
+                ));
+            }
+            match &lit.lit {
+                Lit::Int(v) => {
+                    let v = match v.base10_parse::<usize>() {
+                        Ok(n_v) => n_v,
+                        Err(_) => {
+                            return Err(Error::new_spanned(
+                                ty,
+                                "Cannot parse integer literal to base10",
+                            ))
+                        }
+                    };
+                    Ok(Type::Array(Box::new(Array {
+                        bracket: ty.bracket_token,
+                        inner,
+                        semi_token: ty.semi_token,
+                        len: v,
+                    })))
+                }
+                _ => Err(Error::new_spanned(ty, "length literal must be a integer")),
+            }
+        }
+        _ => Err(Error::new_spanned(
+            ty,
+            "only literal is currently supported in len field",
+        )),
+    }
+}
+
 fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
     let inner = parse_type(&ty.elem, namespace)?;
     let which = match &inner {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 40ab723..27c2693 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
-    Slice, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
+    Signature, Slice, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -22,6 +22,7 @@ impl ToTokens for Type {
             }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
             Type::Slice(s) => s.to_tokens(tokens),
+            Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
@@ -68,6 +69,16 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Array {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.bracket.surround(tokens, |tokens| {
+            self.inner.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+            self.len.to_tokens(tokens);
+        });
+    }
+}
+
 impl ToTokens for Slice {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.bracket.surround(tokens, |tokens| {
diff --git a/syntax/types.rs b/syntax/types.rs
index 92c9a75..84b03be 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -49,6 +49,7 @@ impl<'a> Types<'a> {
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
+                Type::Array(a) => visit(all, &a.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5844bd1..bfc1e43 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -116,6 +116,10 @@ pub mod ffi {
         i: i32,
     }
 
+    pub struct Array {
+        a: [i32; 4],
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
@@ -204,6 +208,7 @@ pub mod ffi {
         fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
         fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
+        fn c_set_array(self: &mut Array, value: i32);
 
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
@@ -274,6 +279,7 @@ pub mod ffi {
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
         fn r_method_on_shared(self: &Shared) -> String;
+        fn r_get_array_sum(self: &Array) -> i32;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -321,6 +327,12 @@ impl ffi::Shared {
     }
 }
 
+impl ffi::Array {
+    pub fn r_get_array_sum(&self) -> i32 {
+        self.a.iter().sum()
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f1c293d..ef72047 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -32,6 +32,10 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 size_t Shared::c_method_on_shared() const noexcept { return 2021; }
 
+void Array::c_set_array(int32_t val) noexcept {
+  this->a = {val, val, val, val};
+}
+
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
 std::vector<uint8_t> &C::get_v() { return this->v; }
diff --git a/tests/test.rs b/tests/test.rs
index e5e1373..141ebeb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -197,6 +197,11 @@ fn test_c_method_calls() {
     );
     assert!(unique_ptr.as_mut().unwrap().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
+
+    let val = 42;
+    let mut array = ffi::Array { a: [0, 0, 0, 0] };
+    array.c_set_array(val);
+    assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum());
 }
 
 #[test]

From 7750b8165a28c39219f527fcef41b0bbe7aa08b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 04:25:43 +0000
Subject: [PATCH 1512/2232] Merge master into pr/459


---

diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..9962a64
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,17 @@
+Checks:
+  # TODO: many of these need to be resolved.
+  # https://github.com/dtolnay/cxx/issues/500
+  clang-analyzer-*,
+  clang-diagnostic-*,
+  cppcoreguidelines-*,
+  modernize-*,
+  -cppcoreguidelines-macro-usage,
+  -cppcoreguidelines-owning-memory,
+  -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+  -cppcoreguidelines-pro-type-const-cast,
+  -cppcoreguidelines-pro-type-member-init,
+  -cppcoreguidelines-pro-type-reinterpret-cast,
+  -cppcoreguidelines-special-member-functions,
+  -modernize-use-default-member-init,
+  -modernize-use-trailing-return-type,
+HeaderFilterRegex: cxx\.h
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a633fd8..c9d60f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,8 +15,8 @@ jobs:
         include:
           - rust: nightly
           - rust: beta
-          #- rust: stable
-          #- rust: 1.48.0
+          - rust: stable
+          - rust: 1.48.0
           - name: macOS
             rust: nightly
             os: macos
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: dtolnay/rust-toolchain@beta
+      - uses: dtolnay/rust-toolchain@stable
       - uses: actions/setup-java@v1
         with:
           java-version: 11
@@ -64,7 +64,7 @@ jobs:
           chmod +x bin/buck
           echo bin >> $GITHUB_PATH
       - name: Install lld
-        run: sudo apt install lld
+        run: sudo apt-get install lld
       - name: Vendor dependencies
         run: |
           cp third-party/Cargo.lock .
@@ -94,3 +94,13 @@ jobs:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
       - run: cargo clippy --workspace --tests -- -Dclippy::all
+
+  clang-tidy:
+    name: Clang Tidy
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Install clang-tidy
+        run: sudo apt-get install clang-tidy-10
+      - name: Run clang-tidy
+        run: clang-tidy-10 src/cxx.cc --warnings-as-errors=*
diff --git a/Cargo.toml b/Cargo.toml
index 4fad728..c84106d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.0" # remember to update html_root_url
+version = "1.0.3" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.0", path = "macro" }
+cxxbridge-macro = { version = "=1.0.3", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.0", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.3", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.0", path = "gen/build" }
+cxx-build = { version = "=1.0.3", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/README.md b/README.md
index bc76006..e4ac67e 100644
--- a/README.md
+++ b/README.md
@@ -323,6 +323,7 @@ returns of functions.
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/WORKSPACE b/WORKSPACE
index 3fc2f90..039237b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -25,17 +25,15 @@ bazel_version(name = "bazel_version")
 load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
 
 rust_repository_set(
-    name = "rust_1_48_beta_linux",
+    name = "rust_1_48_linux",
     exec_triple = "x86_64-unknown-linux-gnu",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 rust_repository_set(
-    name = "rust_1_48_beta_darwin",
+    name = "rust_1_48_darwin",
     exec_triple = "x86_64-apple-darwin",
-    iso_date = "2020-11-08",
-    version = "beta",
+    version = "1.48.0",
 )
 
 vendor(
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 31cbb46..e10c2cc 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -25,7 +25,7 @@
 - [Reference: built-in bindings](bindings.md)
     - [String &mdash; rust::String](binding/string.md)
     - [&str &mdash; rust::Str](binding/str.md)
-    - [&&#91;T&#93; &mdash; rust::Slice\<const T\>](binding/slice.md)
+    - [&&#91;T&#93;, &mut &#91;T&#93; &mdash; rust::Slice\<T\>](binding/slice.md)
     - [CxxString &mdash; std::string](binding/cxxstring.md)
     - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
     - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index aacd56b..4da7d73 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -1,5 +1,8 @@
 {{#title rust::Slice<T> — Rust ♡ C++}}
-# rust::Slice\<T\>
+# rust::Slice\<const T\>,&ensp;rust::Slice\<T\>
+
+- Rust `&[T]` is written `rust::Slice<const T>` in C++
+- Rust `&mut [T]` is written `rust::Slice<T>` in C++
 
 ### Public API:
 
@@ -15,7 +18,10 @@ public:
   Slice(const Slice<T> &) noexcept;
   Slice(T *, size_t count) noexcept;
 
+  // if std::is_const<T> {
   Slice &operator=(const Slice<T> &) noexcept;
+  // }
+  Slice &operator=(Slice<T> &&) noexcept;
 
   T *data() const noexcept;
   size_t size() const noexcept;
@@ -27,11 +33,14 @@ public:
 
 ### Restrictions:
 
-Only &amp;\[u8\] i.e. rust::Slice\<const uint8\_t\> is currently implemented.
-Support for arbitrary &amp;\[T\] is coming.
+Only T=u8 i.e. rust::Slice\<const uint8\_t\> and rust::Slice\<uint8\_t\> are
+currently implemented. Support for arbitrary T is coming.
 
 Allowed as function argument or return value. Not supported in shared structs.
-&amp;mut \[T\] is not supported yet.
+
+Only rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are
+move-assignable.) You'll need to write std::move occasionally as a reminder that
+accidentally exposing overlapping &amp;mut \[T\] to Rust is UB.
 
 ## Example
 
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 2774754..7d7d6e8 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -20,7 +20,6 @@ public:
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
-  Str(std::string &&) = delete;
 
   Str &operator=(const Str &) noexcept;
 
diff --git a/book/src/bindings.md b/book/src/bindings.md
index f19dc5d..df6a8d7 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -12,6 +12,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;mut [u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -43,7 +44,6 @@ matter of designing a nice API for each in its non-native language.
 
 <table>
 <tr><th>name in Rust</th><th>name in C++</th></tr>
-<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td></tr>
 <tr><td>BTreeMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>HashMap&lt;K, V&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td>Arc&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..c24e3b5
--- /dev/null
+++ b/compile_flags.txt
@@ -0,0 +1 @@
+-std=c++11
diff --git a/demo/Cargo.toml b/demo/Cargo.toml
index dc94861..8328cde 100644
--- a/demo/Cargo.toml
+++ b/demo/Cargo.toml
@@ -2,11 +2,14 @@
 name = "demo"
 version = "0.0.0"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
+license = "MIT OR Apache-2.0"
+description = "Toy project from https://github.com/dtolnay/cxx"
+repository = "https://github.com/dtolnay/cxx"
 edition = "2018"
 publish = false
 
 [dependencies]
-cxx = { path = ".." }
+cxx = { version = "1.0", path = ".." }
 
 [build-dependencies]
-cxx-build = { path = "../gen/build" }
+cxx-build = { version = "1.0", path = "../gen/build" }
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 2d21aa1..194d53c 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.0"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b232919..1b0b488 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.0"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/src/target.rs b/gen/build/src/target.rs
index 58ada3a..4c9a9f3 100644
--- a/gen/build/src/target.rs
+++ b/gen/build/src/target.rs
@@ -1,4 +1,5 @@
 use std::env;
+use std::ffi::OsStr;
 use std::path::{Path, PathBuf};
 
 pub(crate) enum TargetDir {
@@ -24,7 +25,13 @@ pub(crate) fn find_target_dir(out_dir: &Path) -> TargetDir {
 
     let mut dir = out_dir.to_owned();
     loop {
-        if dir.join(".rustc_info.json").exists() || dir.join("CACHEDIR.TAG").exists() {
+        if dir.join(".rustc_info.json").exists()
+            || dir.join("CACHEDIR.TAG").exists()
+            || dir.file_name() == Some(OsStr::new("target"))
+                && dir
+                    .parent()
+                    .map_or(false, |parent| parent.join("Cargo.toml").exists())
+        {
             return TargetDir::Path(dir);
         }
         if dir.pop() {
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b38aa68..ed79053 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.0"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 250fa3f..4bf4f2b 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.0"
+version = "0.7.3"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 9c5f4fd..53facbf 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -149,7 +149,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.ptr_len {
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
-        writeln!(out, "  const void *ptr;");
+        writeln!(out, "  void *ptr;");
         writeln!(out, "  size_t len;");
         writeln!(out, "}};");
         out.end_block(Block::Namespace("repr"));
@@ -173,7 +173,10 @@ pub(super) fn write(out: &mut OutFile) {
         }
         if builtin.rust_str_repr {
             writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(out, "    return repr::PtrLen{{str.ptr, str.len}};");
+            writeln!(
+                out,
+                "    return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
+            );
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
@@ -189,18 +192,21 @@ pub(super) fn write(out: &mut OutFile) {
                 out,
                 "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
             );
-            writeln!(
-                out,
-                "    return {{static_cast<const T *>(repr.ptr), repr.len}};",
-            );
+            writeln!(out, "    return {{static_cast<T *>(repr.ptr), repr.len}};");
             writeln!(out, "  }}");
         }
         if builtin.rust_slice_repr {
+            include.type_traits = true;
             writeln!(
                 out,
                 "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
             );
-            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
+            writeln!(out, "    return repr::PtrLen{{");
+            writeln!(
+                out,
+                "        const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
+            );
+            writeln!(out, "        slice.len}};");
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f90a76f..2240ed9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -272,6 +272,12 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
 
 fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     out.set_namespace(&enm.name.namespace);
+    out.include.type_traits = true;
+    writeln!(
+        out,
+        "static_assert(::std::is_enum<{}>::value, \"expected enum\");",
+        enm.name.cxx,
+    );
     write!(out, "static_assert(sizeof({}) == sizeof(", enm.name.cxx);
     write_atom(out, enm.repr);
     writeln!(out, "), \"incorrect size\");");
@@ -433,9 +439,11 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.rust_str_repr = true;
             write!(out, "::rust::impl<::rust::Str>::repr(");
         }
-        Some(Type::SliceRefU8(_)) if !indirect_return => {
+        Some(ty @ Type::SliceRefU8(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
+            write!(out, "::rust::impl<");
+            write_type(out, ty);
+            write!(out, ">::repr(");
         }
         _ => {}
     }
@@ -471,12 +479,13 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if let Type::SliceRefU8(_) = arg.ty {
-            write!(
-                out,
-                "::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
-                arg.ident,
-            );
+        } else if let Type::SliceRefU8(slice) = &arg.ty {
+            write_type(out, &arg.ty);
+            write!(out, "(static_cast<");
+            if slice.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t *>({0}.ptr), {0}.len)", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -504,7 +513,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         writeln!(out, "        throw$.len = ::std::strlen(catch$);");
         writeln!(
             out,
-            "        throw$.ptr = ::cxxbridge1$exception(catch$, throw$.len);",
+            "        throw$.ptr = const_cast<char *>(::cxxbridge1$exception(catch$, throw$.len));",
         );
         writeln!(out, "      }});");
         writeln!(out, "  return throw$;");
@@ -691,7 +700,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::slice(");
+                write!(out, "::rust::impl<");
+                write_type(out, ret);
+                write!(out, ">::slice(");
             }
             _ => {}
         }
@@ -717,7 +728,9 @@ fn write_rust_function_shim_impl(
             }
             Type::SliceRefU8(_) => {
                 out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
+                write!(out, "::rust::impl<");
+                write_type(out, &arg.ty);
+                write!(out, ">::repr(");
             }
             ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
             _ => {}
@@ -887,8 +900,12 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRefU8(_) => {
-            write!(out, "::rust::Slice<const uint8_t>");
+        Type::SliceRefU8(ty) => {
+            write!(out, "::rust::Slice<");
+            if ty.mutability.is_none() {
+                write!(out, "const ");
+            }
+            write!(out, "uint8_t>");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 24a5292..1b30497 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -63,7 +63,6 @@ public:
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
-  Str(std::string &&) = delete;
 
   Str &operator=(const Str &) noexcept = default;
 
@@ -88,16 +87,28 @@ private:
 #endif // CXXBRIDGE1_RUST_STR
 
 #ifndef CXXBRIDGE1_RUST_SLICE
-template <typename T>
-class Slice final {
-  static_assert(std::is_const<T>::value,
-                "&[T] needs to be written as rust::Slice<const T> in C++");
+namespace detail {
+template <bool cond>
+struct copy_assignable_if {};
+
+template <>
+struct copy_assignable_if<false> {
+  copy_assignable_if() noexcept = default;
+  copy_assignable_if(const copy_assignable_if &) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+};
+} // namespace detail
 
+template <typename T>
+class Slice final
+    : private detail::copy_assignable_if<std::is_const<T>::value> {
 public:
   Slice() noexcept;
   Slice(T *, size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
+  Slice &operator=(Slice<T> &&) noexcept = default;
 
   T *data() const noexcept;
   size_t size() const noexcept;
@@ -251,7 +262,7 @@ class Error final : public std::exception {
 public:
   Error(const Error &);
   Error(Error &&) noexcept;
-  ~Error() noexcept;
+  ~Error() noexcept override;
 
   Error &operator=(const Error &);
   Error &operator=(Error &&) noexcept;
@@ -478,14 +489,13 @@ T *Box<T>::into_raw() noexcept {
 }
 
 template <typename T>
-Box<T>::Box() noexcept {}
+Box<T>::Box() noexcept = default;
 #endif // CXXBRIDGE1_RUST_BOX
 
 #ifndef CXXBRIDGE1_RUST_VEC
 #define CXXBRIDGE1_RUST_VEC
 template <typename T>
-Vec<T>::Vec(Vec &&other) noexcept {
-  this->repr = other.repr;
+Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }
 
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 61c8b14..3b86dc4 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.0"
+version = "1.0.3"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f29c4cc..1fee928 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -330,7 +330,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
-            Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
+                true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
         }
@@ -423,7 +426,10 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRefU8(_) => quote!(#call.as_slice()),
+                Type::SliceRefU8(ty) => match ty.mutable {
+                    false => quote!(#call.as_slice()),
+                    true => quote!(#call.as_mut_slice()),
+                },
                 _ => call,
             },
         };
@@ -610,7 +616,10 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRefU8(_) => quote!(#ident.as_slice()),
+            Type::SliceRefU8(ty) => match ty.mutable {
+                false => quote!(#ident.as_slice()),
+                true => quote!(#ident.as_mut_slice()),
+            },
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -654,7 +663,10 @@ fn expand_rust_function_shim_impl(
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
-        Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
+            true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
+        },
         _ => None,
     });
 
diff --git a/src/cxx.cc b/src/cxx.cc
index ecc3668..28506ef 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -67,8 +67,7 @@ String::String(const String &other) noexcept {
   cxxbridge1$string$clone(this, other);
 }
 
-String::String(String &&other) noexcept {
-  this->repr = other.repr;
+String::String(String &&other) noexcept : repr(other.repr) {
   cxxbridge1$string$new(&other);
 }
 
@@ -170,6 +169,28 @@ static_assert(std::is_trivially_copy_assignable<Str>::value,
               "trivial operator=(const Str &)");
 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
 
+static_assert(std::is_trivially_copy_constructible<Slice<const uint8_t>>::value,
+              "trivial Slice(const Slice &)");
+static_assert(std::is_trivially_move_constructible<Slice<const uint8_t>>::value,
+              "trivial Slice(Slice &&)");
+static_assert(std::is_trivially_copy_assignable<Slice<const uint8_t>>::value,
+              "trivial Slice::operator=(const Slice &) for const slices");
+static_assert(std::is_trivially_move_assignable<Slice<const uint8_t>>::value,
+              "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<const uint8_t>>::value,
+              "trivial ~Slice()");
+
+static_assert(std::is_trivially_copy_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(const Slice &)");
+static_assert(std::is_trivially_move_constructible<Slice<uint8_t>>::value,
+              "trivial Slice(Slice &&)");
+static_assert(!std::is_copy_assignable<Slice<uint8_t>>::value,
+              "delete Slice::operator=(const Slice &) for mut slices");
+static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
+              "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
+              "trivial ~Slice()");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];
@@ -240,10 +261,13 @@ void cxxbridge1$unique_ptr$std$string$drop(
 }
 } // extern "C"
 
+namespace {
+const size_t kMaxExpectedWordsInString = 8;
 static_assert(alignof(std::string) <= alignof(void *),
               "unexpectedly large std::string alignment");
-static_assert(sizeof(std::string) <= 8 * sizeof(void *),
+static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
               "unexpectedly large std::string size");
+} // namespace
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                             \
diff --git a/src/lib.rs b/src/lib.rs
index cf9212c..a057732 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -332,6 +332,7 @@
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
 //! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -361,7 +362,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.0")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.3")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
index 32f8798..e14f988 100644
--- a/src/rust_sliceu8.rs
+++ b/src/rust_sliceu8.rs
@@ -11,16 +11,27 @@ pub struct RustSliceU8 {
 }
 
 impl RustSliceU8 {
-    pub fn from(s: &[u8]) -> Self {
+    pub fn from_ref(s: &[u8]) -> Self {
         RustSliceU8 {
             ptr: NonNull::from(s).cast::<u8>(),
             len: s.len(),
         }
     }
 
+    pub fn from_mut(s: &mut [u8]) -> Self {
+        RustSliceU8 {
+            len: s.len(),
+            ptr: NonNull::from(s).cast::<u8>(),
+        }
+    }
+
     pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
         slice::from_raw_parts(self.ptr.as_ptr(), self.len)
     }
+
+    pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [u8] {
+        slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
+    }
 }
 
 const_assert_eq!(
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index c4d436e..3655a7a 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -6,7 +6,7 @@ use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem;
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
 use core::pin::Pin;
 use core::ptr;
 
@@ -68,6 +68,19 @@ where
         }
     }
 
+    /// Returns a mutable pinned reference to the object owned by this
+    /// UniquePtr.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the UniquePtr holds a null pointer.
+    pub fn pin_mut(&mut self) -> Pin<&mut T> {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called pin_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+
     /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T.
     ///
     /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release).
@@ -119,6 +132,18 @@ where
     }
 }
 
+impl<T> DerefMut for UniquePtr<T>
+where
+    T: UniquePtrTarget + Unpin,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => Pin::into_inner(target),
+            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+        }
+    }
+}
+
 impl<T> Debug for UniquePtr<T>
 where
     T: Debug + UniquePtrTarget,
diff --git a/syntax/check.rs b/syntax/check.rs
index 06e99fe..0c694c6 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -179,7 +179,10 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice(cx: &mut Check, ty: &Slice) {
-    cx.error(ty, "only &[u8] is supported so far, not other slice types");
+    cx.error(
+        ty,
+        "only &[u8] and &mut [u8] are supported so far, not other slice types",
+    );
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
@@ -237,9 +240,12 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
 fn check_api_enum(cx: &mut Check, enm: &Enum) {
     check_reserved_name(cx, &enm.name.rust);
 
-    if enm.variants.is_empty() {
+    if enm.variants.is_empty() && !enm.explicit_repr {
         let span = span_for_enum_error(enm);
-        cx.error(span, "enums without any variants are not supported");
+        cx.error(
+            span,
+            "explicit #[repr(...)] is required for enum without any variants",
+        );
     }
 }
 
@@ -411,6 +417,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
         || ident == "UniquePtr"
         || ident == "Vec"
         || ident == "CxxVector"
+        || ident == "str"
         || Atom::from(ident).is_some()
     {
         cx.error(ident, "reserved name");
@@ -418,12 +425,20 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
 }
 
 fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
-    let ident = match ty {
-        Type::Ident(ident) => &ident.rust,
-        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => return true,
-        _ => return false,
-    };
-    ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+    match ty {
+        Type::Ident(ident) => {
+            let ident = &ident.rust;
+            ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
+        }
+        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => true,
+        Type::RustBox(_)
+        | Type::RustVec(_)
+        | Type::UniquePtr(_)
+        | Type::Ref(_)
+        | Type::Str(_)
+        | Type::Fn(_)
+        | Type::SliceRefU8(_) => false,
+    }
 }
 
 fn is_opaque_cxx(cx: &mut Check, ty: &Ident) -> bool {
@@ -493,7 +508,10 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::Slice(_) => "slice".to_owned(),
-        Type::SliceRefU8(_) => "&[u8]".to_owned(),
+        Type::SliceRefU8(ty) => match ty.mutable {
+            false => "&[u8]".to_owned(),
+            true => "&mut [u8]".to_owned(),
+        },
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
         Type::Array(_) => "array".to_owned(),
diff --git a/syntax/discriminant.rs b/syntax/discriminant.rs
index 6a04d88..80f7c0b 100644
--- a/syntax/discriminant.rs
+++ b/syntax/discriminant.rs
@@ -16,10 +16,16 @@ pub struct DiscriminantSet {
 
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Discriminant {
-    negative: bool,
+    sign: Sign,
     magnitude: u64,
 }
 
+#[derive(Copy, Clone, Eq, PartialEq)]
+enum Sign {
+    Negative,
+    Positive,
+}
+
 impl DiscriminantSet {
     pub fn new(repr: Option<Atom>) -> Self {
         DiscriminantSet {
@@ -59,21 +65,23 @@ impl DiscriminantSet {
     pub fn insert_next(&mut self) -> Result<Discriminant> {
         let discriminant = match self.previous {
             None => Discriminant::zero(),
-            Some(mut discriminant) if discriminant.negative => {
-                discriminant.magnitude -= 1;
-                if discriminant.magnitude == 0 {
-                    discriminant.negative = false;
+            Some(mut discriminant) => match discriminant.sign {
+                Sign::Negative => {
+                    discriminant.magnitude -= 1;
+                    if discriminant.magnitude == 0 {
+                        discriminant.sign = Sign::Positive;
+                    }
+                    discriminant
                 }
-                discriminant
-            }
-            Some(mut discriminant) => {
-                if discriminant.magnitude == u64::MAX {
-                    let msg = format!("discriminant overflow on value after {}", u64::MAX);
-                    return Err(Error::new(Span::call_site(), msg));
+                Sign::Positive => {
+                    if discriminant.magnitude == u64::MAX {
+                        let msg = format!("discriminant overflow on value after {}", u64::MAX);
+                        return Err(Error::new(Span::call_site(), msg));
+                    }
+                    discriminant.magnitude += 1;
+                    discriminant
                 }
-                discriminant.magnitude += 1;
-                discriminant
-            }
+            },
         };
         insert(self, discriminant)
     }
@@ -109,7 +117,10 @@ fn expr_to_discriminant(expr: &Expr) -> Result<(Discriminant, Option<Atom>)> {
         Expr::Unary(unary) => {
             if let UnOp::Neg(_) = unary.op {
                 let (mut discriminant, repr) = expr_to_discriminant(&unary.expr)?;
-                discriminant.negative ^= true;
+                discriminant.sign = match discriminant.sign {
+                    Sign::Positive => Sign::Negative,
+                    Sign::Negative => Sign::Positive,
+                };
                 return Ok((discriminant, repr));
             }
         }
@@ -133,33 +144,33 @@ fn insert(set: &mut DiscriminantSet, discriminant: Discriminant) -> Result<Discr
             }
         }
     }
-    if set.values.insert(discriminant) {
-        set.previous = Some(discriminant);
-        Ok(discriminant)
-    } else {
-        let msg = format!("discriminant value `{}` already exists", discriminant);
-        Err(Error::new(Span::call_site(), msg))
-    }
+    set.values.insert(discriminant);
+    set.previous = Some(discriminant);
+    Ok(discriminant)
 }
 
 impl Discriminant {
     const fn zero() -> Self {
         Discriminant {
-            negative: false,
+            sign: Sign::Positive,
             magnitude: 0,
         }
     }
 
     const fn pos(u: u64) -> Self {
         Discriminant {
-            negative: false,
+            sign: Sign::Positive,
             magnitude: u,
         }
     }
 
     const fn neg(i: i64) -> Self {
         Discriminant {
-            negative: i < 0,
+            sign: if i < 0 {
+                Sign::Negative
+            } else {
+                Sign::Positive
+            },
             // This is `i.abs() as u64` but without overflow on MIN. Uses the
             // fact that MIN.wrapping_abs() wraps back to MIN whose binary
             // representation is 1<<63, and thus the `as u64` conversion
@@ -172,7 +183,7 @@ impl Discriminant {
 
 impl Display for Discriminant {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.negative {
+        if self.sign == Sign::Negative {
             f.write_str("-")?;
         }
         Display::fmt(&self.magnitude, f)
@@ -181,7 +192,7 @@ impl Display for Discriminant {
 
 impl ToTokens for Discriminant {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if self.negative {
+        if self.sign == Sign::Negative {
             Token![-](Span::call_site()).to_tokens(tokens);
         }
         Literal::u64_unsuffixed(self.magnitude).to_tokens(tokens);
@@ -192,15 +203,14 @@ impl FromStr for Discriminant {
     type Err = Error;
 
     fn from_str(mut s: &str) -> Result<Self> {
-        let negative = s.starts_with('-');
-        if negative {
+        let sign = if s.starts_with('-') {
             s = &s[1..];
-        }
+            Sign::Negative
+        } else {
+            Sign::Positive
+        };
         match s.parse::<u64>() {
-            Ok(magnitude) => Ok(Discriminant {
-                negative,
-                magnitude,
-            }),
+            Ok(magnitude) => Ok(Discriminant { sign, magnitude }),
             Err(_) => Err(Error::new(
                 Span::call_site(),
                 "discriminant value outside of supported range",
@@ -211,11 +221,12 @@ impl FromStr for Discriminant {
 
 impl Ord for Discriminant {
     fn cmp(&self, other: &Self) -> Ordering {
-        match (self.negative, other.negative) {
-            (true, true) => self.magnitude.cmp(&other.magnitude).reverse(),
-            (true, false) => Ordering::Less, // negative < positive
-            (false, true) => Ordering::Greater, // positive > negative
-            (false, false) => self.magnitude.cmp(&other.magnitude),
+        use self::Sign::{Negative, Positive};
+        match (self.sign, other.sign) {
+            (Negative, Negative) => self.magnitude.cmp(&other.magnitude).reverse(),
+            (Negative, Positive) => Ordering::Less, // negative < positive
+            (Positive, Negative) => Ordering::Greater, // positive > negative
+            (Positive, Positive) => self.magnitude.cmp(&other.magnitude),
         }
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4d65874..45a4aa5 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -91,6 +91,7 @@ pub struct Enum {
     pub variants: Vec<Variant>,
     pub repr: Atom,
     pub repr_type: Type,
+    pub explicit_repr: bool,
 }
 
 pub struct ExternFn {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0099299..80ecc71 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -170,6 +170,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
+    let explicit_repr = repr.is_some();
     let mut repr = U8;
     match discriminants.inferred_repr() {
         Ok(inferred) => repr = inferred,
@@ -191,6 +192,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         variants,
         repr,
         repr_type,
+        explicit_repr,
     }))
 }
 
@@ -234,10 +236,8 @@ fn parse_foreign_mod(
     for foreign in &foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
-                match parse_extern_type(cx, foreign, lang, trusted, &namespace) {
-                    Ok(ety) => items.push(ety),
-                    Err(err) => cx.push(err),
-                }
+                let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
+                items.push(ety);
             }
             ForeignItem::Fn(foreign) => {
                 match parse_extern_fn(cx, foreign, lang, trusted, &namespace) {
@@ -320,7 +320,7 @@ fn parse_extern_type(
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
-) -> Result<Api> {
+) -> Api {
     let mut doc = Doc::new();
     let mut namespace = namespace.clone();
     attrs::parse(
@@ -339,13 +339,13 @@ fn parse_extern_type(
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
     };
-    Ok(api_type(ExternType {
+    api_type(ExternType {
         doc,
         type_token,
         name: Pair::new(namespace, ident),
         semi_token,
         trusted,
-    }))
+    })
 }
 
 fn parse_extern_fn(
@@ -373,6 +373,24 @@ fn parse_extern_fn(
             "variadic function is not supported yet",
         ));
     }
+    if foreign_fn.sig.asyncness.is_some() {
+        return Err(Error::new_spanned(
+            foreign_fn,
+            "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
+        ));
+    }
+    if foreign_fn.sig.constness.is_some() {
+        return Err(Error::new_spanned(
+            foreign_fn,
+            "const extern function is not supported",
+        ));
+    }
+    if let Some(abi) = &foreign_fn.sig.abi {
+        return Err(Error::new_spanned(
+            abi,
+            "explicit ABI on extern function is not supported",
+        ));
+    }
 
     let mut doc = Doc::new();
     let mut cxx_name = None;
@@ -677,7 +695,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
             }
         }
         Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
+            Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
             _ => Type::Ref,
         },
         _ => Type::Ref,
diff --git a/syntax/types.rs b/syntax/types.rs
index 84b03be..6df3ca6 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -171,7 +171,10 @@ impl<'a> Types<'a> {
         let mut required_trivial = Map::new();
         let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
             if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust) {
+                if cxx.contains(&ident.rust)
+                    && !structs.contains_key(&ident.rust)
+                    && !enums.contains_key(&ident.rust)
+                {
                     required_trivial.entry(&ident.rust).or_insert(reason);
                 }
             }
diff --git a/tests/BUCK b/tests/BUCK
index 5bbe500..4bdcc46 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -12,7 +12,6 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
-        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -28,7 +27,6 @@ cxx_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":extra/source",
         ":module/source",
     ],
     headers = {
@@ -44,11 +42,6 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
-)
-
-rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
 )
diff --git a/tests/BUILD b/tests/BUILD
index 57ffab9..b255a3c 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -15,7 +15,6 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
-        "ffi/extra.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
@@ -30,7 +29,6 @@ cc_library(
     srcs = [
         "ffi/tests.cc",
         ":bridge/source",
-        ":extra/source",
         ":module/source",
     ],
     hdrs = ["ffi/tests.h"],
@@ -47,12 +45,6 @@ rust_cxx_bridge(
 )
 
 rust_cxx_bridge(
-    name = "extra",
-    src = "ffi/extra.rs",
-    deps = [":impl"],
-)
-
-rust_cxx_bridge(
     name = "module",
     src = "ffi/module.rs",
     deps = [":impl"],
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index 4b2cbdf..e583944 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -6,7 +6,7 @@ fn main() {
     }
 
     CFG.include_prefix = "tests/ffi";
-    let sources = vec!["lib.rs", "extra.rs", "module.rs"];
+    let sources = vec!["lib.rs", "module.rs"];
     cxx_build::bridges(sources)
         .file("tests.cc")
         .flag_if_supported(cxxbridge_flags::STD)
diff --git a/tests/ffi/extra.rs b/tests/ffi/extra.rs
deleted file mode 100644
index 8ca5e57..0000000
--- a/tests/ffi/extra.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Separate mod so that &self in the lib.rs mod has an unambiguous receiver. At
-// the moment, the cxx C++ codegen can't convert more than one cxx::bridge mod
-// per file, so that's why we need to put this outside of lib.rs. All of this
-// could go into module.rs instead, but for now its purpose is narrowly scoped
-// for testing aliasing between cxx::bridge mods, so we'll keep it that way and
-// start a new mod here.
-
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
-#[cxx::bridge(namespace = "tests")]
-pub mod ffi2 {
-    impl UniquePtr<D> {}
-    impl UniquePtr<E> {}
-    impl UniquePtr<F> {}
-    impl UniquePtr<G> {}
-
-    unsafe extern "C++" {
-        include!("tests/ffi/tests.h");
-
-        type D = crate::other::D;
-        type E = crate::other::E;
-        #[namespace = "F"]
-        type F = crate::other::f::F;
-        #[namespace = "G"]
-        type G = crate::other::G;
-
-        #[namespace = "H"]
-        type H;
-
-        fn c_take_trivial_ptr(d: UniquePtr<D>);
-        fn c_take_trivial_ref(d: &D);
-        fn c_take_trivial(d: D);
-        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
-        fn c_take_trivial_ns_ref(g: &G);
-        fn c_take_trivial_ns(g: G);
-        fn c_take_opaque_ptr(e: UniquePtr<E>);
-        fn c_take_opaque_ref(e: &E);
-        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
-        fn c_take_opaque_ns_ref(e: &F);
-        fn c_return_trivial_ptr() -> UniquePtr<D>;
-        fn c_return_trivial() -> D;
-        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
-        fn c_return_trivial_ns() -> G;
-        fn c_return_opaque_ptr() -> UniquePtr<E>;
-        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;  
-        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
-        fn c_take_ref_ns_c(h: &H);
-
-        #[namespace = "other"]
-        fn ns_c_take_trivial(d: D);
-        #[namespace = "other"]
-        fn ns_c_return_trivial() -> D;
-
-        #[namespace = "I"]
-        type I;
-
-        fn get(self: &I) -> u32;
-
-        #[namespace = "I"]
-        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
-    }
-}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index bfc1e43..2d7544a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -2,67 +2,15 @@
     clippy::boxed_local,
     clippy::just_underscores_and_digits,
     clippy::ptr_arg,
-    clippy::trivially_copy_pass_by_ref
+    clippy::trivially_copy_pass_by_ref,
+    clippy::unnecessary_wraps
 )]
 
-pub mod extra;
 pub mod module;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
 
-mod other {
-    use cxx::kind::{Opaque, Trivial};
-    use cxx::{type_id, CxxString, ExternType};
-
-    #[repr(C)]
-    pub struct D {
-        pub d: u64,
-    }
-
-    #[repr(C)]
-    pub struct E {
-        e: u64,
-        e_str: CxxString,
-    }
-
-    pub mod f {
-        use cxx::kind::Opaque;
-        use cxx::{type_id, CxxString, ExternType};
-
-        #[repr(C)]
-        pub struct F {
-            e: u64,
-            e_str: CxxString,
-        }
-
-        unsafe impl ExternType for F {
-            type Id = type_id!("F::F");
-            type Kind = Opaque;
-        }
-    }
-
-    #[repr(C)]
-    pub struct G {
-        pub g: u64,
-    }
-
-    unsafe impl ExternType for G {
-        type Id = type_id!("G::G");
-        type Kind = Trivial;
-    }
-
-    unsafe impl ExternType for D {
-        type Id = type_id!("tests::D");
-        type Kind = Trivial;
-    }
-
-    unsafe impl ExternType for E {
-        type Id = type_id!("tests::E");
-        type Kind = Opaque;
-    }
-}
-
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     #[derive(Clone)]
@@ -114,6 +62,7 @@ pub mod ffi {
     #[namespace = "second"]
     struct Second {
         i: i32,
+        e: COwnedEnum,
     }
 
     pub struct Array {
@@ -133,6 +82,7 @@ pub mod ffi {
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
         fn c_return_sliceu8(shared: &Shared) -> &[u8];
+        fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
@@ -196,6 +146,7 @@ pub mod ffi {
         fn c_try_return_ref(s: &String) -> Result<&String>;
         fn c_try_return_str(s: &str) -> Result<&str>;
         fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
         fn c_try_return_rust_string() -> Result<String>;
         fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
         fn c_try_return_rust_vec() -> Result<Vec<u8>>;
@@ -243,6 +194,8 @@ pub mod ffi {
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
+        fn r_return_sliceu8(shared: &Shared) -> &[u8];
+        fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn r_return_rust_string() -> String;
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
@@ -275,6 +228,8 @@ pub mod ffi {
         fn r_try_return_primitive() -> Result<usize>;
         fn r_try_return_box() -> Result<Box<R>>;
         fn r_fail_return_primitive() -> Result<usize>;
+        fn r_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
+        fn r_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
 
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
@@ -307,6 +262,58 @@ pub mod ffi {
     }
 }
 
+mod other {
+    use cxx::kind::{Opaque, Trivial};
+    use cxx::{type_id, CxxString, ExternType};
+
+    #[repr(C)]
+    pub struct D {
+        pub d: u64,
+    }
+
+    #[repr(C)]
+    pub struct E {
+        e: u64,
+        e_str: CxxString,
+    }
+
+    pub mod f {
+        use cxx::kind::Opaque;
+        use cxx::{type_id, CxxString, ExternType};
+
+        #[repr(C)]
+        pub struct F {
+            e: u64,
+            e_str: CxxString,
+        }
+
+        unsafe impl ExternType for F {
+            type Id = type_id!("F::F");
+            type Kind = Opaque;
+        }
+    }
+
+    #[repr(C)]
+    pub struct G {
+        pub g: u64,
+    }
+
+    unsafe impl ExternType for G {
+        type Id = type_id!("G::G");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for D {
+        type Id = type_id!("tests::D");
+        type Kind = Trivial;
+    }
+
+    unsafe impl ExternType for E {
+        type Id = type_id!("tests::E");
+        type Kind = Opaque;
+    }
+}
+
 #[derive(PartialEq, Debug)]
 pub struct R(pub usize);
 
@@ -376,6 +383,15 @@ fn r_return_str(shared: &ffi::Shared) -> &str {
     "2020"
 }
 
+fn r_return_sliceu8(shared: &ffi::Shared) -> &[u8] {
+    let _ = shared;
+    b"2020"
+}
+
+fn r_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8] {
+    slice
+}
+
 fn r_return_rust_string() -> String {
     "2020".to_owned()
 }
@@ -510,6 +526,14 @@ fn r_fail_return_primitive() -> Result<usize, Error> {
     Err(Error)
 }
 
+fn r_try_return_sliceu8(slice: &[u8]) -> Result<&[u8], Error> {
+    Ok(slice)
+}
+
+fn r_try_return_mutsliceu8(slice: &mut [u8]) -> Result<&mut [u8], Error> {
+    Ok(slice)
+}
+
 fn r_aliased_function(x: i32) -> String {
     x.to_string()
 }
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index aff1b1c..5846e11 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,6 +1,3 @@
-// Rustfmt mangles the extern type alias.
-// https://github.com/rust-lang/rustfmt/issues/4159
-#[rustfmt::skip]
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
     unsafe extern "C++" {
@@ -11,3 +8,57 @@ pub mod ffi {
         fn c_take_unique_ptr(c: UniquePtr<C>);
     }
 }
+
+#[cxx::bridge(namespace = "tests")]
+pub mod ffi2 {
+    unsafe extern "C++" {
+        include!("tests/ffi/tests.h");
+
+        type D = crate::other::D;
+        type E = crate::other::E;
+        #[namespace = "F"]
+        type F = crate::other::f::F;
+        #[namespace = "G"]
+        type G = crate::other::G;
+
+        #[namespace = "H"]
+        type H;
+
+        fn c_take_trivial_ptr(d: UniquePtr<D>);
+        fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial(d: D);
+        fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
+        fn c_take_trivial_ns_ref(g: &G);
+        fn c_take_trivial_ns(g: G);
+        fn c_take_opaque_ptr(e: UniquePtr<E>);
+        fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
+        fn c_take_opaque_ns_ref(e: &F);
+        fn c_return_trivial_ptr() -> UniquePtr<D>;
+        fn c_return_trivial() -> D;
+        fn c_return_trivial_ns_ptr() -> UniquePtr<G>;
+        fn c_return_trivial_ns() -> G;
+        fn c_return_opaque_ptr() -> UniquePtr<E>;
+        fn c_return_ns_opaque_ptr() -> UniquePtr<F>;
+        fn c_return_ns_unique_ptr() -> UniquePtr<H>;
+        fn c_take_ref_ns_c(h: &H);
+
+        #[namespace = "other"]
+        fn ns_c_take_trivial(d: D);
+        #[namespace = "other"]
+        fn ns_c_return_trivial() -> D;
+
+        #[namespace = "I"]
+        type I;
+
+        fn get(self: &I) -> u32;
+
+        #[namespace = "I"]
+        fn ns_c_return_unique_ptr_ns() -> UniquePtr<I>;
+    }
+
+    impl UniquePtr<D> {}
+    impl UniquePtr<E> {}
+    impl UniquePtr<F> {}
+    impl UniquePtr<G> {}
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index ef72047..46d8b16 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -81,6 +81,10 @@ rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
       reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
 }
 
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
+  return slice;
+}
+
 rust::String c_return_rust_string() { return "2020"; }
 
 std::unique_ptr<std::string> c_return_unique_ptr_string() {
@@ -439,6 +443,10 @@ rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t> s) {
   return s;
 }
 
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t> s) {
+  return s;
+}
+
 rust::String c_try_return_rust_string() { return c_return_rust_string(); }
 
 std::unique_ptr<std::string> c_try_return_unique_ptr_string() {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 5acf469..6c288d7 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -84,6 +84,7 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
 rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -148,6 +149,7 @@ rust::Box<R> c_try_return_box();
 const rust::String &c_try_return_ref(const rust::String &);
 rust::Str c_try_return_str(rust::Str);
 rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
+rust::Slice<uint8_t> c_try_return_mutsliceu8(rust::Slice<uint8_t>);
 rust::String c_try_return_rust_string();
 std::unique_ptr<std::string> c_try_return_unique_ptr_string();
 rust::Vec<uint8_t> c_try_return_rust_vec();
diff --git a/tests/test.rs b/tests/test.rs
index 141ebeb..3bd41d1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
-use cxx_test_suite::extra::ffi2;
+use cxx_test_suite::module::ffi2;
 use cxx_test_suite::{ffi, R};
 use std::cell::Cell;
 use std::ffi::CStr;
@@ -18,7 +18,11 @@ macro_rules! check {
     ($run:expr) => {{
         CORRECT.with(|correct| correct.set(false));
         $run;
-        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
+        assert!(
+            CORRECT.with(|correct| correct.get()),
+            "{}",
+            stringify!($run),
+        );
     }};
 }
 
@@ -188,14 +192,11 @@ fn test_c_method_calls() {
 
     let old_value = unique_ptr.get();
     assert_eq!(2020, old_value);
-    assert_eq!(2021, unique_ptr.as_mut().unwrap().set(2021));
+    assert_eq!(2021, unique_ptr.pin_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
-    assert_eq!(
-        2022,
-        unique_ptr.as_mut().unwrap().set_succeed(2022).unwrap(),
-    );
-    assert!(unique_ptr.as_mut().unwrap().get_fail().is_err());
+    assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap(),);
+    assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 
     let val = 42;
diff --git a/tests/ui/async_fn.rs b/tests/ui/async_fn.rs
new file mode 100644
index 0000000..69f2642
--- /dev/null
+++ b/tests/ui/async_fn.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        async fn f();
+    }
+}
+
+async fn f() {}
+
+fn main() {}
diff --git a/tests/ui/async_fn.stderr b/tests/ui/async_fn.stderr
new file mode 100644
index 0000000..dedec7b
--- /dev/null
+++ b/tests/ui/async_fn.stderr
@@ -0,0 +1,5 @@
+error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach
+ --> $DIR/async_fn.rs:4:9
+  |
+4 |         async fn f();
+  |         ^^^^^^^^^^^^^
diff --git a/tests/ui/const_fn.rs b/tests/ui/const_fn.rs
new file mode 100644
index 0000000..1ad4894
--- /dev/null
+++ b/tests/ui/const_fn.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        const fn f();
+    }
+}
+
+const fn f() {}
+
+fn main() {}
diff --git a/tests/ui/const_fn.stderr b/tests/ui/const_fn.stderr
new file mode 100644
index 0000000..a62ca83
--- /dev/null
+++ b/tests/ui/const_fn.stderr
@@ -0,0 +1,5 @@
+error: const extern function is not supported
+ --> $DIR/const_fn.rs:4:9
+  |
+4 |         const fn f();
+  |         ^^^^^^^^^^^^^
diff --git a/tests/ui/duplicate_enum_discriminants.rs b/tests/ui/duplicate_enum_discriminants.rs
deleted file mode 100644
index ec3d61a..0000000
--- a/tests/ui/duplicate_enum_discriminants.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    enum A {
-        V1 = 10,
-        V2 = 10,
-    }
-
-    enum B {
-        V1 = 10,
-        V2,
-        V3 = 11,
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/duplicate_enum_discriminants.stderr b/tests/ui/duplicate_enum_discriminants.stderr
deleted file mode 100644
index 14505e3..0000000
--- a/tests/ui/duplicate_enum_discriminants.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: discriminant value `10` already exists
- --> $DIR/duplicate_enum_discriminants.rs:5:9
-  |
-5 |         V2 = 10,
-  |         ^^^^^^^
-
-error: discriminant value `11` already exists
-  --> $DIR/duplicate_enum_discriminants.rs:11:9
-   |
-11 |         V3 = 11,
-   |         ^^^^^^^
diff --git a/tests/ui/empty_enum.stderr b/tests/ui/empty_enum.stderr
index 7f35019..0556da9 100644
--- a/tests/ui/empty_enum.stderr
+++ b/tests/ui/empty_enum.stderr
@@ -1,4 +1,4 @@
-error: enums without any variants are not supported
+error: explicit #[repr(...)] is required for enum without any variants
  --> $DIR/empty_enum.rs:3:5
   |
 3 |     enum A {}
diff --git a/tests/ui/extern_fn_abi.rs b/tests/ui/extern_fn_abi.rs
new file mode 100644
index 0000000..1f93338
--- /dev/null
+++ b/tests/ui/extern_fn_abi.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        extern "Java" fn f();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_fn_abi.stderr b/tests/ui/extern_fn_abi.stderr
new file mode 100644
index 0000000..3abf47a
--- /dev/null
+++ b/tests/ui/extern_fn_abi.stderr
@@ -0,0 +1,5 @@
+error: explicit ABI on extern function is not supported
+ --> $DIR/extern_fn_abi.rs:4:9
+  |
+4 |         extern "Java" fn f();
+  |         ^^^^^^^^^^^^^
diff --git a/tests/ui/unique_ptr_as_mut.rs b/tests/ui/unique_ptr_as_mut.rs
new file mode 100644
index 0000000..d2c758a
--- /dev/null
+++ b/tests/ui/unique_ptr_as_mut.rs
@@ -0,0 +1,23 @@
+use cxx::UniquePtr;
+
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        x: i32,
+    }
+
+    extern "C++" {
+        type Opaque;
+    }
+
+    impl UniquePtr<Shared> {}
+    impl UniquePtr<Opaque> {}
+}
+
+fn main() {
+    let mut shared = UniquePtr::<ffi::Shared>::null();
+    let _: &mut ffi::Shared = &mut shared;
+
+    let mut opaque = UniquePtr::<ffi::Opaque>::null();
+    let _: &mut ffi::Opaque = &mut opaque;
+}
diff --git a/tests/ui/unique_ptr_as_mut.stderr b/tests/ui/unique_ptr_as_mut.stderr
new file mode 100644
index 0000000..a41f716
--- /dev/null
+++ b/tests/ui/unique_ptr_as_mut.stderr
@@ -0,0 +1,7 @@
+error[E0596]: cannot borrow data in a dereference of `UniquePtr<ffi::Opaque>` as mutable
+  --> $DIR/unique_ptr_as_mut.rs:22:31
+   |
+22 |     let _: &mut ffi::Opaque = &mut opaque;
+   |                               ^^^^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<ffi::Opaque>`
diff --git a/third-party/BUCK b/third-party/BUCK
index a9a3913..6cc37e8 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.62/src/**"]),
+    srcs = glob(["vendor/cc-1.0.65/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.48/src/**"]),
+    srcs = glob(["vendor/syn-1.0.51/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
@@ -91,7 +91,7 @@ rust_library(
 
 rust_library(
     name = "termcolor",
-    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+    srcs = glob(["vendor/termcolor-1.1.2/src/**"]),
 )
 
 rust_library(
diff --git a/third-party/BUILD b/third-party/BUILD
index d72b083..ef9dba1 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -13,7 +13,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.62/src/**"]),
+    srcs = glob(["vendor/cc-1.0.65/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.48/src/**"]),
+    srcs = glob(["vendor/syn-1.0.51/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
@@ -97,7 +97,7 @@ rust_library(
 
 rust_library(
     name = "termcolor",
-    srcs = glob(["vendor/termcolor-1.1.0/src/**"]),
+    srcs = glob(["vendor/termcolor-1.1.2/src/**"]),
 )
 
 rust_library(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5f35669..b1d1aca 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.62"
+version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
+checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
 
 [[package]]
 name = "clap"
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.0"
+version = "1.0.3"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.0"
+version = "1.0.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.0"
+version = "0.7.3"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.0"
+version = "1.0.3"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.0"
+version = "1.0.3"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.0"
+version = "1.0.3"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.48"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
+checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -280,9 +280,9 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.1.0"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
 dependencies = [
  "winapi-util",
 ]

From 93f1c36647c60eeaaa4e4b92ab469fdd373b13c6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:16:25 +0000
Subject: [PATCH 1513/2232] Remove redundant array type recursive check calls


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0c694c6..630288a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -192,10 +192,7 @@ fn check_type_array(cx: &mut Check, ty: &Array) {
                 cx.error(ty, "Only shared structs are supported in array yet");
             }
         }
-        Type::RustBox(ty1) => check_type_box(cx, ty1),
-        Type::RustVec(ty1) => check_type_rust_vec(cx, ty1),
-        Type::CxxVector(ty1) => check_type_cxx_vector(cx, ty1),
-        Type::UniquePtr(ty1) => check_type_unique_ptr(cx, ty1),
+        Type::RustBox(_) | Type::RustVec(_) | Type::CxxVector(_) | Type::UniquePtr(_) => {}
         _ => cx.error(ty, "unsupported array target type"),
     };
 }

From 8f8d78dded8728cc0d74318a5d126b639cbf5576 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:16:25 +0000
Subject: [PATCH 1514/2232] Implement is_unsized for Array based on element sizedness


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 630288a..eaa10e9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -427,6 +427,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
             let ident = &ident.rust;
             ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
         }
+        Type::Array(array) => is_unsized(cx, &array.inner),
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => true,
         Type::RustBox(_)
         | Type::RustVec(_)

From 2cabd0a8a37b79f4ad4c9f7648e71921d3640e70 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:16:26 +0000
Subject: [PATCH 1515/2232] Set needs_indirect_abi for Array


Otherwise:

    warning: `extern` fn uses type `[u8; 3]`, which is not FFI-safe
     --> src/main.rs:8:21
      |
    8 |         fn arr() -> [u8; 3];
      |                     ^^^^^^^ not FFI-safe
      |
      = note: `#[warn(improper_ctypes_definitions)]` on by default
      = help: consider passing a pointer to the array
      = note: passing raw arrays by value is not FFI-safe

---

diff --git a/syntax/types.rs b/syntax/types.rs
index 6df3ca6..d59bce0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -254,7 +254,7 @@ impl<'a> Types<'a> {
                     Atom::from(&ident.rust) == Some(RustString)
                 }
             }
-            Type::RustVec(_) => true,
+            Type::RustVec(_) | Type::Array(_) => true,
             _ => false,
         }
     }

From e8b1bb4d126e68d48fdb3bd2df0be130f1bd1ece Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:06 +0000
Subject: [PATCH 1516/2232] Touch up pr 459


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2240ed9..227df19 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -172,9 +172,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
             }
-            Type::Array(_) => {
-                out.include.array = true;
-            }
+            Type::Array(_) => out.include.array = true,
             Type::Ref(_) | Type::Void(_) => {}
         }
     }
diff --git a/syntax/check.rs b/syntax/check.rs
index eaa10e9..a926d1c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,8 +2,8 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Types,
+    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    Slice, Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -194,7 +194,7 @@ fn check_type_array(cx: &mut Check, ty: &Array) {
         }
         Type::RustBox(_) | Type::RustVec(_) | Type::CxxVector(_) | Type::UniquePtr(_) => {}
         _ => cx.error(ty, "unsupported array target type"),
-    };
+    }
 }
 
 fn check_type_fn(cx: &mut Check, ty: &Signature) {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 6fae2f9..ef3ba8f 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -175,6 +175,7 @@ impl Hash for Slice {
 }
 
 impl Eq for Array {}
+
 impl PartialEq for Array {
     fn eq(&self, other: &Array) -> bool {
         let Array {
@@ -192,6 +193,7 @@ impl PartialEq for Array {
         inner == inner2 && len == len2
     }
 }
+
 impl Hash for Array {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Array {
@@ -201,7 +203,7 @@ impl Hash for Array {
             len,
         } = self;
         inner.hash(state);
-        len.to_string().hash(state);
+        len.hash(state);
     }
 }
 

From f22fb65fcfd7a08176c9d4a985838d81a0fdbe6d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:06 +0000
Subject: [PATCH 1517/2232] Add ui test of improper suffix on array len


---

diff --git a/tests/ui/array_len_suffix.rs b/tests/ui/array_len_suffix.rs
new file mode 100644
index 0000000..1e9d514
--- /dev/null
+++ b/tests/ui/array_len_suffix.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn array() -> [String; 12u16];
+    }
+}
+
+fn main() {}

From c351dc40cd4a6504a19c6d4c79293d3329ebbea1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:06 +0000
Subject: [PATCH 1518/2232] Preserve lit token of array length


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index ef3ba8f..f533093 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -183,12 +183,14 @@ impl PartialEq for Array {
             inner,
             semi_token: _,
             len,
+            len_token: _,
         } = self;
         let Array {
             bracket: _,
             inner: inner2,
             semi_token: _,
             len: len2,
+            len_token: _,
         } = other;
         inner == inner2 && len == len2
     }
@@ -201,6 +203,7 @@ impl Hash for Array {
             inner,
             semi_token: _,
             len,
+            len_token: _,
         } = self;
         inner.hash(state);
         len.hash(state);
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 45a4aa5..e61e384 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -30,7 +30,7 @@ use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Generics, Lifetime, Token, Type as RustType};
+use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -196,6 +196,7 @@ pub struct Array {
     pub inner: Type,
     pub semi_token: Token![;],
     pub len: usize,
+    pub len_token: LitInt,
 }
 
 #[derive(Copy, Clone, PartialEq)]
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 80ecc71..597ccfd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -657,8 +657,8 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
                 ));
             }
             match &lit.lit {
-                Lit::Int(v) => {
-                    let v = match v.base10_parse::<usize>() {
+                Lit::Int(len_token) => {
+                    let v = match len_token.base10_parse::<usize>() {
                         Ok(n_v) => n_v,
                         Err(_) => {
                             return Err(Error::new_spanned(
@@ -672,6 +672,7 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
                         inner,
                         semi_token: ty.semi_token,
                         len: v,
+                        len_token: len_token.clone(),
                     })))
                 }
                 _ => Err(Error::new_spanned(ty, "length literal must be a integer")),
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 27c2693..30a63d8 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -74,7 +74,7 @@ impl ToTokens for Array {
         self.bracket.surround(tokens, |tokens| {
             self.inner.to_tokens(tokens);
             self.semi_token.to_tokens(tokens);
-            self.len.to_tokens(tokens);
+            self.len_token.to_tokens(tokens);
         });
     }
 }
diff --git a/tests/ui/array_len_suffix.stderr b/tests/ui/array_len_suffix.stderr
new file mode 100644
index 0000000..b72fc02
--- /dev/null
+++ b/tests/ui/array_len_suffix.stderr
@@ -0,0 +1,10 @@
+error[E0308]: mismatched types
+ --> $DIR/array_len_suffix.rs:4:32
+  |
+4 |         fn array() -> [String; 12u16];
+  |                                ^^^^^ expected `usize`, found `u16`
+  |
+help: change the type of the numeric literal from `u16` to `usize`
+  |
+4 |         fn array() -> [String; 12usize];
+  |                                ^^^^^^^

From 2d0df23b44d7618e1c1a449292ee843840f3a175 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:06 +0000
Subject: [PATCH 1519/2232] Reorder array parsing near slice


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 597ccfd..581f43b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -639,52 +639,13 @@ fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
         RustType::Reference(ty) => parse_type_reference(ty, namespace),
         RustType::Path(ty) => parse_type_path(ty, namespace),
         RustType::Slice(ty) => parse_type_slice(ty, namespace),
+        RustType::Array(ty) => parse_type_array(ty, namespace),
         RustType::BareFn(ty) => parse_type_fn(ty, namespace),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
-        RustType::Array(ty) => parse_type_array(ty, namespace),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
-    match &ty.len {
-        Expr::Lit(lit) => {
-            if !lit.attrs.is_empty() {
-                return Err(Error::new_spanned(
-                    ty,
-                    "attribute not allowed in length field",
-                ));
-            }
-            match &lit.lit {
-                Lit::Int(len_token) => {
-                    let v = match len_token.base10_parse::<usize>() {
-                        Ok(n_v) => n_v,
-                        Err(_) => {
-                            return Err(Error::new_spanned(
-                                ty,
-                                "Cannot parse integer literal to base10",
-                            ))
-                        }
-                    };
-                    Ok(Type::Array(Box::new(Array {
-                        bracket: ty.bracket_token,
-                        inner,
-                        semi_token: ty.semi_token,
-                        len: v,
-                        len_token: len_token.clone(),
-                    })))
-                }
-                _ => Err(Error::new_spanned(ty, "length literal must be a integer")),
-            }
-        }
-        _ => Err(Error::new_spanned(
-            ty,
-            "only literal is currently supported in len field",
-        )),
-    }
-}
-
 fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
     let inner = parse_type(&ty.elem, namespace)?;
     let which = match &inner {
@@ -787,6 +748,45 @@ fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
     })))
 }
 
+fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, namespace)?;
+    match &ty.len {
+        Expr::Lit(lit) => {
+            if !lit.attrs.is_empty() {
+                return Err(Error::new_spanned(
+                    ty,
+                    "attribute not allowed in length field",
+                ));
+            }
+            match &lit.lit {
+                Lit::Int(len_token) => {
+                    let v = match len_token.base10_parse::<usize>() {
+                        Ok(n_v) => n_v,
+                        Err(_) => {
+                            return Err(Error::new_spanned(
+                                ty,
+                                "Cannot parse integer literal to base10",
+                            ))
+                        }
+                    };
+                    Ok(Type::Array(Box::new(Array {
+                        bracket: ty.bracket_token,
+                        inner,
+                        semi_token: ty.semi_token,
+                        len: v,
+                        len_token: len_token.clone(),
+                    })))
+                }
+                _ => Err(Error::new_spanned(ty, "length literal must be a integer")),
+            }
+        }
+        _ => Err(Error::new_spanned(
+            ty,
+            "only literal is currently supported in len field",
+        )),
+    }
+}
+
 fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(

From 5cb90652a3deb5e31f11c3c76e3f3e679c788d10 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:06 +0000
Subject: [PATCH 1520/2232] Improve array parse error messages


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 581f43b..8d2b703 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -752,22 +752,11 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
     let inner = parse_type(&ty.elem, namespace)?;
     match &ty.len {
         Expr::Lit(lit) => {
-            if !lit.attrs.is_empty() {
-                return Err(Error::new_spanned(
-                    ty,
-                    "attribute not allowed in length field",
-                ));
-            }
             match &lit.lit {
                 Lit::Int(len_token) => {
                     let v = match len_token.base10_parse::<usize>() {
                         Ok(n_v) => n_v,
-                        Err(_) => {
-                            return Err(Error::new_spanned(
-                                ty,
-                                "Cannot parse integer literal to base10",
-                            ))
-                        }
+                        Err(err) => return Err(Error::new_spanned(len_token, err)),
                     };
                     Ok(Type::Array(Box::new(Array {
                         bracket: ty.bracket_token,
@@ -777,12 +766,12 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
                         len_token: len_token.clone(),
                     })))
                 }
-                _ => Err(Error::new_spanned(ty, "length literal must be a integer")),
+                _ => Err(Error::new_spanned(lit, "array length must be an integer literal")),
             }
         }
         _ => Err(Error::new_spanned(
-            ty,
-            "only literal is currently supported in len field",
+            &ty.len,
+            "unsupported expression, array length must be an integer literal",
         )),
     }
 }

From d9f9784c930deee039f52ec9014f85c8d16c7ba0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:07 +0000
Subject: [PATCH 1521/2232] Reduce nesting of array parse


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8d2b703..2c8d982 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -750,30 +750,32 @@ fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
 
 fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
     let inner = parse_type(&ty.elem, namespace)?;
-    match &ty.len {
-        Expr::Lit(lit) => {
-            match &lit.lit {
-                Lit::Int(len_token) => {
-                    let v = match len_token.base10_parse::<usize>() {
-                        Ok(n_v) => n_v,
-                        Err(err) => return Err(Error::new_spanned(len_token, err)),
-                    };
-                    Ok(Type::Array(Box::new(Array {
-                        bracket: ty.bracket_token,
-                        inner,
-                        semi_token: ty.semi_token,
-                        len: v,
-                        len_token: len_token.clone(),
-                    })))
-                }
-                _ => Err(Error::new_spanned(lit, "array length must be an integer literal")),
-            }
-        }
-        _ => Err(Error::new_spanned(
-            &ty.len,
-            "unsupported expression, array length must be an integer literal",
-        )),
-    }
+
+    let len_expr = if let Expr::Lit(lit) = &ty.len {
+        lit
+    } else {
+        let msg = "unsupported expression, array length must be an integer literal";
+        return Err(Error::new_spanned(&ty.len, msg));
+    };
+
+    let len_token = if let Lit::Int(int) = &len_expr.lit {
+        int.clone()
+    } else {
+        let msg = "array length must be an integer literal";
+        return Err(Error::new_spanned(len_expr, msg));
+    };
+
+    let bracket = ty.bracket_token;
+    let semi_token = ty.semi_token;
+    let len = len_token.base10_parse::<usize>()?;
+
+    Ok(Type::Array(Box::new(Array {
+        bracket,
+        inner,
+        semi_token,
+        len,
+        len_token,
+    })))
 }
 
 fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {

From 9075bafa1dfe3417f1b9ce732618c11c2a2563da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:17:07 +0000
Subject: [PATCH 1522/2232] Add array len parse ui tests


---

diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
new file mode 100644
index 0000000..fdd9783
--- /dev/null
+++ b/tests/ui/array_len_expr.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn arraystr() -> [String; "13"];
+        fn arraysub() -> [String; 15 - 1];
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
new file mode 100644
index 0000000..cb94328
--- /dev/null
+++ b/tests/ui/array_len_expr.stderr
@@ -0,0 +1,11 @@
+error: array length must be an integer literal
+ --> $DIR/array_len_expr.rs:4:35
+  |
+4 |         fn arraystr() -> [String; "13"];
+  |                                   ^^^^
+
+error: unsupported expression, array length must be an integer literal
+ --> $DIR/array_len_expr.rs:5:35
+  |
+5 |         fn arraysub() -> [String; 15 - 1];
+  |                                   ^^^^^^

From c4658294548e8e85e99b4e3cf00709959f7d3fbd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:24:32 +0000
Subject: [PATCH 1523/2232] Fix array element supported condition


This disallows previously wrongly allowed array element types in PR 459
(such as [CxxString; N]) and allows previously disallowed but
unproblematic array element types (such as [&str; N]).

---

diff --git a/syntax/check.rs b/syntax/check.rs
index a926d1c..f077bd3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -186,14 +186,13 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
-    match &ty.inner {
-        Type::Ident(ident) => {
-            if cx.types.rust.contains(&ident.rust) || cx.types.cxx.contains(&ident.rust) {
-                cx.error(ty, "Only shared structs are supported in array yet");
-            }
-        }
-        Type::RustBox(_) | Type::RustVec(_) | Type::CxxVector(_) | Type::UniquePtr(_) => {}
-        _ => cx.error(ty, "unsupported array target type"),
+    let supported = match &ty.inner {
+        Type::Fn(_) => false,
+        element => !is_unsized(cx, element),
+    };
+
+    if !supported {
+        cx.error(ty, "unsupported array element type");
     }
 }
 

From 10926400450ad209c2c8b875fc422c12495d8099 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:35:43 +0000
Subject: [PATCH 1524/2232] Add array support to readme and website


---

diff --git a/README.md b/README.md
index e4ac67e..49bd43c 100644
--- a/README.md
+++ b/README.md
@@ -327,6 +327,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index df6a8d7..c2a525c 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -16,6 +16,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/src/lib.rs b/src/lib.rs
index a057732..9ee2c4f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -336,6 +336,7 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>

From 909b8fc7c21516c75e2b8ee9a9d9b994a25d4ff0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:44:01 +0000
Subject: [PATCH 1525/2232] Merge pull request #503 from dtolnay/array


Implement Rust [T; N] <-> std::array<T, N>
---

diff --git a/README.md b/README.md
index e4ac67e..49bd43c 100644
--- a/README.md
+++ b/README.md
@@ -327,6 +327,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index df6a8d7..c2a525c 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -16,6 +16,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8b512da..227df19 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -172,6 +172,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
             }
+            Type::Array(_) => out.include.array = true,
             Type::Ref(_) | Type::Void(_) => {}
         }
     }
@@ -919,6 +920,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             }
             write!(out, ")>");
         }
+        Type::Array(a) => {
+            write!(out, "::std::array<");
+            write_type(out, &a.inner);
+            write!(out, ", {}>", &a.len);
+        }
         Type::Void(_) => unreachable!(),
     }
 }
@@ -957,7 +963,8 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::CxxVector(_)
         | Type::RustVec(_)
         | Type::SliceRefU8(_)
-        | Type::Fn(_) => write!(out, " "),
+        | Type::Fn(_)
+        | Type::Array(_) => write!(out, " "),
         Type::Ref(_) => {}
         Type::Void(_) | Type::Slice(_) => unreachable!(),
     }
diff --git a/src/lib.rs b/src/lib.rs
index a057732..9ee2c4f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -336,6 +336,7 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/syntax/check.rs b/syntax/check.rs
index 1ec6178..f077bd3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,8 +2,8 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
-    error, ident, Api, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature, Slice,
-    Struct, Ty1, Type, Types,
+    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
+    Slice, Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -35,6 +35,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Slice(ty) => check_type_slice(cx, ty),
+            Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
         }
@@ -184,6 +185,17 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
     );
 }
 
+fn check_type_array(cx: &mut Check, ty: &Array) {
+    let supported = match &ty.inner {
+        Type::Fn(_) => false,
+        element => !is_unsized(cx, element),
+    };
+
+    if !supported {
+        cx.error(ty, "unsupported array element type");
+    }
+}
+
 fn check_type_fn(cx: &mut Check, ty: &Signature) {
     if ty.throws {
         cx.error(ty, "function pointer returning Result is not supported yet");
@@ -414,6 +426,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
             let ident = &ident.rust;
             ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
         }
+        Type::Array(array) => is_unsized(cx, &array.inner),
         Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => true,
         Type::RustBox(_)
         | Type::RustVec(_)
@@ -498,5 +511,6 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         },
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
+        Type::Array(_) => "array".to_owned(),
     }
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index a9c48c3..f533093 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{Array, ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
@@ -50,6 +50,7 @@ impl Hash for Type {
             Type::Fn(t) => t.hash(state),
             Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
+            Type::Array(t) => t.hash(state),
             Type::Void(_) => {}
         }
     }
@@ -173,6 +174,42 @@ impl Hash for Slice {
     }
 }
 
+impl Eq for Array {}
+
+impl PartialEq for Array {
+    fn eq(&self, other: &Array) -> bool {
+        let Array {
+            bracket: _,
+            inner,
+            semi_token: _,
+            len,
+            len_token: _,
+        } = self;
+        let Array {
+            bracket: _,
+            inner: inner2,
+            semi_token: _,
+            len: len2,
+            len_token: _,
+        } = other;
+        inner == inner2 && len == len2
+    }
+}
+
+impl Hash for Array {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Array {
+            bracket: _,
+            inner,
+            semi_token: _,
+            len,
+            len_token: _,
+        } = self;
+        inner.hash(state);
+        len.hash(state);
+    }
+}
+
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6fd3162..e016884 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -31,6 +31,7 @@ impl<'a> Types<'a> {
             | Type::SliceRefU8(_) => Definite(true),
             Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+            Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 475cec1..e61e384 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -30,7 +30,7 @@ use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Generics, Lifetime, Token, Type as RustType};
+use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::Derive;
@@ -166,6 +166,7 @@ pub enum Type {
     Void(Span),
     Slice(Box<Slice>),
     SliceRefU8(Box<Ref>),
+    Array(Box<Array>),
 }
 
 pub struct Ty1 {
@@ -190,6 +191,14 @@ pub struct Slice {
     pub inner: Type,
 }
 
+pub struct Array {
+    pub bracket: Bracket,
+    pub inner: Type,
+    pub semi_token: Token![;],
+    pub len: usize,
+    pub len_token: LitInt,
+}
+
 #[derive(Copy, Clone, PartialEq)]
 pub enum Lang {
     Cxx,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8ce767c..2c8d982 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,7 +3,7 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
+    attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
     Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
     Var, Variant,
 };
@@ -12,10 +12,10 @@ use quote::{format_ident, quote, quote_spanned};
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat,
-    PathArguments, Result, ReturnType, Token, Type as RustType, TypeBareFn, TypePath,
-    TypeReference, TypeSlice,
+    Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
+    Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
+    TypePath, TypeReference, TypeSlice,
 };
 
 pub mod kw {
@@ -639,6 +639,7 @@ fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
         RustType::Reference(ty) => parse_type_reference(ty, namespace),
         RustType::Path(ty) => parse_type_path(ty, namespace),
         RustType::Slice(ty) => parse_type_slice(ty, namespace),
+        RustType::Array(ty) => parse_type_array(ty, namespace),
         RustType::BareFn(ty) => parse_type_fn(ty, namespace),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
@@ -747,6 +748,36 @@ fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
     })))
 }
 
+fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
+    let inner = parse_type(&ty.elem, namespace)?;
+
+    let len_expr = if let Expr::Lit(lit) = &ty.len {
+        lit
+    } else {
+        let msg = "unsupported expression, array length must be an integer literal";
+        return Err(Error::new_spanned(&ty.len, msg));
+    };
+
+    let len_token = if let Lit::Int(int) = &len_expr.lit {
+        int.clone()
+    } else {
+        let msg = "array length must be an integer literal";
+        return Err(Error::new_spanned(len_expr, msg));
+    };
+
+    let bracket = ty.bracket_token;
+    let semi_token = ty.semi_token;
+    let len = len_token.base10_parse::<usize>()?;
+
+    Ok(Type::Array(Box::new(Array {
+        bracket,
+        inner,
+        semi_token,
+        len,
+        len_token,
+    })))
+}
+
 fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 40ab723..30a63d8 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
-    Slice, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
+    Signature, Slice, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -22,6 +22,7 @@ impl ToTokens for Type {
             }
             Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
             Type::Slice(s) => s.to_tokens(tokens),
+            Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
         }
@@ -68,6 +69,16 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Array {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.bracket.surround(tokens, |tokens| {
+            self.inner.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+            self.len_token.to_tokens(tokens);
+        });
+    }
+}
+
 impl ToTokens for Slice {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.bracket.surround(tokens, |tokens| {
diff --git a/syntax/types.rs b/syntax/types.rs
index f57b61b..d59bce0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -49,6 +49,7 @@ impl<'a> Types<'a> {
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Slice(s) => visit(all, &s.inner),
+                Type::Array(a) => visit(all, &a.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
@@ -253,7 +254,7 @@ impl<'a> Types<'a> {
                     Atom::from(&ident.rust) == Some(RustString)
                 }
             }
-            Type::RustVec(_) => true,
+            Type::RustVec(_) | Type::Array(_) => true,
             _ => false,
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index aa9d3b4..2d7544a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -65,6 +65,10 @@ pub mod ffi {
         e: COwnedEnum,
     }
 
+    pub struct Array {
+        a: [i32; 4],
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
@@ -155,6 +159,7 @@ pub mod ffi {
         fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
         fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
+        fn c_set_array(self: &mut Array, value: i32);
 
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
@@ -229,6 +234,7 @@ pub mod ffi {
         fn get(self: &R) -> usize;
         fn set(self: &mut R, n: usize) -> usize;
         fn r_method_on_shared(self: &Shared) -> String;
+        fn r_get_array_sum(self: &Array) -> i32;
 
         #[cxx_name = "rAliasedFunction"]
         fn r_aliased_function(x: i32) -> String;
@@ -328,6 +334,12 @@ impl ffi::Shared {
     }
 }
 
+impl ffi::Array {
+    pub fn r_get_array_sum(&self) -> i32 {
+        self.a.iter().sum()
+    }
+}
+
 #[derive(Debug)]
 struct Error;
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 238b145..46d8b16 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -32,6 +32,10 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 size_t Shared::c_method_on_shared() const noexcept { return 2021; }
 
+void Array::c_set_array(int32_t val) noexcept {
+  this->a = {val, val, val, val};
+}
+
 const std::vector<uint8_t> &C::get_v() const { return this->v; }
 
 std::vector<uint8_t> &C::get_v() { return this->v; }
diff --git a/tests/test.rs b/tests/test.rs
index 24fa97f..3bd41d1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -198,6 +198,11 @@ fn test_c_method_calls() {
     assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap(),);
     assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
+
+    let val = 42;
+    let mut array = ffi::Array { a: [0, 0, 0, 0] };
+    array.c_set_array(val);
+    assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum());
 }
 
 #[test]
diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
new file mode 100644
index 0000000..fdd9783
--- /dev/null
+++ b/tests/ui/array_len_expr.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn arraystr() -> [String; "13"];
+        fn arraysub() -> [String; 15 - 1];
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
new file mode 100644
index 0000000..cb94328
--- /dev/null
+++ b/tests/ui/array_len_expr.stderr
@@ -0,0 +1,11 @@
+error: array length must be an integer literal
+ --> $DIR/array_len_expr.rs:4:35
+  |
+4 |         fn arraystr() -> [String; "13"];
+  |                                   ^^^^
+
+error: unsupported expression, array length must be an integer literal
+ --> $DIR/array_len_expr.rs:5:35
+  |
+5 |         fn arraysub() -> [String; 15 - 1];
+  |                                   ^^^^^^
diff --git a/tests/ui/array_len_suffix.rs b/tests/ui/array_len_suffix.rs
new file mode 100644
index 0000000..1e9d514
--- /dev/null
+++ b/tests/ui/array_len_suffix.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn array() -> [String; 12u16];
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/array_len_suffix.stderr b/tests/ui/array_len_suffix.stderr
new file mode 100644
index 0000000..b72fc02
--- /dev/null
+++ b/tests/ui/array_len_suffix.stderr
@@ -0,0 +1,10 @@
+error[E0308]: mismatched types
+ --> $DIR/array_len_suffix.rs:4:32
+  |
+4 |         fn array() -> [String; 12u16];
+  |                                ^^^^^ expected `usize`, found `u16`
+  |
+help: change the type of the numeric literal from `u16` to `usize`
+  |
+4 |         fn array() -> [String; 12usize];
+  |                                ^^^^^^^

From 313cc0ac61a36856a55fbc80c8900fc29ff165da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 05:47:01 +0000
Subject: [PATCH 1526/2232] Remove redundant namespaces passed around by parser


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2c8d982..15ee4f2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -43,7 +43,7 @@ pub fn parse_items(
             Item::ForeignMod(foreign_mod) => {
                 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
             }
-            Item::Impl(item) => match parse_impl(item, namespace) {
+            Item::Impl(item) => match parse_impl(item) {
                 Ok(imp) => apis.push(imp),
                 Err(err) => cx.push(err),
             },
@@ -95,7 +95,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         .map(|field| {
             Ok(Var {
                 ident: field.ident.unwrap(),
-                ty: parse_type(&field.ty, &namespace)?,
+                ty: parse_type(&field.ty)?,
             })
         })
         .collect::<Result<_>>()?;
@@ -438,7 +438,7 @@ fn parse_extern_fn(
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
-                let ty = parse_type(&arg.ty, &namespace)?;
+                let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     args.push_value(Var { ident, ty });
                     if let Some(comma) = comma {
@@ -468,7 +468,7 @@ fn parse_extern_fn(
     }
 
     let mut throws_tokens = None;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &namespace)?;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
@@ -559,7 +559,7 @@ fn parse_extern_verbatim(
     }
 }
 
-fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
+fn parse_impl(imp: ItemImpl) -> Result<Api> {
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -585,7 +585,7 @@ fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
 
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
-        ty: parse_type(&self_ty, namespace)?,
+        ty: parse_type(&self_ty)?,
         brace_token: imp.brace_token,
     }))
 }
@@ -634,20 +634,20 @@ fn parse_include(input: ParseStream) -> Result<Include> {
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
 }
 
-fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
+fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => parse_type_reference(ty, namespace),
-        RustType::Path(ty) => parse_type_path(ty, namespace),
-        RustType::Slice(ty) => parse_type_slice(ty, namespace),
-        RustType::Array(ty) => parse_type_array(ty, namespace),
-        RustType::BareFn(ty) => parse_type_fn(ty, namespace),
+        RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Path(ty) => parse_type_path(ty),
+        RustType::Slice(ty) => parse_type_slice(ty),
+        RustType::Array(ty) => parse_type_array(ty),
+        RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
     let which = match &inner {
         Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
@@ -673,7 +673,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
     })))
 }
 
-fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
+fn parse_type_path(ty: &TypePath) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
@@ -683,7 +683,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -693,7 +693,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -703,7 +703,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -713,7 +713,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -723,7 +723,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Pin" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         let pin_token = kw::Pin(ident.span());
                         if let Type::Ref(mut inner) = inner {
                             inner.pinned = true;
@@ -740,16 +740,16 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
     Ok(Type::Slice(Box::new(Slice {
         bracket: ty.bracket_token,
         inner,
     })))
 }
 
-fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_array(ty: &TypeArray) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
 
     let len_expr = if let Expr::Lit(lit) = &ty.len {
         lit
@@ -778,7 +778,7 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
     })))
 }
 
-fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
+fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
             ty,
@@ -796,7 +796,7 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
         .iter()
         .enumerate()
         .map(|(i, arg)| {
-            let ty = parse_type(&arg.ty, namespace)?;
+            let ty = parse_type(&arg.ty)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("_{}", i),
@@ -805,7 +805,7 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
         })
         .collect::<Result<_>>()?;
     let mut throws_tokens = None;
-    let ret = parse_return_type(&ty.output, &mut throws_tokens, namespace)?;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
@@ -823,7 +823,6 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
 fn parse_return_type(
     ty: &ReturnType,
     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
-    namespace: &Namespace,
 ) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
@@ -845,7 +844,7 @@ fn parse_return_type(
             }
         }
     }
-    match parse_type(ret, namespace)? {
+    match parse_type(ret)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),
     }

From 4f52dabfa351f8bf51bd5750f350753b6dc3e67e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 06:05:45 +0000
Subject: [PATCH 1527/2232] Merge pull request #504 from dtolnay/parsens


Remove redundant namespaces passed around by parser
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2c8d982..15ee4f2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -43,7 +43,7 @@ pub fn parse_items(
             Item::ForeignMod(foreign_mod) => {
                 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
             }
-            Item::Impl(item) => match parse_impl(item, namespace) {
+            Item::Impl(item) => match parse_impl(item) {
                 Ok(imp) => apis.push(imp),
                 Err(err) => cx.push(err),
             },
@@ -95,7 +95,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         .map(|field| {
             Ok(Var {
                 ident: field.ident.unwrap(),
-                ty: parse_type(&field.ty, &namespace)?,
+                ty: parse_type(&field.ty)?,
             })
         })
         .collect::<Result<_>>()?;
@@ -438,7 +438,7 @@ fn parse_extern_fn(
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
-                let ty = parse_type(&arg.ty, &namespace)?;
+                let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     args.push_value(Var { ident, ty });
                     if let Some(comma) = comma {
@@ -468,7 +468,7 @@ fn parse_extern_fn(
     }
 
     let mut throws_tokens = None;
-    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens, &namespace)?;
+    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
@@ -559,7 +559,7 @@ fn parse_extern_verbatim(
     }
 }
 
-fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
+fn parse_impl(imp: ItemImpl) -> Result<Api> {
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -585,7 +585,7 @@ fn parse_impl(imp: ItemImpl, namespace: &Namespace) -> Result<Api> {
 
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
-        ty: parse_type(&self_ty, namespace)?,
+        ty: parse_type(&self_ty)?,
         brace_token: imp.brace_token,
     }))
 }
@@ -634,20 +634,20 @@ fn parse_include(input: ParseStream) -> Result<Include> {
     Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
 }
 
-fn parse_type(ty: &RustType, namespace: &Namespace) -> Result<Type> {
+fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
-        RustType::Reference(ty) => parse_type_reference(ty, namespace),
-        RustType::Path(ty) => parse_type_path(ty, namespace),
-        RustType::Slice(ty) => parse_type_slice(ty, namespace),
-        RustType::Array(ty) => parse_type_array(ty, namespace),
-        RustType::BareFn(ty) => parse_type_fn(ty, namespace),
+        RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Path(ty) => parse_type_path(ty),
+        RustType::Slice(ty) => parse_type_slice(ty),
+        RustType::Array(ty) => parse_type_array(ty),
+        RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
         _ => Err(Error::new_spanned(ty, "unsupported type")),
     }
 }
 
-fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
     let which = match &inner {
         Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
@@ -673,7 +673,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
     })))
 }
 
-fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
+fn parse_type_path(ty: &TypePath) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
         let segment = &path.segments[0];
@@ -683,7 +683,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::UniquePtr(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -693,7 +693,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::CxxVector(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -703,7 +703,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Box" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::RustBox(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -713,7 +713,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Vec" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         return Ok(Type::RustVec(Box::new(Ty1 {
                             name: ident,
                             langle: generic.lt_token,
@@ -723,7 +723,7 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
                     }
                 } else if ident == "Pin" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
-                        let inner = parse_type(arg, namespace)?;
+                        let inner = parse_type(arg)?;
                         let pin_token = kw::Pin(ident.span());
                         if let Type::Ref(mut inner) = inner {
                             inner.pinned = true;
@@ -740,16 +740,16 @@ fn parse_type_path(ty: &TypePath, namespace: &Namespace) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
     Ok(Type::Slice(Box::new(Slice {
         bracket: ty.bracket_token,
         inner,
     })))
 }
 
-fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
-    let inner = parse_type(&ty.elem, namespace)?;
+fn parse_type_array(ty: &TypeArray) -> Result<Type> {
+    let inner = parse_type(&ty.elem)?;
 
     let len_expr = if let Expr::Lit(lit) = &ty.len {
         lit
@@ -778,7 +778,7 @@ fn parse_type_array(ty: &TypeArray, namespace: &Namespace) -> Result<Type> {
     })))
 }
 
-fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
+fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
     if ty.lifetimes.is_some() {
         return Err(Error::new_spanned(
             ty,
@@ -796,7 +796,7 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
         .iter()
         .enumerate()
         .map(|(i, arg)| {
-            let ty = parse_type(&arg.ty, namespace)?;
+            let ty = parse_type(&arg.ty)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("_{}", i),
@@ -805,7 +805,7 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
         })
         .collect::<Result<_>>()?;
     let mut throws_tokens = None;
-    let ret = parse_return_type(&ty.output, &mut throws_tokens, namespace)?;
+    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     Ok(Type::Fn(Box::new(Signature {
         unsafety: ty.unsafety,
@@ -823,7 +823,6 @@ fn parse_type_fn(ty: &TypeBareFn, namespace: &Namespace) -> Result<Type> {
 fn parse_return_type(
     ty: &ReturnType,
     throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
-    namespace: &Namespace,
 ) -> Result<Option<Type>> {
     let mut ret = match ty {
         ReturnType::Default => return Ok(None),
@@ -845,7 +844,7 @@ fn parse_return_type(
             }
         }
     }
-    match parse_type(ret, namespace)? {
+    match parse_type(ret)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),
     }

From 15609ab97b59377bd6c98b6cad05c6af21465c27 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 15:14:12 +0000
Subject: [PATCH 1528/2232] Enable UniquePtr::new for enums


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 227df19..1b3f893 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1212,6 +1212,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
         // for Opaque types because the 'new' method is not implemented.
         Type::Ident(ident) => {
             out.types.structs.contains_key(&ident.rust)
+                || out.types.enums.contains_key(&ident.rust)
                 || out.types.aliases.contains_key(&ident.rust)
         }
         _ => false,
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1fee928..9bfdecb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -909,22 +909,24 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let new_method =
-        if types.structs.contains_key(&ident.rust) || types.aliases.contains_key(&ident.rust) {
-            Some(quote! {
-                fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
-                    extern "C" {
-                        #[link_name = #link_new]
-                        fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
-                    }
-                    let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                    unsafe { __new(&mut repr, &mut value) }
-                    repr
+    let can_construct_from_value = types.structs.contains_key(&ident.rust)
+        || types.enums.contains_key(&ident.rust)
+        || types.aliases.contains_key(&ident.rust);
+    let new_method = if can_construct_from_value {
+        Some(quote! {
+            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+                extern "C" {
+                    #[link_name = #link_new]
+                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
                 }
-            })
-        } else {
-            None
-        };
+                let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
+                unsafe { __new(&mut repr, &mut value) }
+                repr
+            }
+        })
+    } else {
+        None
+    };
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);

From 1bdb4713993a79df7e9ebc4b09684faa052f455f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 15:39:58 +0000
Subject: [PATCH 1529/2232] Better represent legal UniquePtr referent types


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1b3f893..e33197c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -970,23 +970,49 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_typename(ty: &Type, types: &Types) -> String {
-    match ty {
-        Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
-        _ => unreachable!(),
+#[derive(Copy, Clone)]
+enum UniquePtr<'a> {
+    Ident(&'a ResolvableName),
+    CxxVector(&'a ResolvableName),
+}
+
+trait ToTypename {
+    fn to_typename(&self, types: &Types) -> String;
+}
+
+impl ToTypename for ResolvableName {
+    fn to_typename(&self, types: &Types) -> String {
+        types.resolve(self).to_fully_qualified()
     }
 }
 
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_mangled(ty: &Type, types: &Types) -> Symbol {
-    match ty {
-        Type::Ident(ident) => ident.to_symbol(types),
-        Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
-        _ => unreachable!(),
+impl<'a> ToTypename for UniquePtr<'a> {
+    fn to_typename(&self, types: &Types) -> String {
+        match self {
+            UniquePtr::Ident(ident) => ident.to_typename(types),
+            UniquePtr::CxxVector(element) => {
+                format!("::std::vector<{}>", element.to_typename(types))
+            }
+        }
+    }
+}
+
+trait ToMangled {
+    fn to_mangled(&self, types: &Types) -> Symbol;
+}
+
+impl ToMangled for ResolvableName {
+    fn to_mangled(&self, types: &Types) -> Symbol {
+        self.to_symbol(types)
+    }
+}
+
+impl<'a> ToMangled for UniquePtr<'a> {
+    fn to_mangled(&self, types: &Types) -> Symbol {
+        match self {
+            UniquePtr::Ident(ident) => ident.to_mangled(types),
+            UniquePtr::CxxVector(element) => element.to_mangled(types).prefix_with("std$vector$"),
+        }
     }
 }
 
@@ -1028,7 +1054,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
                         || out.types.explicit_impls.contains(ty))
                 {
                     out.next_section();
-                    write_cxx_vector(out, ty, inner);
+                    write_cxx_vector(out, inner);
                 }
             }
         }
@@ -1074,9 +1100,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
@@ -1134,9 +1159,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
 }
 
 fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
@@ -1187,35 +1211,35 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
-    let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&ty, out.types);
+    let ty = UniquePtr::Ident(ident);
+    let instance = ty.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 
-    write_unique_ptr_common(out, &ty);
+    write_unique_ptr_common(out, ty);
 
     writeln!(out, "#endif // CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
-fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
+fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     out.include.new = true;
     out.include.utility = true;
-    let inner = to_typename(ty, out.types);
-    let instance = to_mangled(ty, out.types);
+    let inner = ty.to_typename(out.types);
+    let instance = ty.to_mangled(out.types);
 
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types. We can't
         // know at code generation time, so we generate both C++ and Rust side
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
-        Type::Ident(ident) => {
+        UniquePtr::Ident(ident) => {
             out.types.structs.contains_key(&ident.rust)
                 || out.types.enums.contains_key(&ident.rust)
                 || out.types.aliases.contains_key(&ident.rust)
         }
-        _ => false,
+        UniquePtr::CxxVector(_) => false,
     };
 
     writeln!(
@@ -1278,10 +1302,9 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
@@ -1300,7 +1323,7 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableNam
     writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
-    write_unique_ptr_common(out, vector_ty);
+    write_unique_ptr_common(out, UniquePtr::CxxVector(element));
 
     writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
 }

From 5fcfcb48ad144f6c423fdc5958b3aeb22646dd88 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 15:46:47 +0000
Subject: [PATCH 1530/2232] Merge pull request #506 from dtolnay/typenames


Better represent legal UniquePtr referent types
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1b3f893..e33197c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -970,23 +970,49 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_typename(ty: &Type, types: &Types) -> String {
-    match ty {
-        Type::Ident(ident) => types.resolve(&ident).to_fully_qualified(),
-        Type::CxxVector(ptr) => format!("::std::vector<{}>", to_typename(&ptr.inner, types)),
-        _ => unreachable!(),
+#[derive(Copy, Clone)]
+enum UniquePtr<'a> {
+    Ident(&'a ResolvableName),
+    CxxVector(&'a ResolvableName),
+}
+
+trait ToTypename {
+    fn to_typename(&self, types: &Types) -> String;
+}
+
+impl ToTypename for ResolvableName {
+    fn to_typename(&self, types: &Types) -> String {
+        types.resolve(self).to_fully_qualified()
     }
 }
 
-// Only called for legal referent types of unique_ptr and element types of
-// std::vector and Vec.
-fn to_mangled(ty: &Type, types: &Types) -> Symbol {
-    match ty {
-        Type::Ident(ident) => ident.to_symbol(types),
-        Type::CxxVector(ptr) => to_mangled(&ptr.inner, types).prefix_with("std$vector$"),
-        _ => unreachable!(),
+impl<'a> ToTypename for UniquePtr<'a> {
+    fn to_typename(&self, types: &Types) -> String {
+        match self {
+            UniquePtr::Ident(ident) => ident.to_typename(types),
+            UniquePtr::CxxVector(element) => {
+                format!("::std::vector<{}>", element.to_typename(types))
+            }
+        }
+    }
+}
+
+trait ToMangled {
+    fn to_mangled(&self, types: &Types) -> Symbol;
+}
+
+impl ToMangled for ResolvableName {
+    fn to_mangled(&self, types: &Types) -> Symbol {
+        self.to_symbol(types)
+    }
+}
+
+impl<'a> ToMangled for UniquePtr<'a> {
+    fn to_mangled(&self, types: &Types) -> Symbol {
+        match self {
+            UniquePtr::Ident(ident) => ident.to_mangled(types),
+            UniquePtr::CxxVector(element) => element.to_mangled(types).prefix_with("std$vector$"),
+        }
     }
 }
 
@@ -1028,7 +1054,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
                         || out.types.explicit_impls.contains(ty))
                 {
                     out.next_section();
-                    write_cxx_vector(out, ty, inner);
+                    write_cxx_vector(out, inner);
                 }
             }
         }
@@ -1074,9 +1100,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
@@ -1134,9 +1159,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
 }
 
 fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
@@ -1187,35 +1211,35 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
-    let ty = Type::Ident(ident.clone());
-    let instance = to_mangled(&ty, out.types);
+    let ty = UniquePtr::Ident(ident);
+    let instance = ty.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_UNIQUE_PTR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 
-    write_unique_ptr_common(out, &ty);
+    write_unique_ptr_common(out, ty);
 
     writeln!(out, "#endif // CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
-fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
+fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     out.include.new = true;
     out.include.utility = true;
-    let inner = to_typename(ty, out.types);
-    let instance = to_mangled(ty, out.types);
+    let inner = ty.to_typename(out.types);
+    let instance = ty.to_mangled(out.types);
 
     let can_construct_from_value = match ty {
         // Some aliases are to opaque types; some are to trivial types. We can't
         // know at code generation time, so we generate both C++ and Rust side
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
-        Type::Ident(ident) => {
+        UniquePtr::Ident(ident) => {
             out.types.structs.contains_key(&ident.rust)
                 || out.types.enums.contains_key(&ident.rust)
                 || out.types.aliases.contains_key(&ident.rust)
         }
-        _ => false,
+        UniquePtr::CxxVector(_) => false,
     };
 
     writeln!(
@@ -1278,10 +1302,9 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableName) {
-    let element = Type::Ident(element.clone());
-    let inner = to_typename(&element, out.types);
-    let instance = to_mangled(&element, out.types);
+fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
+    let inner = element.to_typename(out.types);
+    let instance = element.to_mangled(out.types);
 
     writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
@@ -1300,7 +1323,7 @@ fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &ResolvableNam
     writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
-    write_unique_ptr_common(out, vector_ty);
+    write_unique_ptr_common(out, UniquePtr::CxxVector(element));
 
     writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
 }

From ee9b9eebadc197f1b4cbd4f66bca718e0d08725e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 16:28:50 +0000
Subject: [PATCH 1531/2232] Remove unneeded copy_assignable_if template parameter name


---

diff --git a/include/cxx.h b/include/cxx.h
index 1b30497..0c91857 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -88,7 +88,7 @@ private:
 
 #ifndef CXXBRIDGE1_RUST_SLICE
 namespace detail {
-template <bool cond>
+template <bool>
 struct copy_assignable_if {};
 
 template <>

From 534627667d2690aadeedb2ccedda77be054e9eb0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 16:29:01 +0000
Subject: [PATCH 1532/2232] Improve error message on unique_ptr of incomplete forward declared type


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 53facbf..35620db 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -25,6 +25,8 @@ pub struct Builtins<'a> {
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
+    pub is_complete: bool,
+    pub deleter_if: bool,
     pub content: Content<'a>,
 }
 
@@ -226,6 +228,33 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
+    if builtin.is_complete {
+        include.type_traits = true;
+        out.next_section();
+        writeln!(out, "template <typename T, typename = size_t>");
+        writeln!(out, "struct is_complete : std::false_type {{}};");
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(
+            out,
+            "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
+        );
+    }
+
+    if builtin.deleter_if {
+        out.next_section();
+        writeln!(out, "template <bool> struct deleter_if {{");
+        writeln!(out, "  template <typename T> void operator()(T *) {{}}");
+        writeln!(out, "}};");
+        out.next_section();
+        writeln!(out, "template <> struct deleter_if<true> {{");
+        writeln!(
+            out,
+            "  template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
+        );
+        writeln!(out, "}};");
+    }
+
     out.end_block(Block::AnonymousNamespace);
     out.end_block(Block::InlineNamespace("cxxbridge1"));
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e33197c..a12af31 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1242,6 +1242,26 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         UniquePtr::CxxVector(_) => false,
     };
 
+    let conditional_delete = match ty {
+        UniquePtr::Ident(ident) => {
+            !out.types.structs.contains_key(&ident.rust)
+                && !out.types.enums.contains_key(&ident.rust)
+        }
+        UniquePtr::CxxVector(_) => false,
+    };
+
+    if conditional_delete {
+        out.builtin.is_complete = true;
+        let definition = match ty {
+            UniquePtr::Ident(ty) => &out.types.resolve(ty).cxx,
+            UniquePtr::CxxVector(_) => unreachable!(),
+        };
+        writeln!(
+            out,
+            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+            inner, definition,
+        );
+    }
     writeln!(
         out,
         "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -1298,7 +1318,16 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  ptr->~unique_ptr();");
+    if conditional_delete {
+        out.builtin.deleter_if = true;
+        writeln!(
+            out,
+            "  ::rust::deleter_if<::rust::is_complete<{}>::value>{{}}(ptr);",
+            inner,
+        );
+    } else {
+        writeln!(out, "  ptr->~unique_ptr();");
+    }
     writeln!(out, "}}");
 }
 

From af7471e6d38e354ac4ce3623775fa3e32099ef90 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 16:43:46 +0000
Subject: [PATCH 1533/2232] Merge pull request #507 from dtolnay/is_complete


Improve error message on unique_ptr of incomplete forward declared type
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 53facbf..35620db 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -25,6 +25,8 @@ pub struct Builtins<'a> {
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
+    pub is_complete: bool,
+    pub deleter_if: bool,
     pub content: Content<'a>,
 }
 
@@ -226,6 +228,33 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
+    if builtin.is_complete {
+        include.type_traits = true;
+        out.next_section();
+        writeln!(out, "template <typename T, typename = size_t>");
+        writeln!(out, "struct is_complete : std::false_type {{}};");
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(
+            out,
+            "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
+        );
+    }
+
+    if builtin.deleter_if {
+        out.next_section();
+        writeln!(out, "template <bool> struct deleter_if {{");
+        writeln!(out, "  template <typename T> void operator()(T *) {{}}");
+        writeln!(out, "}};");
+        out.next_section();
+        writeln!(out, "template <> struct deleter_if<true> {{");
+        writeln!(
+            out,
+            "  template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
+        );
+        writeln!(out, "}};");
+    }
+
     out.end_block(Block::AnonymousNamespace);
     out.end_block(Block::InlineNamespace("cxxbridge1"));
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e33197c..a12af31 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1242,6 +1242,26 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         UniquePtr::CxxVector(_) => false,
     };
 
+    let conditional_delete = match ty {
+        UniquePtr::Ident(ident) => {
+            !out.types.structs.contains_key(&ident.rust)
+                && !out.types.enums.contains_key(&ident.rust)
+        }
+        UniquePtr::CxxVector(_) => false,
+    };
+
+    if conditional_delete {
+        out.builtin.is_complete = true;
+        let definition = match ty {
+            UniquePtr::Ident(ty) => &out.types.resolve(ty).cxx,
+            UniquePtr::CxxVector(_) => unreachable!(),
+        };
+        writeln!(
+            out,
+            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+            inner, definition,
+        );
+    }
     writeln!(
         out,
         "static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -1298,7 +1318,16 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  ptr->~unique_ptr();");
+    if conditional_delete {
+        out.builtin.deleter_if = true;
+        writeln!(
+            out,
+            "  ::rust::deleter_if<::rust::is_complete<{}>::value>{{}}(ptr);",
+            inner,
+        );
+    } else {
+        writeln!(out, "  ptr->~unique_ptr();");
+    }
     writeln!(out, "}}");
 }
 

From 2c642d82e3e492d4b201da22f4edff67f7c9ca02 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 20:56:39 +0000
Subject: [PATCH 1534/2232] Include filepath in no-bridge-found error


---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 2335d43..2c8287f 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -68,6 +68,13 @@ pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
                 display_syn_error(stderr, path, source, error);
             }
         }
+        Error::NoBridgeMod => {
+            let _ = writeln!(
+                io::stderr(),
+                "cxxbridge: no #[cxx::bridge] module found in {}",
+                path.display(),
+            );
+        }
         _ => {
             let _ = writeln!(io::stderr(), "cxxbridge: {}", report(error));
         }

From 8abd492dc51eb4c884195a3f8430bc73d50986c5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:07:20 +0000
Subject: [PATCH 1535/2232] Merge pull request #508 from dtolnay/nobridge


Include filepath in no-bridge-found error
---

diff --git a/gen/src/error.rs b/gen/src/error.rs
index 2335d43..2c8287f 100644
--- a/gen/src/error.rs
+++ b/gen/src/error.rs
@@ -68,6 +68,13 @@ pub(super) fn format_err(path: &Path, source: &str, error: Error) -> ! {
                 display_syn_error(stderr, path, source, error);
             }
         }
+        Error::NoBridgeMod => {
+            let _ = writeln!(
+                io::stderr(),
+                "cxxbridge: no #[cxx::bridge] module found in {}",
+                path.display(),
+            );
+        }
         _ => {
             let _ = writeln!(io::stderr(), "cxxbridge: {}", report(error));
         }

From 216fed4a37307e71947611fa9ee22fea0f1dbe19 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:10:10 +0000
Subject: [PATCH 1536/2232] Release 1.0.4


---

diff --git a/Cargo.toml b/Cargo.toml
index c84106d..9d66514 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.3" # remember to update html_root_url
+version = "1.0.4" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.3", path = "macro" }
+cxxbridge-macro = { version = "=1.0.4", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.3", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.4", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.3", path = "gen/build" }
+cxx-build = { version = "=1.0.4", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 194d53c..28c1fe0 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.3"
+version = "1.0.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 1b0b488..9364808 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.3"
+version = "1.0.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index ed79053..c817cbb 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.3"
+version = "1.0.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 4bf4f2b..6245519 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.3"
+version = "0.7.4"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 3b86dc4..1a581f2 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.3"
+version = "1.0.4"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 9ee2c4f..e971b50 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.3")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.4")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b1d1aca..14a5bb9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.3"
+version = "0.7.4"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.3"
+version = "1.0.4"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.3"
+version = "1.0.4"
 dependencies = [
  "cxx",
  "proc-macro2",

From 66f216c77656fd70e785bdfd2835a69e3292b64d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:25:52 +0000
Subject: [PATCH 1537/2232] Move Vec<T>::const_iterator definition out of line


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index f3056fb..88d49d3 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -39,27 +39,29 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
-  class const_iterator final {
-  public:
-    using difference_type = ptrdiff_t;
-    using value_type = typename std::add_const<T>::type;
-    using pointer =
-        typename std::add_pointer<typename std::add_const<T>::type>::type;
-    using reference = typename std::add_lvalue_reference<
-        typename std::add_const<T>::type>::type;
-    using iterator_category = std::forward_iterator_tag;
-
-    const T &operator*() const noexcept;
-    const T *operator->() const noexcept;
-    const_iterator &operator++() noexcept;
-    const_iterator operator++(int) noexcept;
-    bool operator==(const const_iterator &) const noexcept;
-    bool operator!=(const const_iterator &) const noexcept;
-  };
-
+  class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
 };
+
+template <typename T>
+class Vec<T>::const_iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = typename std::add_const<T>::type;
+  using pointer =
+      typename std::add_pointer<typename std::add_const<T>::type>::type;
+  using reference = typename std::add_lvalue_reference<
+      typename std::add_const<T>::type>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  const T &operator*() const noexcept;
+  const T *operator->() const noexcept;
+  const_iterator &operator++() noexcept;
+  const_iterator operator++(int) noexcept;
+  bool operator==(const const_iterator &) const noexcept;
+  bool operator!=(const const_iterator &) const noexcept;
+};
 #
 # } // namespace rust
 ```
diff --git a/include/cxx.h b/include/cxx.h
index 0c91857..d1ab3c7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -197,29 +197,7 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
-  class const_iterator final {
-  public:
-    using difference_type = ptrdiff_t;
-    using value_type = typename std::add_const<T>::type;
-    using pointer =
-        typename std::add_pointer<typename std::add_const<T>::type>::type;
-    using reference = typename std::add_lvalue_reference<
-        typename std::add_const<T>::type>::type;
-    using iterator_category = std::forward_iterator_tag;
-
-    const T &operator*() const noexcept;
-    const T *operator->() const noexcept;
-    const_iterator &operator++() noexcept;
-    const_iterator operator++(int) noexcept;
-    bool operator==(const const_iterator &) const noexcept;
-    bool operator!=(const const_iterator &) const noexcept;
-
-  private:
-    friend class Vec;
-    const void *pos;
-    size_t stride;
-  };
-
+  class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
 
@@ -235,6 +213,30 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<uintptr_t, 3> repr;
 };
+
+template <typename T>
+class Vec<T>::const_iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = typename std::add_const<T>::type;
+  using pointer =
+      typename std::add_pointer<typename std::add_const<T>::type>::type;
+  using reference = typename std::add_lvalue_reference<
+      typename std::add_const<T>::type>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  const T &operator*() const noexcept;
+  const T *operator->() const noexcept;
+  const_iterator &operator++() noexcept;
+  const_iterator operator++(int) noexcept;
+  bool operator==(const const_iterator &) const noexcept;
+  bool operator!=(const const_iterator &) const noexcept;
+
+private:
+  friend class Vec;
+  const void *pos;
+  size_t stride;
+};
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN

From 960b511adce091c5ad398908e8948a797e878e91 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:31:54 +0000
Subject: [PATCH 1538/2232] Add rust::Vec mutable iterator


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 88d49d3..01c1d1f 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -39,9 +39,32 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
+  class iterator;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
   class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+};
+
+template <typename T>
+class Vec<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
 };
 
 template <typename T>
diff --git a/include/cxx.h b/include/cxx.h
index d1ab3c7..374714b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -197,9 +197,15 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
+  class iterator;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
   class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 
   // Internal API only intended for the cxxbridge code generator.
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
@@ -215,6 +221,28 @@ private:
 };
 
 template <typename T>
+class Vec<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
+
+private:
+  friend class Vec;
+  void *pos;
+  size_t stride;
+};
+
+template <typename T>
 class Vec<T>::const_iterator final {
 public:
   using difference_type = ptrdiff_t;
@@ -577,6 +605,39 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
+T &Vec<T>::iterator::operator*() const noexcept {
+  return *static_cast<T *>(this->pos);
+}
+
+template <typename T>
+T *Vec<T>::iterator::operator->() const noexcept {
+  return static_cast<T *>(this->pos);
+}
+
+template <typename T>
+typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
+  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
+  auto ret = iterator(*this);
+  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  return ret;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
@@ -613,7 +674,32 @@ bool Vec<T>::const_iterator::operator!=(
 }
 
 template <typename T>
+typename Vec<T>::iterator Vec<T>::begin() noexcept {
+  iterator it;
+  it.pos = this->data();
+  it.stride = this->stride();
+  return it;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::end() noexcept {
+  iterator it = this->begin();
+  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
+  return it;
+}
+
+template <typename T>
 typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
+  return this->cbegin();
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
+  return this->cend();
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
   it.pos = this->data();
   it.stride = this->stride();
@@ -621,8 +707,8 @@ typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
 }
 
 template <typename T>
-typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
-  const_iterator it = this->begin();
+typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
+  const_iterator it = this->cbegin();
   it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
   return it;
 }

From 079f69a5e3306a18011da83ed0d58ece8d6e7ab7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:42:35 +0000
Subject: [PATCH 1539/2232] Merge pull request #509 from dtolnay/iterator


Add rust::Vec mutable iterator
---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 88d49d3..01c1d1f 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -39,9 +39,32 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
+  class iterator;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
   class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+};
+
+template <typename T>
+class Vec<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
 };
 
 template <typename T>
diff --git a/include/cxx.h b/include/cxx.h
index d1ab3c7..374714b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -197,9 +197,15 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
+  class iterator;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
   class const_iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 
   // Internal API only intended for the cxxbridge code generator.
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
@@ -215,6 +221,28 @@ private:
 };
 
 template <typename T>
+class Vec<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
+
+private:
+  friend class Vec;
+  void *pos;
+  size_t stride;
+};
+
+template <typename T>
 class Vec<T>::const_iterator final {
 public:
   using difference_type = ptrdiff_t;
@@ -577,6 +605,39 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
+T &Vec<T>::iterator::operator*() const noexcept {
+  return *static_cast<T *>(this->pos);
+}
+
+template <typename T>
+T *Vec<T>::iterator::operator->() const noexcept {
+  return static_cast<T *>(this->pos);
+}
+
+template <typename T>
+typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
+  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
+  auto ret = iterator(*this);
+  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  return ret;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
 const T &Vec<T>::const_iterator::operator*() const noexcept {
   return *static_cast<const T *>(this->pos);
 }
@@ -613,7 +674,32 @@ bool Vec<T>::const_iterator::operator!=(
 }
 
 template <typename T>
+typename Vec<T>::iterator Vec<T>::begin() noexcept {
+  iterator it;
+  it.pos = this->data();
+  it.stride = this->stride();
+  return it;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::end() noexcept {
+  iterator it = this->begin();
+  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
+  return it;
+}
+
+template <typename T>
 typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
+  return this->cbegin();
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
+  return this->cend();
+}
+
+template <typename T>
+typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
   it.pos = this->data();
   it.stride = this->stride();
@@ -621,8 +707,8 @@ typename Vec<T>::const_iterator Vec<T>::begin() const noexcept {
 }
 
 template <typename T>
-typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
-  const_iterator it = this->begin();
+typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
+  const_iterator it = this->cbegin();
   it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
   return it;
 }

From 3d5a25a496c17cc615d21433aed52611aa2be9ee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 21:48:35 +0000
Subject: [PATCH 1540/2232] Simplify irrelevant detail from documentation of Vec iterator API


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 01c1d1f..e1767e5 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -53,11 +53,9 @@ public:
 template <typename T>
 class Vec<T>::iterator final {
 public:
-  using difference_type = ptrdiff_t;
   using value_type = T;
-  using pointer = typename std::add_pointer<T>::type;
-  using reference = typename std::add_lvalue_reference<T>::type;
-  using iterator_category = std::forward_iterator_tag;
+  using pointer = T *;
+  using reference = T &;
 
   T &operator*() const noexcept;
   T *operator->() const noexcept;
@@ -70,13 +68,9 @@ public:
 template <typename T>
 class Vec<T>::const_iterator final {
 public:
-  using difference_type = ptrdiff_t;
-  using value_type = typename std::add_const<T>::type;
-  using pointer =
-      typename std::add_pointer<typename std::add_const<T>::type>::type;
-  using reference = typename std::add_lvalue_reference<
-      typename std::add_const<T>::type>::type;
-  using iterator_category = std::forward_iterator_tag;
+  using value_type = const T;
+  using pointer = const T *;
+  using reference = const T &;
 
   const T &operator*() const noexcept;
   const T *operator->() const noexcept;

From b004098cee51d5946324374561978ef38e0fff07 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 22:29:15 +0000
Subject: [PATCH 1541/2232] Add Vec cbegin/cend test


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 46d8b16..38942e1 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -343,11 +343,14 @@ void c_take_rust_vec_string(rust::Vec<rust::String> v) {
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   // Exercise requirements of ForwardIterator
   // https://en.cppreference.com/w/cpp/named_req/ForwardIterator
-  uint32_t sum = 0;
+  uint32_t sum = 0, csum = 0;
   for (auto it = v.begin(), it_end = v.end(); it != it_end; it++) {
     sum += it->z;
   }
-  if (sum == 2021) {
+  for (auto it = v.cbegin(), it_end = v.cend(); it != it_end; it++) {
+    csum += it->z;
+  }
+  if (sum == 2021 && csum == 2021) {
     cxx_test_suite_set_correct();
   }
 }

From 9578cf114d71246970b198802083f42bf1472321 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 22:36:59 +0000
Subject: [PATCH 1542/2232] Add static assertions on type equality of Vec iterators


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 28506ef..cd72d82 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -191,6 +191,16 @@ static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
 static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
               "trivial ~Slice()");
 
+static_assert(std::is_same<Vec<uint8_t>::const_iterator,
+                           Vec<const uint8_t>::iterator>::value,
+              "Vec<T>::const_iterator == Vec<const T>::iterator");
+static_assert(std::is_same<Vec<const uint8_t>::const_iterator,
+                           Vec<const uint8_t>::iterator>::value,
+              "Vec<const T>::const_iterator == Vec<const T>::iterator");
+static_assert(
+    !std::is_same<Vec<uint8_t>::const_iterator, Vec<uint8_t>::iterator>::value,
+    "Vec<T>::const_iterator != Vec<T>::iterator");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];

From a5d72c6b99629fd64812b8b946884772222444d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 22:36:59 +0000
Subject: [PATCH 1543/2232] Share type between Vec<T>::const_iterator and Vec<const T>::iterator


---

diff --git a/include/cxx.h b/include/cxx.h
index 374714b..204f6a9 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -201,7 +201,7 @@ public:
   iterator begin() noexcept;
   iterator end() noexcept;
 
-  class const_iterator;
+  using const_iterator = typename Vec<const T>::iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
@@ -238,33 +238,10 @@ public:
 
 private:
   friend class Vec;
+  friend class Vec<typename std::remove_const<T>::type>;
   void *pos;
   size_t stride;
 };
-
-template <typename T>
-class Vec<T>::const_iterator final {
-public:
-  using difference_type = ptrdiff_t;
-  using value_type = typename std::add_const<T>::type;
-  using pointer =
-      typename std::add_pointer<typename std::add_const<T>::type>::type;
-  using reference = typename std::add_lvalue_reference<
-      typename std::add_const<T>::type>::type;
-  using iterator_category = std::forward_iterator_tag;
-
-  const T &operator*() const noexcept;
-  const T *operator->() const noexcept;
-  const_iterator &operator++() noexcept;
-  const_iterator operator++(int) noexcept;
-  bool operator==(const const_iterator &) const noexcept;
-  bool operator!=(const const_iterator &) const noexcept;
-
-private:
-  friend class Vec;
-  const void *pos;
-  size_t stride;
-};
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN
@@ -638,45 +615,9 @@ bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
-const T &Vec<T>::const_iterator::operator*() const noexcept {
-  return *static_cast<const T *>(this->pos);
-}
-
-template <typename T>
-const T *Vec<T>::const_iterator::operator->() const noexcept {
-  return static_cast<const T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
-  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::const_iterator
-Vec<T>::const_iterator::operator++(int) noexcept {
-  auto ret = const_iterator(*this);
-  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-  return ret;
-}
-
-template <typename T>
-bool Vec<T>::const_iterator::operator==(
-    const const_iterator &other) const noexcept {
-  return this->pos == other.pos;
-}
-
-template <typename T>
-bool Vec<T>::const_iterator::operator!=(
-    const const_iterator &other) const noexcept {
-  return this->pos != other.pos;
-}
-
-template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
-  it.pos = this->data();
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
   it.stride = this->stride();
   return it;
 }
@@ -701,7 +642,7 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
-  it.pos = this->data();
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
   it.stride = this->stride();
   return it;
 }
@@ -709,7 +650,7 @@ typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
   const_iterator it = this->cbegin();
-  it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
   return it;
 }
 

From 63b92f5530d4219a5ecd7bf5f08a8fbadd9a0ae4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 22:46:29 +0000
Subject: [PATCH 1544/2232] Merge pull request #510 from dtolnay/iterator


Share type between Vec<T>::const_iterator and Vec<const T>::iterator
---

diff --git a/include/cxx.h b/include/cxx.h
index 374714b..204f6a9 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -201,7 +201,7 @@ public:
   iterator begin() noexcept;
   iterator end() noexcept;
 
-  class const_iterator;
+  using const_iterator = typename Vec<const T>::iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
@@ -238,33 +238,10 @@ public:
 
 private:
   friend class Vec;
+  friend class Vec<typename std::remove_const<T>::type>;
   void *pos;
   size_t stride;
 };
-
-template <typename T>
-class Vec<T>::const_iterator final {
-public:
-  using difference_type = ptrdiff_t;
-  using value_type = typename std::add_const<T>::type;
-  using pointer =
-      typename std::add_pointer<typename std::add_const<T>::type>::type;
-  using reference = typename std::add_lvalue_reference<
-      typename std::add_const<T>::type>::type;
-  using iterator_category = std::forward_iterator_tag;
-
-  const T &operator*() const noexcept;
-  const T *operator->() const noexcept;
-  const_iterator &operator++() noexcept;
-  const_iterator operator++(int) noexcept;
-  bool operator==(const const_iterator &) const noexcept;
-  bool operator!=(const const_iterator &) const noexcept;
-
-private:
-  friend class Vec;
-  const void *pos;
-  size_t stride;
-};
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN
@@ -638,45 +615,9 @@ bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
-const T &Vec<T>::const_iterator::operator*() const noexcept {
-  return *static_cast<const T *>(this->pos);
-}
-
-template <typename T>
-const T *Vec<T>::const_iterator::operator->() const noexcept {
-  return static_cast<const T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::const_iterator &Vec<T>::const_iterator::operator++() noexcept {
-  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::const_iterator
-Vec<T>::const_iterator::operator++(int) noexcept {
-  auto ret = const_iterator(*this);
-  this->pos = static_cast<const uint8_t *>(this->pos) + this->stride;
-  return ret;
-}
-
-template <typename T>
-bool Vec<T>::const_iterator::operator==(
-    const const_iterator &other) const noexcept {
-  return this->pos == other.pos;
-}
-
-template <typename T>
-bool Vec<T>::const_iterator::operator!=(
-    const const_iterator &other) const noexcept {
-  return this->pos != other.pos;
-}
-
-template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
-  it.pos = this->data();
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
   it.stride = this->stride();
   return it;
 }
@@ -701,7 +642,7 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
-  it.pos = this->data();
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
   it.stride = this->stride();
   return it;
 }
@@ -709,7 +650,7 @@ typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
   const_iterator it = this->cbegin();
-  it.pos = static_cast<const uint8_t *>(it.pos) + it.stride * this->size();
+  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
   return it;
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 28506ef..cd72d82 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -191,6 +191,16 @@ static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
 static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
               "trivial ~Slice()");
 
+static_assert(std::is_same<Vec<uint8_t>::const_iterator,
+                           Vec<const uint8_t>::iterator>::value,
+              "Vec<T>::const_iterator == Vec<const T>::iterator");
+static_assert(std::is_same<Vec<const uint8_t>::const_iterator,
+                           Vec<const uint8_t>::iterator>::value,
+              "Vec<const T>::const_iterator == Vec<const T>::iterator");
+static_assert(
+    !std::is_same<Vec<uint8_t>::const_iterator, Vec<uint8_t>::iterator>::value,
+    "Vec<T>::const_iterator != Vec<T>::iterator");
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, size_t len) {
   char *copy = new char[len];

From 819eeb7f5b90a8e03f8e8fd14f2d9e920b0a83e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 23:50:07 +0000
Subject: [PATCH 1545/2232] Convert array expr test to fields of a struct


---

diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
index fdd9783..1e1a548 100644
--- a/tests/ui/array_len_expr.rs
+++ b/tests/ui/array_len_expr.rs
@@ -1,8 +1,8 @@
 #[cxx::bridge]
 mod ffi {
-    unsafe extern "C++" {
-        fn arraystr() -> [String; "13"];
-        fn arraysub() -> [String; 15 - 1];
+    struct Shared {
+        arraystr: [String; "13"],
+        arraysub: [String; 15 - 1],
     }
 }
 
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
index cb94328..2c26ab0 100644
--- a/tests/ui/array_len_expr.stderr
+++ b/tests/ui/array_len_expr.stderr
@@ -1,11 +1,5 @@
 error: array length must be an integer literal
- --> $DIR/array_len_expr.rs:4:35
+ --> $DIR/array_len_expr.rs:4:28
   |
-4 |         fn arraystr() -> [String; "13"];
-  |                                   ^^^^
-
-error: unsupported expression, array length must be an integer literal
- --> $DIR/array_len_expr.rs:5:35
-  |
-5 |         fn arraysub() -> [String; 15 - 1];
-  |                                   ^^^^^^
+4 |         arraystr: [String; "13"],
+  |                            ^^^^

From 38c1121df3a242ac1639aea326fcda828661de70 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 23:50:19 +0000
Subject: [PATCH 1546/2232] Allow simultaneous diagnostics on multiple fields of a struct


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 15ee4f2..18809b5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -89,16 +89,18 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         }
     };
 
-    let fields = named_fields
-        .named
-        .into_iter()
-        .map(|field| {
-            Ok(Var {
-                ident: field.ident.unwrap(),
-                ty: parse_type(&field.ty)?,
-            })
-        })
-        .collect::<Result<_>>()?;
+    let mut fields = Vec::new();
+    for field in named_fields.named {
+        let ident = field.ident.unwrap();
+        let ty = match parse_type(&field.ty) {
+            Ok(ty) => ty,
+            Err(err) => {
+                cx.push(err);
+                continue;
+            }
+        };
+        fields.push(Var { ident, ty });
+    }
 
     Ok(Api::Struct(Struct {
         doc,
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
index 2c26ab0..bbd7d11 100644
--- a/tests/ui/array_len_expr.stderr
+++ b/tests/ui/array_len_expr.stderr
@@ -3,3 +3,9 @@ error: array length must be an integer literal
   |
 4 |         arraystr: [String; "13"],
   |                            ^^^^
+
+error: unsupported expression, array length must be an integer literal
+ --> $DIR/array_len_expr.rs:5:28
+  |
+5 |         arraysub: [String; 15 - 1],
+  |                            ^^^^^^

From bc8e0276632c0b5512e5579653bf5587f22dbcc4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 25 2020 23:58:45 +0000
Subject: [PATCH 1547/2232] Merge pull request #511 from dtolnay/fielderr


Allow simultaneous diagnostics on multiple fields of a struct
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 15ee4f2..18809b5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -89,16 +89,18 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         }
     };
 
-    let fields = named_fields
-        .named
-        .into_iter()
-        .map(|field| {
-            Ok(Var {
-                ident: field.ident.unwrap(),
-                ty: parse_type(&field.ty)?,
-            })
-        })
-        .collect::<Result<_>>()?;
+    let mut fields = Vec::new();
+    for field in named_fields.named {
+        let ident = field.ident.unwrap();
+        let ty = match parse_type(&field.ty) {
+            Ok(ty) => ty,
+            Err(err) => {
+                cx.push(err);
+                continue;
+            }
+        };
+        fields.push(Var { ident, ty });
+    }
 
     Ok(Api::Struct(Struct {
         doc,
diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
index fdd9783..1e1a548 100644
--- a/tests/ui/array_len_expr.rs
+++ b/tests/ui/array_len_expr.rs
@@ -1,8 +1,8 @@
 #[cxx::bridge]
 mod ffi {
-    unsafe extern "C++" {
-        fn arraystr() -> [String; "13"];
-        fn arraysub() -> [String; 15 - 1];
+    struct Shared {
+        arraystr: [String; "13"],
+        arraysub: [String; 15 - 1],
     }
 }
 
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
index cb94328..bbd7d11 100644
--- a/tests/ui/array_len_expr.stderr
+++ b/tests/ui/array_len_expr.stderr
@@ -1,11 +1,11 @@
 error: array length must be an integer literal
- --> $DIR/array_len_expr.rs:4:35
+ --> $DIR/array_len_expr.rs:4:28
   |
-4 |         fn arraystr() -> [String; "13"];
-  |                                   ^^^^
+4 |         arraystr: [String; "13"],
+  |                            ^^^^
 
 error: unsupported expression, array length must be an integer literal
- --> $DIR/array_len_expr.rs:5:35
+ --> $DIR/array_len_expr.rs:5:28
   |
-5 |         fn arraysub() -> [String; 15 - 1];
-  |                                   ^^^^^^
+5 |         arraysub: [String; 15 - 1],
+  |                            ^^^^^^

From 581f72dc8fa8157dcbd42ca62e95a6d9ecad53f2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:00:03 +0000
Subject: [PATCH 1548/2232] Disallow array with zero size


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 18809b5..018e71a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -767,9 +767,14 @@ fn parse_type_array(ty: &TypeArray) -> Result<Type> {
         return Err(Error::new_spanned(len_expr, msg));
     };
 
+    let len = len_token.base10_parse::<usize>()?;
+    if len == 0 {
+        let msg = "array with zero size is not supported";
+        return Err(Error::new_spanned(ty, msg));
+    }
+
     let bracket = ty.bracket_token;
     let semi_token = ty.semi_token;
-    let len = len_token.base10_parse::<usize>()?;
 
     Ok(Type::Array(Box::new(Array {
         bracket,
diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
index 1e1a548..73da57c 100644
--- a/tests/ui/array_len_expr.rs
+++ b/tests/ui/array_len_expr.rs
@@ -3,6 +3,7 @@ mod ffi {
     struct Shared {
         arraystr: [String; "13"],
         arraysub: [String; 15 - 1],
+        arrayzero: [String; 0],
     }
 }
 
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
index bbd7d11..4b45a0b 100644
--- a/tests/ui/array_len_expr.stderr
+++ b/tests/ui/array_len_expr.stderr
@@ -9,3 +9,9 @@ error: unsupported expression, array length must be an integer literal
   |
 5 |         arraysub: [String; 15 - 1],
   |                            ^^^^^^
+
+error: array with zero size is not supported
+ --> $DIR/array_len_expr.rs:6:20
+  |
+6 |         arrayzero: [String; 0],
+  |                    ^^^^^^^^^^^

From f520e20cfc48cc4006debb9c20533ace2c3bc3c5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:07:18 +0000
Subject: [PATCH 1549/2232] Merge pull request #512 from dtolnay/arrayzero


Disallow array with zero size
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 18809b5..018e71a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -767,9 +767,14 @@ fn parse_type_array(ty: &TypeArray) -> Result<Type> {
         return Err(Error::new_spanned(len_expr, msg));
     };
 
+    let len = len_token.base10_parse::<usize>()?;
+    if len == 0 {
+        let msg = "array with zero size is not supported";
+        return Err(Error::new_spanned(ty, msg));
+    }
+
     let bracket = ty.bracket_token;
     let semi_token = ty.semi_token;
-    let len = len_token.base10_parse::<usize>()?;
 
     Ok(Type::Array(Box::new(Array {
         bracket,
diff --git a/tests/ui/array_len_expr.rs b/tests/ui/array_len_expr.rs
index 1e1a548..73da57c 100644
--- a/tests/ui/array_len_expr.rs
+++ b/tests/ui/array_len_expr.rs
@@ -3,6 +3,7 @@ mod ffi {
     struct Shared {
         arraystr: [String; "13"],
         arraysub: [String; 15 - 1],
+        arrayzero: [String; 0],
     }
 }
 
diff --git a/tests/ui/array_len_expr.stderr b/tests/ui/array_len_expr.stderr
index bbd7d11..4b45a0b 100644
--- a/tests/ui/array_len_expr.stderr
+++ b/tests/ui/array_len_expr.stderr
@@ -9,3 +9,9 @@ error: unsupported expression, array length must be an integer literal
   |
 5 |         arraysub: [String; 15 - 1],
   |                            ^^^^^^
+
+error: array with zero size is not supported
+ --> $DIR/array_len_expr.rs:6:20
+  |
+6 |         arrayzero: [String; 0],
+  |                    ^^^^^^^^^^^

From 365fc7c66ae7a920123d9d936dccc0594f23e4be Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:22:54 +0000
Subject: [PATCH 1550/2232] Add common base class for opaque Rust types


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 35620db..621d88c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -12,6 +12,7 @@ pub struct Builtins<'a> {
     pub rust_vec: bool,
     pub rust_fn: bool,
     pub rust_isize: bool,
+    pub opaque: bool,
     pub unsafe_bitcopy: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
@@ -120,6 +121,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+    ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
     if builtin.manually_drop {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a12af31..66d6351 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -232,13 +232,8 @@ fn write_struct_with_methods<'a>(
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "struct {} final {{", ety.name.cxx);
-    writeln!(out, "  {}() = delete;", ety.name.cxx);
-    writeln!(
-        out,
-        "  {}(const {} &) = delete;",
-        ety.name.cxx, ety.name.cxx,
-    );
+    out.builtin.opaque = true;
+    writeln!(out, "struct {} final : public ::rust::Opaque {{", ety.name.cxx);
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
diff --git a/include/cxx.h b/include/cxx.h
index 204f6a9..0632f22 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -296,6 +296,16 @@ using isize = ssize_t;
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
+#ifndef CXXBRIDGE1_RUST_OPAQUE
+#define CXXBRIDGE1_RUST_OPAQUE
+// Base class of generated opaque Rust types.
+class Opaque {
+  Opaque() = delete;
+  Opaque(const Opaque &) = delete;
+  ~Opaque() = delete;
+};
+#endif // CXXBRIDGE1_RUST_OPAQUE
+
 // IsRelocatable<T> is used in assertions that a C++ type passed by value
 // between Rust and C++ is soundly relocatable by Rust.
 //

From a857c32d402fbfd471d3953524934794cde42407 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:27:25 +0000
Subject: [PATCH 1551/2232] Public deleted Opaque special members to resolve modernize-use-equals-delete


    include/cxx.h:303:3: warning: deleted member function should be public [modernize-use-equals-delete]
      Opaque() = delete;
      ^
    include/cxx.h:304:3: warning: deleted member function should be public [modernize-use-equals-delete]
      Opaque(const Opaque &) = delete;
      ^
    include/cxx.h:305:3: warning: deleted member function should be public [modernize-use-equals-delete]
      ~Opaque() = delete;
      ^

---

diff --git a/include/cxx.h b/include/cxx.h
index 0632f22..064d51f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -300,6 +300,7 @@ std::ostream &operator<<(std::ostream &, const Str &);
 #define CXXBRIDGE1_RUST_OPAQUE
 // Base class of generated opaque Rust types.
 class Opaque {
+public:
   Opaque() = delete;
   Opaque(const Opaque &) = delete;
   ~Opaque() = delete;

From 4b52066c72aed368db45905547e44f1190e7c118 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:32:28 +0000
Subject: [PATCH 1552/2232] Merge pull request #513 from dtolnay/opaque


Add common base class for opaque Rust types
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 35620db..621d88c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -12,6 +12,7 @@ pub struct Builtins<'a> {
     pub rust_vec: bool,
     pub rust_fn: bool,
     pub rust_isize: bool,
+    pub opaque: bool,
     pub unsafe_bitcopy: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
@@ -120,6 +121,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+    ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
     if builtin.manually_drop {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a12af31..66d6351 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -232,13 +232,8 @@ fn write_struct_with_methods<'a>(
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
-    writeln!(out, "struct {} final {{", ety.name.cxx);
-    writeln!(out, "  {}() = delete;", ety.name.cxx);
-    writeln!(
-        out,
-        "  {}(const {} &) = delete;",
-        ety.name.cxx, ety.name.cxx,
-    );
+    out.builtin.opaque = true;
+    writeln!(out, "struct {} final : public ::rust::Opaque {{", ety.name.cxx);
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
diff --git a/include/cxx.h b/include/cxx.h
index 204f6a9..064d51f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -296,6 +296,17 @@ using isize = ssize_t;
 std::ostream &operator<<(std::ostream &, const String &);
 std::ostream &operator<<(std::ostream &, const Str &);
 
+#ifndef CXXBRIDGE1_RUST_OPAQUE
+#define CXXBRIDGE1_RUST_OPAQUE
+// Base class of generated opaque Rust types.
+class Opaque {
+public:
+  Opaque() = delete;
+  Opaque(const Opaque &) = delete;
+  ~Opaque() = delete;
+};
+#endif // CXXBRIDGE1_RUST_OPAQUE
+
 // IsRelocatable<T> is used in assertions that a C++ type passed by value
 // between Rust and C++ is soundly relocatable by Rust.
 //

From 7c06b86fdb6ed3519b8cbd2bbb5e01612c1f4764 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:59:17 +0000
Subject: [PATCH 1553/2232] Format with rustfmt 1.4.27-nightly


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 66d6351..5ee620a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -233,7 +233,11 @@ fn write_struct_with_methods<'a>(
         writeln!(out, "//{}", line);
     }
     out.builtin.opaque = true;
-    writeln!(out, "struct {} final : public ::rust::Opaque {{", ety.name.cxx);
+    writeln!(
+        out,
+        "struct {} final : public ::rust::Opaque {{",
+        ety.name.cxx,
+    );
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;

From 817f09e832442739c7856f0b194a92b66649860e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 00:59:17 +0000
Subject: [PATCH 1554/2232] Fn makes more sense to treat like unsized


---

diff --git a/syntax/check.rs b/syntax/check.rs
index f077bd3..6ffdbb1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -186,12 +186,7 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
-    let supported = match &ty.inner {
-        Type::Fn(_) => false,
-        element => !is_unsized(cx, element),
-    };
-
-    if !supported {
+    if is_unsized(cx, &ty.inner) {
         cx.error(ty, "unsupported array element type");
     }
 }
@@ -219,16 +214,15 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
     }
 
     for field in &strct.fields {
-        if is_unsized(cx, &field.ty) {
-            let desc = describe(cx, &field.ty);
-            let msg = format!("using {} by value is not supported", desc);
-            cx.error(field, msg);
-        }
         if let Type::Fn(_) = field.ty {
             cx.error(
                 field,
                 "function pointers in a struct field are not implemented yet",
             );
+        } else if is_unsized(cx, &field.ty) {
+            let desc = describe(cx, &field.ty);
+            let msg = format!("using {} by value is not supported", desc);
+            cx.error(field, msg);
         }
     }
 }
@@ -314,11 +308,6 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     }
 
     for arg in &efn.args {
-        if is_unsized(cx, &arg.ty) {
-            let desc = describe(cx, &arg.ty);
-            let msg = format!("passing {} by value is not supported", desc);
-            cx.error(arg, msg);
-        }
         if let Type::Fn(_) = arg.ty {
             if efn.lang == Lang::Rust {
                 cx.error(
@@ -326,18 +315,21 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                     "passing a function pointer from C++ to Rust is not implemented yet",
                 );
             }
+        } else if is_unsized(cx, &arg.ty) {
+            let desc = describe(cx, &arg.ty);
+            let msg = format!("passing {} by value is not supported", desc);
+            cx.error(arg, msg);
         }
     }
 
     if let Some(ty) = &efn.ret {
-        if is_unsized(cx, ty) {
+        if let Type::Fn(_) = ty {
+            cx.error(ty, "returning a function pointer is not implemented yet");
+        } else if is_unsized(cx, ty) {
             let desc = describe(cx, ty);
             let msg = format!("returning {} by value is not supported", desc);
             cx.error(ty, msg);
         }
-        if let Type::Fn(_) = ty {
-            cx.error(ty, "returning a function pointer is not implemented yet");
-        }
     }
 
     if efn.lang == Lang::Cxx {
@@ -427,13 +419,12 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
             ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
         }
         Type::Array(array) => is_unsized(cx, &array.inner),
-        Type::CxxVector(_) | Type::Slice(_) | Type::Void(_) => true,
+        Type::CxxVector(_) | Type::Slice(_) | Type::Fn(_) | Type::Void(_) => true,
         Type::RustBox(_)
         | Type::RustVec(_)
         | Type::UniquePtr(_)
         | Type::Ref(_)
         | Type::Str(_)
-        | Type::Fn(_)
         | Type::SliceRefU8(_) => false,
     }
 }

From da2558ec92bfd5c2ec2008f02e522b1fb97ef7d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 01:16:14 +0000
Subject: [PATCH 1555/2232] Reject array containing &str or &[u8] for now


This is blocked on making slices' data() and size() call into Rust to
deconstruct the fat pointer, which is TODO.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6ffdbb1..fcce5d4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -186,7 +186,12 @@ fn check_type_slice(cx: &mut Check, ty: &Slice) {
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
-    if is_unsized(cx, &ty.inner) {
+    let supported = match &ty.inner {
+        Type::Str(_) | Type::SliceRefU8(_) => false,
+        element => !is_unsized(cx, element),
+    };
+
+    if !supported {
         cx.error(ty, "unsupported array element type");
     }
 }

From e0dca7b994166d06df7b2cd76ca546cf003c8d32 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 01:38:54 +0000
Subject: [PATCH 1556/2232] Remove Type::Slice from syntax tree


Slices were considered illegal in most positions except as the target of
a reference, which led to confusing code in the code generators. This
commit replaces their syntax tree representation from
Type::Ref(Type::Slice(...)) to Type::SliceRef(...).

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5ee620a..d9e20da 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -167,7 +167,6 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
-            Type::Slice(_) => out.builtin.rust_slice = true,
             Type::SliceRefU8(_) => {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
@@ -890,10 +889,6 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &r.inner);
             write!(out, " &");
         }
-        Type::Slice(_) => {
-            // For now, only U8 slices are supported, which are covered separately below
-            unreachable!()
-        }
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
@@ -965,7 +960,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::Fn(_)
         | Type::Array(_) => write!(out, " "),
         Type::Ref(_) => {}
-        Type::Void(_) | Type::Slice(_) => unreachable!(),
+        Type::Void(_) => unreachable!(),
     }
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index fcce5d4..968f28b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    Slice, Struct, Ty1, Type, Types,
+    Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -34,7 +34,6 @@ fn do_typecheck(cx: &mut Check) {
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
-            Type::Slice(ty) => check_type_slice(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
@@ -178,13 +177,6 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     cx.error(ty, "unsupported reference type");
 }
 
-fn check_type_slice(cx: &mut Check, ty: &Slice) {
-    cx.error(
-        ty,
-        "only &[u8] and &mut [u8] are supported so far, not other slice types",
-    );
-}
-
 fn check_type_array(cx: &mut Check, ty: &Array) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRefU8(_) => false,
@@ -424,7 +416,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
             ident == CxxString || is_opaque_cxx(cx, ident) || cx.types.rust.contains(ident)
         }
         Type::Array(array) => is_unsized(cx, &array.inner),
-        Type::CxxVector(_) | Type::Slice(_) | Type::Fn(_) | Type::Void(_) => true,
+        Type::CxxVector(_) | Type::Fn(_) | Type::Void(_) => true,
         Type::RustBox(_)
         | Type::RustVec(_)
         | Type::UniquePtr(_)
@@ -500,7 +492,6 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
-        Type::Slice(_) => "slice".to_owned(),
         Type::SliceRefU8(ty) => match ty.mutable {
             false => "&[u8]".to_owned(),
             true => "&mut [u8]".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index f533093..36cf3cd 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,4 +1,6 @@
-use crate::syntax::{Array, ExternFn, Impl, Include, Receiver, Ref, Signature, Slice, Ty1, Type};
+use crate::syntax::{
+    Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type,
+};
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
@@ -48,7 +50,6 @@ impl Hash for Type {
             Type::RustVec(t) => t.hash(state),
             Type::CxxVector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
-            Type::Slice(t) => t.hash(state),
             Type::SliceRefU8(t) => t.hash(state),
             Type::Array(t) => t.hash(state),
             Type::Void(_) => {}
@@ -69,7 +70,6 @@ impl PartialEq for Type {
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
             (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
-            (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs,
             (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
@@ -154,22 +154,42 @@ impl Hash for Ref {
     }
 }
 
-impl Eq for Slice {}
+impl Eq for SliceRef {}
 
-impl PartialEq for Slice {
-    fn eq(&self, other: &Slice) -> bool {
-        let Slice { bracket: _, inner } = self;
-        let Slice {
+impl PartialEq for SliceRef {
+    fn eq(&self, other: &SliceRef) -> bool {
+        let SliceRef {
+            ampersand: _,
+            lifetime,
+            mutable,
+            bracket: _,
+            inner,
+            mutability: _,
+        } = self;
+        let SliceRef {
+            ampersand: _,
+            lifetime: lifetime2,
+            mutable: mutable2,
             bracket: _,
             inner: inner2,
+            mutability: _,
         } = other;
-        inner == inner2
+        lifetime == lifetime2 && mutable == mutable2 && inner == inner2
     }
 }
 
-impl Hash for Slice {
+impl Hash for SliceRef {
     fn hash<H: Hasher>(&self, state: &mut H) {
-        let Slice { bracket: _, inner } = self;
+        let SliceRef {
+            ampersand: _,
+            lifetime,
+            mutable,
+            bracket: _,
+            inner,
+            mutability: _,
+        } = self;
+        lifetime.hash(state);
+        mutable.hash(state);
         inner.hash(state);
     }
 }
diff --git a/syntax/improper.rs b/syntax/improper.rs
index e016884..95cf4af 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -27,7 +27,6 @@ impl<'a> Types<'a> {
             | Type::Str(_)
             | Type::Fn(_)
             | Type::Void(_)
-            | Type::Slice(_)
             | Type::SliceRefU8(_) => Definite(true),
             Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e61e384..c3c24ff 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -164,8 +164,7 @@ pub enum Type {
     CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
-    Slice(Box<Slice>),
-    SliceRefU8(Box<Ref>),
+    SliceRefU8(Box<SliceRef>),
     Array(Box<Array>),
 }
 
@@ -186,9 +185,13 @@ pub struct Ref {
     pub mutability: Option<Token![mut]>,
 }
 
-pub struct Slice {
+pub struct SliceRef {
+    pub ampersand: Token![&],
+    pub lifetime: Option<Lifetime>,
+    pub mutable: bool,
     pub bracket: Bracket,
     pub inner: Type,
+    pub mutability: Option<Token![mut]>,
 }
 
 pub struct Array {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 018e71a..71da158 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,8 +4,8 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
-    Namespace, Pair, Receiver, Ref, ResolvableName, Signature, Slice, Struct, Ty1, Type, TypeAlias,
-    Var, Variant,
+    Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
+    TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -15,7 +15,7 @@ use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
-    TypePath, TypeReference, TypeSlice,
+    TypePath, TypeReference,
 };
 
 pub mod kw {
@@ -640,7 +640,6 @@ fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
         RustType::Path(ty) => parse_type_path(ty),
-        RustType::Slice(ty) => parse_type_slice(ty),
         RustType::Array(ty) => parse_type_array(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
         RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
@@ -649,6 +648,24 @@ fn parse_type(ty: &RustType) -> Result<Type> {
 }
 
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+    if let RustType::Slice(slice) = ty.elem.as_ref() {
+        let inner = parse_type(&slice.elem)?;
+        return match &inner {
+            Type::Ident(ident) if ident.rust == U8 => Ok(Type::SliceRefU8(Box::new(SliceRef {
+                ampersand: ty.and_token,
+                lifetime: ty.lifetime.clone(),
+                mutable: ty.mutability.is_some(),
+                bracket: slice.bracket_token,
+                inner,
+                mutability: ty.mutability,
+            }))),
+            _ => Err(Error::new_spanned(
+                ty,
+                "only &[u8] and &mut [u8] are supported so far, not other slice types",
+            )),
+        };
+    }
+
     let inner = parse_type(&ty.elem)?;
     let which = match &inner {
         Type::Ident(ident) if ident.rust == "str" => {
@@ -658,10 +675,6 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
                 Type::Str
             }
         }
-        Type::Slice(slice) => match &slice.inner {
-            Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
-            _ => Type::Ref,
-        },
         _ => Type::Ref,
     };
     Ok(which(Box::new(Ref {
@@ -742,14 +755,6 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
-fn parse_type_slice(ty: &TypeSlice) -> Result<Type> {
-    let inner = parse_type(&ty.elem)?;
-    Ok(Type::Slice(Box::new(Slice {
-        bracket: ty.bracket_token,
-        inner,
-    })))
-}
-
 fn parse_type_array(ty: &TypeArray) -> Result<Type> {
     let inner = parse_type(&ty.elem)?;
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 30a63d8..7b64a2d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
     Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
-    Signature, Slice, Struct, Ty1, Type, TypeAlias, Var,
+    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -20,11 +20,11 @@ impl ToTokens for Type {
             Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
                 ty.to_tokens(tokens)
             }
-            Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens),
-            Type::Slice(s) => s.to_tokens(tokens),
+            Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
+            Type::SliceRefU8(r) => r.to_tokens(tokens),
         }
     }
 }
@@ -69,20 +69,23 @@ impl ToTokens for Ref {
     }
 }
 
-impl ToTokens for Array {
+impl ToTokens for SliceRef {
     fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.ampersand.to_tokens(tokens);
+        self.lifetime.to_tokens(tokens);
+        self.mutability.to_tokens(tokens);
         self.bracket.surround(tokens, |tokens| {
             self.inner.to_tokens(tokens);
-            self.semi_token.to_tokens(tokens);
-            self.len_token.to_tokens(tokens);
         });
     }
 }
 
-impl ToTokens for Slice {
+impl ToTokens for Array {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.bracket.surround(tokens, |tokens| {
             self.inner.to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+            self.len_token.to_tokens(tokens);
         });
     }
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index d59bce0..746370c 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -48,7 +48,6 @@ impl<'a> Types<'a> {
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
-                Type::Slice(s) => visit(all, &s.inner),
                 Type::Array(a) => visit(all, &a.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {

From 73b7264eb0cea5e3ba2b30674e49d478cd00cb0a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 01:44:10 +0000
Subject: [PATCH 1557/2232] Generalize Type::SliceRefU8 to Type::SliceRef


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index d9e20da..0757146 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -167,7 +167,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
-            Type::SliceRefU8(_) => {
+            Type::SliceRef(_) => {
                 out.include.cstdint = true;
                 out.builtin.rust_slice = true;
             }
@@ -435,7 +435,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.rust_str_repr = true;
             write!(out, "::rust::impl<::rust::Str>::repr(");
         }
-        Some(ty @ Type::SliceRefU8(_)) if !indirect_return => {
+        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
             write!(out, "::rust::impl<");
             write_type(out, ty);
@@ -475,7 +475,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
-        } else if let Type::SliceRefU8(slice) = &arg.ty {
+        } else if let Type::SliceRef(slice) = &arg.ty {
             write_type(out, &arg.ty);
             write!(out, "(static_cast<");
             if slice.mutability.is_none() {
@@ -493,7 +493,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -694,7 +694,7 @@ fn write_rust_function_shim_impl(
                 out.builtin.rust_str_new_unchecked = true;
                 write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
             }
-            Type::SliceRefU8(_) => {
+            Type::SliceRef(_) => {
                 out.builtin.rust_slice_new = true;
                 write!(out, "::rust::impl<");
                 write_type(out, ret);
@@ -722,7 +722,7 @@ fn write_rust_function_shim_impl(
                 out.builtin.rust_str_repr = true;
                 write!(out, "::rust::impl<::rust::Str>::repr(");
             }
-            Type::SliceRefU8(_) => {
+            Type::SliceRef(_) => {
                 out.builtin.rust_slice_repr = true;
                 write!(out, "::rust::impl<");
                 write_type(out, &arg.ty);
@@ -735,7 +735,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"),
+            Type::Str(_) | Type::SliceRef(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -757,8 +757,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) = ret
-            {
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
                 write!(out, ")");
             }
         }
@@ -811,7 +810,7 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) {
     write_indirect_return_type(out, ty);
     match ty {
         Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {}
-        Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "),
+        Type::Str(_) | Type::SliceRef(_) => write!(out, " "),
         _ => write_space_after_type(out, ty),
     }
 }
@@ -829,7 +828,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) => {
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
@@ -844,7 +843,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) | Type::SliceRefU8(_) => {
+        Type::Str(_) | Type::SliceRef(_) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
@@ -892,7 +891,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRefU8(ty) => {
+        Type::SliceRef(ty) => {
             write!(out, "::rust::Slice<");
             if ty.mutability.is_none() {
                 write!(out, "const ");
@@ -956,7 +955,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::Str(_)
         | Type::CxxVector(_)
         | Type::RustVec(_)
-        | Type::SliceRefU8(_)
+        | Type::SliceRef(_)
         | Type::Fn(_)
         | Type::Array(_) => write!(out, " "),
         Type::Ref(_) => {}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9bfdecb..ccca8b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -330,7 +330,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 _ => quote!(#var),
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
-            Type::SliceRefU8(ty) => match ty.mutable {
+            Type::SliceRef(ty) => match ty.mutable {
                 false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
                 true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
             },
@@ -426,7 +426,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRefU8(ty) => match ty.mutable {
+                Type::SliceRef(ty) => match ty.mutable {
                     false => quote!(#call.as_slice()),
                     true => quote!(#call.as_mut_slice()),
                 },
@@ -616,7 +616,7 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRefU8(ty) => match ty.mutable {
+            Type::SliceRef(ty) => match ty.mutable {
                 false => quote!(#ident.as_slice()),
                 true => quote!(#ident.as_mut_slice()),
             },
@@ -663,7 +663,7 @@ fn expand_rust_function_shim_impl(
             _ => None,
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
-        Type::SliceRefU8(ty) => match ty.mutable {
+        Type::SliceRef(ty) => match ty.mutable {
             false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
             true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
         },
@@ -1107,7 +1107,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
             }
         }
         Type::Str(_) => quote!(::cxx::private::RustStr),
-        Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
+        Type::SliceRef(_) => quote!(::cxx::private::RustSliceU8),
         _ => quote!(#ty),
     }
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 968f28b..431aeee 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -36,7 +36,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
-            Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
+            Type::Str(_) | Type::Void(_) | Type::SliceRef(_) => {}
         }
     }
 
@@ -179,7 +179,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
     let supported = match &ty.inner {
-        Type::Str(_) | Type::SliceRefU8(_) => false,
+        Type::Str(_) | Type::SliceRef(_) => false,
         element => !is_unsized(cx, element),
     };
 
@@ -422,7 +422,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         | Type::UniquePtr(_)
         | Type::Ref(_)
         | Type::Str(_)
-        | Type::SliceRefU8(_) => false,
+        | Type::SliceRef(_) => false,
     }
 }
 
@@ -492,7 +492,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
-        Type::SliceRefU8(ty) => match ty.mutable {
+        Type::SliceRef(ty) => match ty.mutable {
             false => "&[u8]".to_owned(),
             true => "&mut [u8]".to_owned(),
         },
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 36cf3cd..4de3c29 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -50,7 +50,7 @@ impl Hash for Type {
             Type::RustVec(t) => t.hash(state),
             Type::CxxVector(t) => t.hash(state),
             Type::Fn(t) => t.hash(state),
-            Type::SliceRefU8(t) => t.hash(state),
+            Type::SliceRef(t) => t.hash(state),
             Type::Array(t) => t.hash(state),
             Type::Void(_) => {}
         }
@@ -70,7 +70,7 @@ impl PartialEq for Type {
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
             (Type::CxxVector(lhs), Type::CxxVector(rhs)) => lhs == rhs,
             (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs,
-            (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs,
+            (Type::SliceRef(lhs), Type::SliceRef(rhs)) => lhs == rhs,
             (Type::Void(_), Type::Void(_)) => true,
             (_, _) => false,
         }
diff --git a/syntax/improper.rs b/syntax/improper.rs
index 95cf4af..e0e5154 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -27,7 +27,7 @@ impl<'a> Types<'a> {
             | Type::Str(_)
             | Type::Fn(_)
             | Type::Void(_)
-            | Type::SliceRefU8(_) => Definite(true),
+            | Type::SliceRef(_) => Definite(true),
             Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c3c24ff..69b77bc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -164,7 +164,7 @@ pub enum Type {
     CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
     Void(Span),
-    SliceRefU8(Box<SliceRef>),
+    SliceRef(Box<SliceRef>),
     Array(Box<Array>),
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 71da158..25b17fd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -651,7 +651,7 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     if let RustType::Slice(slice) = ty.elem.as_ref() {
         let inner = parse_type(&slice.elem)?;
         return match &inner {
-            Type::Ident(ident) if ident.rust == U8 => Ok(Type::SliceRefU8(Box::new(SliceRef {
+            Type::Ident(ident) if ident.rust == U8 => Ok(Type::SliceRef(Box::new(SliceRef {
                 ampersand: ty.and_token,
                 lifetime: ty.lifetime.clone(),
                 mutable: ty.mutability.is_some(),
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7b64a2d..8ce7ed9 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -24,7 +24,7 @@ impl ToTokens for Type {
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
-            Type::SliceRefU8(r) => r.to_tokens(tokens),
+            Type::SliceRef(r) => r.to_tokens(tokens),
         }
     }
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index 746370c..8983273 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -42,7 +42,7 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRef(_) => {}
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
                 | Type::CxxVector(ty)

From 69db81496c97adb72f30d3b35f40755b75860c4a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 01:49:40 +0000
Subject: [PATCH 1558/2232] Move slice validation to type checker


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 431aeee..0dbd45e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    Struct, Ty1, Type, Types,
+    SliceRef, Struct, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -36,7 +36,8 @@ fn do_typecheck(cx: &mut Check) {
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
-            Type::Str(_) | Type::Void(_) | Type::SliceRef(_) => {}
+            Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
+            Type::Str(_) | Type::Void(_) => {}
         }
     }
 
@@ -177,6 +178,16 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     cx.error(ty, "unsupported reference type");
 }
 
+fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
+    match &ty.inner {
+        Type::Ident(ident) if ident.rust == U8 => {}
+        _ => cx.error(
+            ty,
+            "only &[u8] and &mut [u8] are supported so far, not other slice types",
+        ),
+    }
+}
+
 fn check_type_array(cx: &mut Check, ty: &Array) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRef(_) => false,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 25b17fd..f1a330c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -650,20 +650,14 @@ fn parse_type(ty: &RustType) -> Result<Type> {
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     if let RustType::Slice(slice) = ty.elem.as_ref() {
         let inner = parse_type(&slice.elem)?;
-        return match &inner {
-            Type::Ident(ident) if ident.rust == U8 => Ok(Type::SliceRef(Box::new(SliceRef {
-                ampersand: ty.and_token,
-                lifetime: ty.lifetime.clone(),
-                mutable: ty.mutability.is_some(),
-                bracket: slice.bracket_token,
-                inner,
-                mutability: ty.mutability,
-            }))),
-            _ => Err(Error::new_spanned(
-                ty,
-                "only &[u8] and &mut [u8] are supported so far, not other slice types",
-            )),
-        };
+        return Ok(Type::SliceRef(Box::new(SliceRef {
+            ampersand: ty.and_token,
+            lifetime: ty.lifetime.clone(),
+            mutable: ty.mutability.is_some(),
+            bracket: slice.bracket_token,
+            inner,
+            mutability: ty.mutability,
+        })));
     }
 
     let inner = parse_type(&ty.elem)?;

From 85ef67a70fdb2112ab2b007ffe1630391ff4ab33 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 01:51:35 +0000
Subject: [PATCH 1559/2232] Match the user's mut on slice error


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0dbd45e..960c569 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -181,10 +181,14 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     match &ty.inner {
         Type::Ident(ident) if ident.rust == U8 => {}
-        _ => cx.error(
-            ty,
-            "only &[u8] and &mut [u8] are supported so far, not other slice types",
-        ),
+        _ => {
+            let mutable = if ty.mutable { "mut " } else { "" };
+            let msg = format!(
+                "only &{}[u8] is supported so far, not other slice types",
+                mutable,
+            );
+            cx.error(ty, msg);
+        }
     }
 }
 

From 5515a9e820dfca9601c519f6f14cabe2ff3e43a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 03:34:42 +0000
Subject: [PATCH 1560/2232] Generalize SliceRef codegen to non-u8 element type


---

diff --git a/README.md b/README.md
index 49bd43c..746e466 100644
--- a/README.md
+++ b/README.md
@@ -322,8 +322,8 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 4da7d73..106a258 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -33,8 +33,8 @@ public:
 
 ### Restrictions:
 
-Only T=u8 i.e. rust::Slice\<const uint8\_t\> and rust::Slice\<uint8\_t\> are
-currently implemented. Support for arbitrary T is coming.
+T must not be an opaque Rust type or opaque C++ type. Support for opaque Rust
+types in slices is coming.
 
 Allowed as function argument or return value. Not supported in shared structs.
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0757146..1aa128f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -167,10 +167,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
-            Type::SliceRef(_) => {
-                out.include.cstdint = true;
-                out.builtin.rust_slice = true;
-            }
+            Type::SliceRef(_) => out.builtin.rust_slice = true,
             Type::Array(_) => out.include.array = true,
             Type::Ref(_) | Type::Void(_) => {}
         }
@@ -481,7 +478,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             if slice.mutability.is_none() {
                 write!(out, "const ");
             }
-            write!(out, "uint8_t *>({0}.ptr), {0}.len)", arg.ident);
+            write_type_space(out, &slice.inner);
+            write!(out, "*>({0}.ptr), {0}.len)", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -891,12 +889,13 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRef(ty) => {
+        Type::SliceRef(slice) => {
             write!(out, "::rust::Slice<");
-            if ty.mutability.is_none() {
+            if slice.mutability.is_none() {
                 write!(out, "const ");
             }
-            write!(out, "uint8_t>");
+            write_type(out, &slice.inner);
+            write!(out, ">");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 064d51f..1e939a5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -121,7 +121,7 @@ public:
 private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
-  // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
+  // cxx::rust_slice::RustSlice which matches this layout.
   T *ptr;
   size_t len;
 };
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ccca8b5..c735483 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -331,8 +331,8 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
             Type::SliceRef(ty) => match ty.mutable {
-                false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
-                true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
+                false => quote!(::cxx::private::RustSlice::from_ref(#var)),
+                true => quote!(::cxx::private::RustSlice::from_mut(#var)),
             },
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
@@ -426,10 +426,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRef(ty) => match ty.mutable {
-                    false => quote!(#call.as_slice()),
-                    true => quote!(#call.as_mut_slice()),
-                },
+                Type::SliceRef(slice) => {
+                    let inner = &slice.inner;
+                    match slice.mutable {
+                        false => quote!(#call.as_slice::<#inner>()),
+                        true => quote!(#call.as_mut_slice::<#inner>()),
+                    }
+                }
                 _ => call,
             },
         };
@@ -616,10 +619,13 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRef(ty) => match ty.mutable {
-                false => quote!(#ident.as_slice()),
-                true => quote!(#ident.as_mut_slice()),
-            },
+            Type::SliceRef(slice) => {
+                let inner = &slice.inner;
+                match slice.mutable {
+                    false => quote!(#ident.as_slice::<#inner>()),
+                    true => quote!(#ident.as_mut_slice::<#inner>()),
+                }
+            }
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -664,8 +670,8 @@ fn expand_rust_function_shim_impl(
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
         Type::SliceRef(ty) => match ty.mutable {
-            false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
-            true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
+            false => Some(quote!(::cxx::private::RustSlice::from_ref)),
+            true => Some(quote!(::cxx::private::RustSlice::from_mut)),
         },
         _ => None,
     });
@@ -1107,7 +1113,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
             }
         }
         Type::Str(_) => quote!(::cxx::private::RustStr),
-        Type::SliceRef(_) => quote!(::cxx::private::RustSliceU8),
+        Type::SliceRef(_) => quote!(::cxx::private::RustSlice),
         _ => quote!(#ty),
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index e971b50..a803d55 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -331,8 +331,8 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-//! <tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -398,7 +398,7 @@ mod extern_type;
 mod function;
 mod opaque;
 mod result;
-mod rust_sliceu8;
+mod rust_slice;
 mod rust_str;
 mod rust_string;
 mod rust_type;
@@ -442,7 +442,7 @@ pub mod private {
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
-    pub use crate::rust_sliceu8::RustSliceU8;
+    pub use crate::rust_slice::RustSlice;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::rust_type::RustType;
diff --git a/src/rust_slice.rs b/src/rust_slice.rs
new file mode 100644
index 0000000..8a5e74b
--- /dev/null
+++ b/src/rust_slice.rs
@@ -0,0 +1,40 @@
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
+
+// Not necessarily ABI compatible with &[T]. Codegen performs the translation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct RustSlice {
+    pub(crate) ptr: NonNull<()>,
+    pub(crate) len: usize,
+}
+
+impl RustSlice {
+    pub fn from_ref<T>(s: &[T]) -> Self {
+        RustSlice {
+            ptr: NonNull::from(s).cast::<()>(),
+            len: s.len(),
+        }
+    }
+
+    pub fn from_mut<T>(s: &mut [T]) -> Self {
+        RustSlice {
+            len: s.len(),
+            ptr: NonNull::from(s).cast::<()>(),
+        }
+    }
+
+    pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
+        slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), self.len)
+    }
+
+    pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
+        slice::from_raw_parts_mut(self.ptr.as_ptr().cast::<T>(), self.len)
+    }
+}
+
+const_assert_eq!(
+    mem::size_of::<Option<RustSlice>>(),
+    mem::size_of::<RustSlice>(),
+);
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
deleted file mode 100644
index e14f988..0000000
--- a/src/rust_sliceu8.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use core::mem;
-use core::ptr::NonNull;
-use core::slice;
-
-// Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct RustSliceU8 {
-    pub(crate) ptr: NonNull<u8>,
-    pub(crate) len: usize,
-}
-
-impl RustSliceU8 {
-    pub fn from_ref(s: &[u8]) -> Self {
-        RustSliceU8 {
-            ptr: NonNull::from(s).cast::<u8>(),
-            len: s.len(),
-        }
-    }
-
-    pub fn from_mut(s: &mut [u8]) -> Self {
-        RustSliceU8 {
-            len: s.len(),
-            ptr: NonNull::from(s).cast::<u8>(),
-        }
-    }
-
-    pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
-        slice::from_raw_parts(self.ptr.as_ptr(), self.len)
-    }
-
-    pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [u8] {
-        slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
-    }
-}
-
-const_assert_eq!(
-    mem::size_of::<Option<RustSliceU8>>(),
-    mem::size_of::<RustSliceU8>(),
-);
diff --git a/syntax/check.rs b/syntax/check.rs
index 960c569..f5e8e00 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -179,16 +179,22 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
-    match &ty.inner {
-        Type::Ident(ident) if ident.rust == U8 => {}
-        _ => {
-            let mutable = if ty.mutable { "mut " } else { "" };
-            let msg = format!(
-                "only &{}[u8] is supported so far, not other slice types",
-                mutable,
-            );
-            cx.error(ty, msg);
+    let supported = match &ty.inner {
+        Type::Str(_) | Type::SliceRef(_) => false,
+        element => !is_unsized(cx, element),
+    };
+
+    if !supported {
+        let mutable = if ty.mutable { "mut " } else { "" };
+        let mut msg = format!("unsupported &{}[T] element type", mutable);
+        if let Type::Ident(ident) = &ty.inner {
+            if cx.types.rust.contains(&ident.rust) {
+                msg += ": opaque Rust type is not supported yet";
+            } else if is_opaque_cxx(cx, &ident.rust) {
+                msg += ": opaque C++ type is not supported yet";
+            }
         }
+        cx.error(ty, msg);
     }
 }
 
@@ -507,10 +513,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
-        Type::SliceRef(ty) => match ty.mutable {
-            false => "&[u8]".to_owned(),
-            true => "&mut [u8]".to_owned(),
-        },
+        Type::SliceRef(_) => "slice".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
         Type::Array(_) => "array".to_owned(),
diff --git a/syntax/types.rs b/syntax/types.rs
index 8983273..8c628b3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -42,13 +42,14 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRef(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Array(a) => visit(all, &a.inner),
+                Type::SliceRef(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2d7544a..5ea7584 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -111,6 +111,7 @@ pub mod ffi {
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
         fn c_take_sliceu8(s: &[u8]);
+        fn c_take_slice_shared(s: &[Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 38942e1..4ba48bf 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -250,6 +250,12 @@ void c_take_sliceu8(rust::Slice<const uint8_t> s) {
   }
 }
 
+void c_take_slice_shared(rust::Slice<const Shared> s) {
+  if (s.size() == 2 && s.data()->z == 2020 && (s.data() + 1)->z == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6c288d7..3a4c3cb 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -115,6 +115,7 @@ void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<const uint8_t> s);
+void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 3bd41d1..98fbf45 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -117,6 +117,10 @@ fn test_c_take() {
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
+    check!(ffi::c_take_slice_shared(&[
+        ffi::Shared { z: 2020 },
+        ffi::Shared { z: 2021 },
+    ]));
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()
diff --git a/tests/ui/slice_unsupported.rs b/tests/ui/slice_unsupported.rs
new file mode 100644
index 0000000..7a148dd
--- /dev/null
+++ b/tests/ui/slice_unsupported.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Opaque;
+
+        fn f(_: &mut [Opaque]);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/slice_unsupported.stderr b/tests/ui/slice_unsupported.stderr
new file mode 100644
index 0000000..787076f
--- /dev/null
+++ b/tests/ui/slice_unsupported.stderr
@@ -0,0 +1,5 @@
+error: unsupported &mut [T] element type: opaque C++ type is not supported yet
+ --> $DIR/slice_unsupported.rs:6:17
+  |
+6 |         fn f(_: &mut [Opaque]);
+  |                 ^^^^^^^^^^^^^

From 2923080472872805a7336ce5a051e0ab2b16f2a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 03:41:06 +0000
Subject: [PATCH 1561/2232] Merge pull request #514 from dtolnay/slice


Generalize SliceRef codegen to non-u8 element type
---

diff --git a/README.md b/README.md
index 49bd43c..746e466 100644
--- a/README.md
+++ b/README.md
@@ -322,8 +322,8 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
+<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 4da7d73..106a258 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -33,8 +33,8 @@ public:
 
 ### Restrictions:
 
-Only T=u8 i.e. rust::Slice\<const uint8\_t\> and rust::Slice\<uint8\_t\> are
-currently implemented. Support for arbitrary T is coming.
+T must not be an opaque Rust type or opaque C++ type. Support for opaque Rust
+types in slices is coming.
 
 Allowed as function argument or return value. Not supported in shared structs.
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0757146..1aa128f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -167,10 +167,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
-            Type::SliceRef(_) => {
-                out.include.cstdint = true;
-                out.builtin.rust_slice = true;
-            }
+            Type::SliceRef(_) => out.builtin.rust_slice = true,
             Type::Array(_) => out.include.array = true,
             Type::Ref(_) | Type::Void(_) => {}
         }
@@ -481,7 +478,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             if slice.mutability.is_none() {
                 write!(out, "const ");
             }
-            write!(out, "uint8_t *>({0}.ptr), {0}.len)", arg.ident);
+            write_type_space(out, &slice.inner);
+            write!(out, "*>({0}.ptr), {0}.len)", arg.ident);
         } else if out.types.needs_indirect_abi(&arg.ty) {
             out.include.utility = true;
             write!(out, "::std::move(*{})", arg.ident);
@@ -891,12 +889,13 @@ fn write_type(out: &mut OutFile, ty: &Type) {
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
-        Type::SliceRef(ty) => {
+        Type::SliceRef(slice) => {
             write!(out, "::rust::Slice<");
-            if ty.mutability.is_none() {
+            if slice.mutability.is_none() {
                 write!(out, "const ");
             }
-            write!(out, "uint8_t>");
+            write_type(out, &slice.inner);
+            write!(out, ">");
         }
         Type::Fn(f) => {
             write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
diff --git a/include/cxx.h b/include/cxx.h
index 064d51f..1e939a5 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -121,7 +121,7 @@ public:
 private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
-  // cxx::rust_sliceu8::RustSliceU8 which matches this layout.
+  // cxx::rust_slice::RustSlice which matches this layout.
   T *ptr;
   size_t len;
 };
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ccca8b5..c735483 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -331,8 +331,8 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
             },
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
             Type::SliceRef(ty) => match ty.mutable {
-                false => quote!(::cxx::private::RustSliceU8::from_ref(#var)),
-                true => quote!(::cxx::private::RustSliceU8::from_mut(#var)),
+                false => quote!(::cxx::private::RustSlice::from_ref(#var)),
+                true => quote!(::cxx::private::RustSlice::from_mut(#var)),
             },
             ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
             _ => quote!(#var),
@@ -426,10 +426,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     _ => call,
                 },
                 Type::Str(_) => quote!(#call.as_str()),
-                Type::SliceRef(ty) => match ty.mutable {
-                    false => quote!(#call.as_slice()),
-                    true => quote!(#call.as_mut_slice()),
-                },
+                Type::SliceRef(slice) => {
+                    let inner = &slice.inner;
+                    match slice.mutable {
+                        false => quote!(#call.as_slice::<#inner>()),
+                        true => quote!(#call.as_mut_slice::<#inner>()),
+                    }
+                }
                 _ => call,
             },
         };
@@ -616,10 +619,13 @@ fn expand_rust_function_shim_impl(
                 _ => quote!(#ident),
             },
             Type::Str(_) => quote!(#ident.as_str()),
-            Type::SliceRef(ty) => match ty.mutable {
-                false => quote!(#ident.as_slice()),
-                true => quote!(#ident.as_mut_slice()),
-            },
+            Type::SliceRef(slice) => {
+                let inner = &slice.inner;
+                match slice.mutable {
+                    false => quote!(#ident.as_slice::<#inner>()),
+                    true => quote!(#ident.as_mut_slice::<#inner>()),
+                }
+            }
             ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)),
             _ => quote!(#ident),
         }
@@ -664,8 +670,8 @@ fn expand_rust_function_shim_impl(
         },
         Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
         Type::SliceRef(ty) => match ty.mutable {
-            false => Some(quote!(::cxx::private::RustSliceU8::from_ref)),
-            true => Some(quote!(::cxx::private::RustSliceU8::from_mut)),
+            false => Some(quote!(::cxx::private::RustSlice::from_ref)),
+            true => Some(quote!(::cxx::private::RustSlice::from_mut)),
         },
         _ => None,
     });
@@ -1107,7 +1113,7 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
             }
         }
         Type::Str(_) => quote!(::cxx::private::RustStr),
-        Type::SliceRef(_) => quote!(::cxx::private::RustSliceU8),
+        Type::SliceRef(_) => quote!(::cxx::private::RustSlice),
         _ => quote!(#ty),
     }
 }
diff --git a/src/lib.rs b/src/lib.rs
index e971b50..a803d55 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -331,8 +331,8 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td>&amp;[u8]</td><td>rust::Slice&lt;const uint8_t&gt;</td><td><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-//! <tr><td>&amp;mut [u8]</td><td>rust::Slice&lt;uint8_t&gt;</td><td><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
+//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
@@ -398,7 +398,7 @@ mod extern_type;
 mod function;
 mod opaque;
 mod result;
-mod rust_sliceu8;
+mod rust_slice;
 mod rust_str;
 mod rust_string;
 mod rust_type;
@@ -442,7 +442,7 @@ pub mod private {
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
     pub use crate::result::{r#try, Result};
-    pub use crate::rust_sliceu8::RustSliceU8;
+    pub use crate::rust_slice::RustSlice;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
     pub use crate::rust_type::RustType;
diff --git a/src/rust_slice.rs b/src/rust_slice.rs
new file mode 100644
index 0000000..8a5e74b
--- /dev/null
+++ b/src/rust_slice.rs
@@ -0,0 +1,40 @@
+use core::mem;
+use core::ptr::NonNull;
+use core::slice;
+
+// Not necessarily ABI compatible with &[T]. Codegen performs the translation.
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct RustSlice {
+    pub(crate) ptr: NonNull<()>,
+    pub(crate) len: usize,
+}
+
+impl RustSlice {
+    pub fn from_ref<T>(s: &[T]) -> Self {
+        RustSlice {
+            ptr: NonNull::from(s).cast::<()>(),
+            len: s.len(),
+        }
+    }
+
+    pub fn from_mut<T>(s: &mut [T]) -> Self {
+        RustSlice {
+            len: s.len(),
+            ptr: NonNull::from(s).cast::<()>(),
+        }
+    }
+
+    pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
+        slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), self.len)
+    }
+
+    pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
+        slice::from_raw_parts_mut(self.ptr.as_ptr().cast::<T>(), self.len)
+    }
+}
+
+const_assert_eq!(
+    mem::size_of::<Option<RustSlice>>(),
+    mem::size_of::<RustSlice>(),
+);
diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs
deleted file mode 100644
index e14f988..0000000
--- a/src/rust_sliceu8.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use core::mem;
-use core::ptr::NonNull;
-use core::slice;
-
-// Not necessarily ABI compatible with &[u8]. Codegen performs the translation.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct RustSliceU8 {
-    pub(crate) ptr: NonNull<u8>,
-    pub(crate) len: usize,
-}
-
-impl RustSliceU8 {
-    pub fn from_ref(s: &[u8]) -> Self {
-        RustSliceU8 {
-            ptr: NonNull::from(s).cast::<u8>(),
-            len: s.len(),
-        }
-    }
-
-    pub fn from_mut(s: &mut [u8]) -> Self {
-        RustSliceU8 {
-            len: s.len(),
-            ptr: NonNull::from(s).cast::<u8>(),
-        }
-    }
-
-    pub unsafe fn as_slice<'a>(self) -> &'a [u8] {
-        slice::from_raw_parts(self.ptr.as_ptr(), self.len)
-    }
-
-    pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [u8] {
-        slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
-    }
-}
-
-const_assert_eq!(
-    mem::size_of::<Option<RustSliceU8>>(),
-    mem::size_of::<RustSliceU8>(),
-);
diff --git a/syntax/check.rs b/syntax/check.rs
index 960c569..f5e8e00 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -179,16 +179,22 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
-    match &ty.inner {
-        Type::Ident(ident) if ident.rust == U8 => {}
-        _ => {
-            let mutable = if ty.mutable { "mut " } else { "" };
-            let msg = format!(
-                "only &{}[u8] is supported so far, not other slice types",
-                mutable,
-            );
-            cx.error(ty, msg);
+    let supported = match &ty.inner {
+        Type::Str(_) | Type::SliceRef(_) => false,
+        element => !is_unsized(cx, element),
+    };
+
+    if !supported {
+        let mutable = if ty.mutable { "mut " } else { "" };
+        let mut msg = format!("unsupported &{}[T] element type", mutable);
+        if let Type::Ident(ident) = &ty.inner {
+            if cx.types.rust.contains(&ident.rust) {
+                msg += ": opaque Rust type is not supported yet";
+            } else if is_opaque_cxx(cx, &ident.rust) {
+                msg += ": opaque C++ type is not supported yet";
+            }
         }
+        cx.error(ty, msg);
     }
 }
 
@@ -507,10 +513,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
-        Type::SliceRef(ty) => match ty.mutable {
-            false => "&[u8]".to_owned(),
-            true => "&mut [u8]".to_owned(),
-        },
+        Type::SliceRef(_) => "slice".to_owned(),
         Type::Fn(_) => "function pointer".to_owned(),
         Type::Void(_) => "()".to_owned(),
         Type::Array(_) => "array".to_owned(),
diff --git a/syntax/types.rs b/syntax/types.rs
index 8983273..8c628b3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -42,13 +42,14 @@ impl<'a> Types<'a> {
         fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRef(_) => {}
+                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
                 Type::Array(a) => visit(all, &a.inner),
+                Type::SliceRef(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
                     if let Some(ret) = &f.ret {
                         visit(all, ret);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2d7544a..5ea7584 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -111,6 +111,7 @@ pub mod ffi {
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
         fn c_take_sliceu8(s: &[u8]);
+        fn c_take_slice_shared(s: &[Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 38942e1..4ba48bf 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -250,6 +250,12 @@ void c_take_sliceu8(rust::Slice<const uint8_t> s) {
   }
 }
 
+void c_take_slice_shared(rust::Slice<const Shared> s) {
+  if (s.size() == 2 && s.data()->z == 2020 && (s.data() + 1)->z == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 6c288d7..3a4c3cb 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -115,6 +115,7 @@ void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_sliceu8(rust::Slice<const uint8_t> s);
+void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 3bd41d1..98fbf45 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -117,6 +117,10 @@ fn test_c_take() {
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
     check!(ffi::c_take_sliceu8(b"2020"));
+    check!(ffi::c_take_slice_shared(&[
+        ffi::Shared { z: 2020 },
+        ffi::Shared { z: 2021 },
+    ]));
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()
diff --git a/tests/ui/slice_unsupported.rs b/tests/ui/slice_unsupported.rs
new file mode 100644
index 0000000..7a148dd
--- /dev/null
+++ b/tests/ui/slice_unsupported.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Opaque;
+
+        fn f(_: &mut [Opaque]);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/slice_unsupported.stderr b/tests/ui/slice_unsupported.stderr
new file mode 100644
index 0000000..787076f
--- /dev/null
+++ b/tests/ui/slice_unsupported.stderr
@@ -0,0 +1,5 @@
+error: unsupported &mut [T] element type: opaque C++ type is not supported yet
+ --> $DIR/slice_unsupported.rs:6:17
+  |
+6 |         fn f(_: &mut [Opaque]);
+  |                 ^^^^^^^^^^^^^

From 248215e2060e9d6d7814943bb1b1165741cc0d28 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 03:41:16 +0000
Subject: [PATCH 1562/2232] Replace uint8_t with char for byte-based computations in Vec iterator


---

diff --git a/include/cxx.h b/include/cxx.h
index 1e939a5..5c2f179 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -604,14 +604,14 @@ T *Vec<T>::iterator::operator->() const noexcept {
 
 template <typename T>
 typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
-  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return *this;
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
   auto ret = iterator(*this);
-  this->pos = static_cast<uint8_t *>(this->pos) + this->stride;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return ret;
 }
 
@@ -636,7 +636,7 @@ typename Vec<T>::iterator Vec<T>::begin() noexcept {
 template <typename T>
 typename Vec<T>::iterator Vec<T>::end() noexcept {
   iterator it = this->begin();
-  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
   return it;
 }
 
@@ -661,7 +661,7 @@ typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
   const_iterator it = this->cbegin();
-  it.pos = static_cast<uint8_t *>(it.pos) + it.stride * this->size();
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
   return it;
 }
 

From b3873dcd10d21ac89e0f4e47fe4ebf1b6d80e6a6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:04:09 +0000
Subject: [PATCH 1563/2232] Support c_char type


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1aa128f..60936a0 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -159,7 +159,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 Some(Isize) => out.builtin.rust_isize = true,
                 Some(CxxString) => out.include.string = true,
                 Some(RustString) => out.builtin.rust_string = true,
-                Some(Bool) | Some(F32) | Some(F64) | None => {}
+                Some(Bool) | Some(Char) | Some(F32) | Some(F64) | None => {}
             },
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
@@ -924,6 +924,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
 fn write_atom(out: &mut OutFile, atom: Atom) {
     match atom {
         Bool => write!(out, "bool"),
+        Char => write!(out, "char"),
         U8 => write!(out, "uint8_t"),
         U16 => write!(out, "uint16_t"),
         U32 => write!(out, "uint32_t"),
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 7d0ef6b..d4ad78f 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -5,6 +5,7 @@ use std::fmt::{self, Display};
 #[derive(Copy, Clone, PartialEq)]
 pub enum Atom {
     Bool,
+    Char, // C char, not Rust char
     U8,
     U16,
     U32,
@@ -30,6 +31,7 @@ impl Atom {
         use self::Atom::*;
         match s {
             "bool" => Some(Bool),
+            "c_char" => Some(Char),
             "u8" => Some(U8),
             "u16" => Some(U16),
             "u32" => Some(U32),
@@ -60,6 +62,7 @@ impl AsRef<str> for Atom {
         use self::Atom::*;
         match self {
             Bool => "bool",
+            Char => "c_char",
             U8 => "u8",
             U16 => "u16",
             U32 => "u32",
diff --git a/syntax/check.rs b/syntax/check.rs
index f5e8e00..cdf174c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -102,7 +102,7 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(RustString) => return,
-            Some(Bool) => { /* todo */ }
+            Some(Bool) | Some(Char) => { /* todo */ }
             Some(CxxString) => {}
         }
     }
@@ -140,6 +140,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(CxxString) => return,
+            Some(Char) => { /* todo */ }
             Some(Bool) | Some(RustString) => {}
         }
     }
@@ -503,6 +504,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
                 "opaque Rust type".to_owned()
             } else if Atom::from(&ident.rust) == Some(CxxString) {
                 "C++ string".to_owned()
+            } else if Atom::from(&ident.rust) == Some(Char) {
+                "C char".to_owned()
             } else {
                 ident.rust.to_string()
             }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 8ce7ed9..d450f73 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -11,7 +11,10 @@ impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
             Type::Ident(ident) => {
-                if ident.rust == CxxString {
+                if ident.rust == Char {
+                    let span = ident.rust.span();
+                    tokens.extend(quote_spanned!(span=> ::std::os::raw::));
+                } else if ident.rust == CxxString {
                     let span = ident.rust.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }

From 36bd61615d1058147bba9cb691ab5cc3db8314a5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:13:05 +0000
Subject: [PATCH 1564/2232] Update tests to use c_char where appropriate


---

diff --git a/tests/BUCK b/tests/BUCK
index 4bdcc46..b6699e2 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -12,6 +12,7 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
+        "ffi/cast.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
diff --git a/tests/BUILD b/tests/BUILD
index b255a3c..9194ca4 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -15,6 +15,7 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
+        "ffi/cast.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
diff --git a/tests/ffi/cast.rs b/tests/ffi/cast.rs
new file mode 100644
index 0000000..30ecb6a
--- /dev/null
+++ b/tests/ffi/cast.rs
@@ -0,0 +1,14 @@
+use std::os::raw::c_char;
+use std::slice;
+
+pub fn c_char_to_unsigned(slice: &[c_char]) -> &[u8] {
+    let ptr = slice.as_ptr().cast::<u8>();
+    let len = slice.len();
+    unsafe { slice::from_raw_parts(ptr, len) }
+}
+
+pub fn unsigned_to_c_char(slice: &[u8]) -> &[c_char] {
+    let ptr = slice.as_ptr().cast::<c_char>();
+    let len = slice.len();
+    unsafe { slice::from_raw_parts(ptr, len) }
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5ea7584..41f129a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -6,10 +6,12 @@
     clippy::unnecessary_wraps
 )]
 
+pub mod cast;
 pub mod module;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
+use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
@@ -81,7 +83,7 @@ pub mod ffi {
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
-        fn c_return_sliceu8(shared: &Shared) -> &[u8];
+        fn c_return_slice_char(shared: &Shared) -> &[c_char];
         fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
@@ -110,7 +112,7 @@ pub mod ffi {
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
-        fn c_take_sliceu8(s: &[u8]);
+        fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
@@ -214,7 +216,7 @@ pub mod ffi {
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
-        fn r_take_sliceu8(s: &[u8]);
+        fn r_take_slice_char(s: &[c_char]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_ref_vector(v: &CxxVector<u8>);
@@ -472,8 +474,9 @@ fn r_take_rust_string(s: String) {
     assert_eq!(s, "2020");
 }
 
-fn r_take_sliceu8(s: &[u8]) {
+fn r_take_slice_char(s: &[c_char]) {
     assert_eq!(s.len(), 5);
+    let s = cast::c_char_to_unsigned(s);
     assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4ba48bf..7cd84b8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -75,10 +75,9 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
-rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
+rust::Slice<const char> c_return_slice_char(const Shared &shared) {
   (void)shared;
-  return rust::Slice<const uint8_t>(
-      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
+  return rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA));
 }
 
 rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
@@ -243,9 +242,8 @@ void c_take_str(rust::Str s) {
   }
 }
 
-void c_take_sliceu8(rust::Slice<const uint8_t> s) {
-  if (std::string(reinterpret_cast<const char *>(s.data()), s.size()) ==
-      "2020") {
+void c_take_slice_char(rust::Slice<const char> s) {
+  if (std::string(s.data(), s.size()) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
@@ -626,8 +624,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<const uint8_t>(
-      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA)));
+  r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3a4c3cb..5791983 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -83,7 +83,7 @@ const size_t &c_return_ns_ref(const ::A::AShared &shared);
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
-rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<const char> c_return_slice_char(const Shared &shared);
 rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
@@ -114,7 +114,7 @@ void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
-void c_take_sliceu8(rust::Slice<const uint8_t> s);
+void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
diff --git a/tests/test.rs b/tests/test.rs
index 98fbf45..b4c39fa 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,7 +1,7 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
 use cxx_test_suite::module::ffi2;
-use cxx_test_suite::{ffi, R};
+use cxx_test_suite::{cast, ffi, R};
 use std::cell::Cell;
 use std::ffi::CStr;
 
@@ -41,7 +41,10 @@ fn test_c_return() {
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
     assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
-    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
+    assert_eq!(
+        b"2020\0",
+        cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)),
+    );
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
     assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len());
@@ -116,7 +119,7 @@ fn test_c_take() {
     check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
-    check!(ffi::c_take_sliceu8(b"2020"));
+    check!(ffi::c_take_slice_char(cast::unsigned_to_c_char(b"2020")));
     check!(ffi::c_take_slice_shared(&[
         ffi::Shared { z: 2020 },
         ffi::Shared { z: 2021 },

From 93e71d0b461ebcdd2702b68a0e5a58482d24df5e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:16:52 +0000
Subject: [PATCH 1565/2232] Support Vec<c_char>


---

diff --git a/src/cxx.cc b/src/cxx.cc
index cd72d82..2a8ba97 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -379,6 +379,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
+  MACRO(char, char)                                                            \
   MACRO(string, rust::String)
 
 extern "C" {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index df6dec6..4f4b6ff 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -3,6 +3,7 @@ use crate::rust_vec::RustVec;
 use alloc::vec::Vec;
 use core::mem;
 use core::ptr;
+use std::os::raw::c_char;
 
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
@@ -74,4 +75,5 @@ rust_vec_shims_for_primitive!(i64);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
 
+rust_vec_shims!("char", c_char);
 rust_vec_shims!("string", RustString);
diff --git a/syntax/check.rs b/syntax/check.rs
index cdf174c..85db248 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -99,10 +99,10 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
         }
 
         match Atom::from(&ident.rust) {
-            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
-            | Some(RustString) => return,
-            Some(Bool) | Some(Char) => { /* todo */ }
+            None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+            | Some(F64) | Some(RustString) => return,
+            Some(Bool) => { /* todo */ }
             Some(CxxString) => {}
         }
     }

From 71c7b45e4fba0cba26122b9ae7616c3e88492dc8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:22:58 +0000
Subject: [PATCH 1566/2232] Merge pull request #515 from dtolnay/c_char


Support c_char type
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1aa128f..60936a0 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -159,7 +159,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
                 Some(Isize) => out.builtin.rust_isize = true,
                 Some(CxxString) => out.include.string = true,
                 Some(RustString) => out.builtin.rust_string = true,
-                Some(Bool) | Some(F32) | Some(F64) | None => {}
+                Some(Bool) | Some(Char) | Some(F32) | Some(F64) | None => {}
             },
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
@@ -924,6 +924,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
 fn write_atom(out: &mut OutFile, atom: Atom) {
     match atom {
         Bool => write!(out, "bool"),
+        Char => write!(out, "char"),
         U8 => write!(out, "uint8_t"),
         U16 => write!(out, "uint16_t"),
         U32 => write!(out, "uint32_t"),
diff --git a/src/cxx.cc b/src/cxx.cc
index cd72d82..2a8ba97 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -379,6 +379,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
+  MACRO(char, char)                                                            \
   MACRO(string, rust::String)
 
 extern "C" {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index df6dec6..4f4b6ff 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -3,6 +3,7 @@ use crate::rust_vec::RustVec;
 use alloc::vec::Vec;
 use core::mem;
 use core::ptr;
+use std::os::raw::c_char;
 
 macro_rules! rust_vec_shims {
     ($segment:expr, $ty:ty) => {
@@ -74,4 +75,5 @@ rust_vec_shims_for_primitive!(i64);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
 
+rust_vec_shims!("char", c_char);
 rust_vec_shims!("string", RustString);
diff --git a/syntax/atom.rs b/syntax/atom.rs
index 7d0ef6b..d4ad78f 100644
--- a/syntax/atom.rs
+++ b/syntax/atom.rs
@@ -5,6 +5,7 @@ use std::fmt::{self, Display};
 #[derive(Copy, Clone, PartialEq)]
 pub enum Atom {
     Bool,
+    Char, // C char, not Rust char
     U8,
     U16,
     U32,
@@ -30,6 +31,7 @@ impl Atom {
         use self::Atom::*;
         match s {
             "bool" => Some(Bool),
+            "c_char" => Some(Char),
             "u8" => Some(U8),
             "u16" => Some(U16),
             "u32" => Some(U32),
@@ -60,6 +62,7 @@ impl AsRef<str> for Atom {
         use self::Atom::*;
         match self {
             Bool => "bool",
+            Char => "c_char",
             U8 => "u8",
             U16 => "u16",
             U32 => "u32",
diff --git a/syntax/check.rs b/syntax/check.rs
index f5e8e00..85db248 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -99,9 +99,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
         }
 
         match Atom::from(&ident.rust) {
-            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
-            | Some(RustString) => return,
+            None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+            | Some(F64) | Some(RustString) => return,
             Some(Bool) => { /* todo */ }
             Some(CxxString) => {}
         }
@@ -140,6 +140,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
             | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
             | Some(CxxString) => return,
+            Some(Char) => { /* todo */ }
             Some(Bool) | Some(RustString) => {}
         }
     }
@@ -503,6 +504,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
                 "opaque Rust type".to_owned()
             } else if Atom::from(&ident.rust) == Some(CxxString) {
                 "C++ string".to_owned()
+            } else if Atom::from(&ident.rust) == Some(Char) {
+                "C char".to_owned()
             } else {
                 ident.rust.to_string()
             }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 8ce7ed9..d450f73 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -11,7 +11,10 @@ impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
             Type::Ident(ident) => {
-                if ident.rust == CxxString {
+                if ident.rust == Char {
+                    let span = ident.rust.span();
+                    tokens.extend(quote_spanned!(span=> ::std::os::raw::));
+                } else if ident.rust == CxxString {
                     let span = ident.rust.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }
diff --git a/tests/BUCK b/tests/BUCK
index 4bdcc46..b6699e2 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -12,6 +12,7 @@ rust_test(
 rust_library(
     name = "ffi",
     srcs = [
+        "ffi/cast.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
diff --git a/tests/BUILD b/tests/BUILD
index b255a3c..9194ca4 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -15,6 +15,7 @@ rust_test(
 rust_library(
     name = "cxx_test_suite",
     srcs = [
+        "ffi/cast.rs",
         "ffi/lib.rs",
         "ffi/module.rs",
     ],
diff --git a/tests/ffi/cast.rs b/tests/ffi/cast.rs
new file mode 100644
index 0000000..30ecb6a
--- /dev/null
+++ b/tests/ffi/cast.rs
@@ -0,0 +1,14 @@
+use std::os::raw::c_char;
+use std::slice;
+
+pub fn c_char_to_unsigned(slice: &[c_char]) -> &[u8] {
+    let ptr = slice.as_ptr().cast::<u8>();
+    let len = slice.len();
+    unsafe { slice::from_raw_parts(ptr, len) }
+}
+
+pub fn unsigned_to_c_char(slice: &[u8]) -> &[c_char] {
+    let ptr = slice.as_ptr().cast::<c_char>();
+    let len = slice.len();
+    unsafe { slice::from_raw_parts(ptr, len) }
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5ea7584..41f129a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -6,10 +6,12 @@
     clippy::unnecessary_wraps
 )]
 
+pub mod cast;
 pub mod module;
 
 use cxx::{CxxString, CxxVector, UniquePtr};
 use std::fmt::{self, Display};
+use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
@@ -81,7 +83,7 @@ pub mod ffi {
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
-        fn c_return_sliceu8(shared: &Shared) -> &[u8];
+        fn c_return_slice_char(shared: &Shared) -> &[c_char];
         fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
         fn c_return_rust_string() -> String;
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
@@ -110,7 +112,7 @@ pub mod ffi {
         fn c_take_ref_r(r: &R);
         fn c_take_ref_c(c: &C);
         fn c_take_str(s: &str);
-        fn c_take_sliceu8(s: &[u8]);
+        fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
@@ -214,7 +216,7 @@ pub mod ffi {
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
-        fn r_take_sliceu8(s: &[u8]);
+        fn r_take_slice_char(s: &[c_char]);
         fn r_take_rust_string(s: String);
         fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn r_take_ref_vector(v: &CxxVector<u8>);
@@ -472,8 +474,9 @@ fn r_take_rust_string(s: String) {
     assert_eq!(s, "2020");
 }
 
-fn r_take_sliceu8(s: &[u8]) {
+fn r_take_slice_char(s: &[c_char]) {
     assert_eq!(s.len(), 5);
+    let s = cast::c_char_to_unsigned(s);
     assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 4ba48bf..7cd84b8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -75,10 +75,9 @@ rust::Str c_return_str(const Shared &shared) {
   return "2020";
 }
 
-rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared) {
+rust::Slice<const char> c_return_slice_char(const Shared &shared) {
   (void)shared;
-  return rust::Slice<const uint8_t>(
-      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA));
+  return rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA));
 }
 
 rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice) {
@@ -243,9 +242,8 @@ void c_take_str(rust::Str s) {
   }
 }
 
-void c_take_sliceu8(rust::Slice<const uint8_t> s) {
-  if (std::string(reinterpret_cast<const char *>(s.data()), s.size()) ==
-      "2020") {
+void c_take_slice_char(rust::Slice<const char> s) {
+  if (std::string(s.data(), s.size()) == "2020") {
     cxx_test_suite_set_correct();
   }
 }
@@ -626,8 +624,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
-  r_take_sliceu8(rust::Slice<const uint8_t>(
-      reinterpret_cast<const uint8_t *>(SLICE_DATA), sizeof(SLICE_DATA)));
+  r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
   r_take_rust_string(rust::String("2020"));
   r_take_unique_ptr_string(
       std::unique_ptr<std::string>(new std::string("2020")));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3a4c3cb..5791983 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -83,7 +83,7 @@ const size_t &c_return_ns_ref(const ::A::AShared &shared);
 const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
 size_t &c_return_mut(Shared &shared);
 rust::Str c_return_str(const Shared &shared);
-rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
+rust::Slice<const char> c_return_slice_char(const Shared &shared);
 rust::Slice<uint8_t> c_return_mutsliceu8(rust::Slice<uint8_t> slice);
 rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
@@ -114,7 +114,7 @@ void c_take_ref_r(const R &r);
 void c_take_ref_c(const C &c);
 void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
-void c_take_sliceu8(rust::Slice<const uint8_t> s);
+void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
diff --git a/tests/test.rs b/tests/test.rs
index 98fbf45..b4c39fa 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,7 +1,7 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
 use cxx_test_suite::module::ffi2;
-use cxx_test_suite::{ffi, R};
+use cxx_test_suite::{cast, ffi, R};
 use std::cell::Cell;
 use std::ffi::CStr;
 
@@ -41,7 +41,10 @@ fn test_c_return() {
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
     assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared));
     assert_eq!("2020", ffi::c_return_str(&shared));
-    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
+    assert_eq!(
+        b"2020\0",
+        cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)),
+    );
     assert_eq!("2020", ffi::c_return_rust_string());
     assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
     assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len());
@@ -116,7 +119,7 @@ fn test_c_take() {
     check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns));
     check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr));
     check!(ffi::c_take_str("2020"));
-    check!(ffi::c_take_sliceu8(b"2020"));
+    check!(ffi::c_take_slice_char(cast::unsigned_to_c_char(b"2020")));
     check!(ffi::c_take_slice_shared(&[
         ffi::Shared { z: 2020 },
         ffi::Shared { z: 2021 },

From 7b16a39a02a9b6d84c2195567d9093d953f0ea30 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:23:14 +0000
Subject: [PATCH 1567/2232] Consider T alignment for empty rust::Slice


---

diff --git a/include/cxx.h b/include/cxx.h
index 5c2f179..9c415b7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -390,7 +390,7 @@ inline size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(this)), len(0) {}
+Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(alignof(T))), len(0) {}
 
 template <typename T>
 Slice<T>::Slice(T *s, size_t count) noexcept : ptr(s), len(count) {}

From ac6cb54e3b193a45881cfc6526e1b5b3b4a6e8b5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:27:32 +0000
Subject: [PATCH 1568/2232] Add iterator for rust::Slice


---

diff --git a/include/cxx.h b/include/cxx.h
index 9c415b7..ed571f0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -118,6 +118,10 @@ public:
   Slice(const Slice<T> &) noexcept = default;
   ~Slice() noexcept = default;
 
+  class iterator;
+  iterator begin() const noexcept;
+  iterator end() const noexcept;
+
 private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
@@ -125,6 +129,27 @@ private:
   T *ptr;
   size_t len;
 };
+
+template <typename T>
+class Slice<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
+
+private:
+  friend class Slice;
+  T *pos;
+};
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
@@ -409,6 +434,53 @@ template <typename T>
 size_t Slice<T>::length() const noexcept {
   return this->len;
 }
+
+template <typename T>
+T &Slice<T>::iterator::operator*() const noexcept {
+  return *this->pos;
+}
+
+template <typename T>
+T *Slice<T>::iterator::operator->() const noexcept {
+  return this->pos;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
+  ++this->pos;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
+  auto ret = iterator(*this);
+  ++this->pos;
+  return ret;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator==(const iterator &other) const noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::begin() const noexcept {
+  iterator it;
+  it.pos = this->ptr;
+  return it;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::end() const noexcept {
+  iterator it = this->begin();
+  it.pos += this->len;
+  return it;
+}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX

From e0b03286ebe5a2291291dd6aae5afbbfc66b64dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:32:03 +0000
Subject: [PATCH 1569/2232] Show slice iterator in book


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 106a258..4153170 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -26,6 +26,25 @@ public:
   T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  class iterator;
+  iterator begin() const noexcept;
+  iterator end() const noexcept;
+};
+
+template <typename T>
+class Slice<T>::iterator final {
+public:
+  using value_type = T;
+  using pointer = T *;
+  using reference = T &;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
 };
 #
 # } // namespace rust

From 474f188828d9cad3094ea9272d855e1d456caf51 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:38:08 +0000
Subject: [PATCH 1570/2232] Merge pull request #516 from dtolnay/sliceiterator


Add iterator for rust::Slice
---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 106a258..4153170 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -26,6 +26,25 @@ public:
   T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  class iterator;
+  iterator begin() const noexcept;
+  iterator end() const noexcept;
+};
+
+template <typename T>
+class Slice<T>::iterator final {
+public:
+  using value_type = T;
+  using pointer = T *;
+  using reference = T &;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
 };
 #
 # } // namespace rust
diff --git a/include/cxx.h b/include/cxx.h
index 9c415b7..ed571f0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -118,6 +118,10 @@ public:
   Slice(const Slice<T> &) noexcept = default;
   ~Slice() noexcept = default;
 
+  class iterator;
+  iterator begin() const noexcept;
+  iterator end() const noexcept;
+
 private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
@@ -125,6 +129,27 @@ private:
   T *ptr;
   size_t len;
 };
+
+template <typename T>
+class Slice<T>::iterator final {
+public:
+  using difference_type = ptrdiff_t;
+  using value_type = T;
+  using pointer = typename std::add_pointer<T>::type;
+  using reference = typename std::add_lvalue_reference<T>::type;
+  using iterator_category = std::forward_iterator_tag;
+
+  T &operator*() const noexcept;
+  T *operator->() const noexcept;
+  iterator &operator++() noexcept;
+  iterator operator++(int) noexcept;
+  bool operator==(const iterator &) const noexcept;
+  bool operator!=(const iterator &) const noexcept;
+
+private:
+  friend class Slice;
+  T *pos;
+};
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
@@ -409,6 +434,53 @@ template <typename T>
 size_t Slice<T>::length() const noexcept {
   return this->len;
 }
+
+template <typename T>
+T &Slice<T>::iterator::operator*() const noexcept {
+  return *this->pos;
+}
+
+template <typename T>
+T *Slice<T>::iterator::operator->() const noexcept {
+  return this->pos;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
+  ++this->pos;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
+  auto ret = iterator(*this);
+  ++this->pos;
+  return ret;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator==(const iterator &other) const noexcept {
+  return this->pos == other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {
+  return this->pos != other.pos;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::begin() const noexcept {
+  iterator it;
+  it.pos = this->ptr;
+  return it;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::end() const noexcept {
+  iterator it = this->begin();
+  it.pos += this->len;
+  return it;
+}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX

From 450d8cdd72eba38fa081bdf194ab97482f2ce14d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:38:16 +0000
Subject: [PATCH 1571/2232] Add Slice dependency on type_traits for is_const, add_pointer


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 621d88c..8e6744e 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -59,6 +59,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_slice {
+        include.type_traits = true;
         builtin.friend_impl = true;
     }
 

From d1df4c76212b07f3097122cb07781094a63ad9a0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:38:16 +0000
Subject: [PATCH 1572/2232] Include <iterator> for input_iterator_tag


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8e6744e..8741e2d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -59,6 +59,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_slice {
+        include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
     }
@@ -71,6 +72,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     if builtin.rust_vec {
         include.array = true;
+        include.iterator = true;
         include.new = true;
         include.type_traits = true;
         include.utility = true;
diff --git a/gen/src/include.rs b/gen/src/include.rs
index cf718da..b47cc23 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -26,6 +26,7 @@ pub struct Includes<'a> {
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
+    pub iterator: bool,
     pub memory: bool,
     pub new: bool,
     pub string: bool,
@@ -81,6 +82,9 @@ pub(super) fn write(out: &mut OutFile) {
     if include.exception {
         writeln!(out, "#include <exception>");
     }
+    if include.iterator {
+        writeln!(out, "#include <iterator>");
+    }
     if include.memory {
         writeln!(out, "#include <memory>");
     }
diff --git a/include/cxx.h b/include/cxx.h
index ed571f0..5725be9 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -4,6 +4,7 @@
 #include <cstdint>
 #include <exception>
 #include <iosfwd>
+#include <iterator>
 #include <new>
 #include <stdexcept>
 #include <string>

From a829be62dfc0f500af7f66d792372f220ba1dda4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:41:12 +0000
Subject: [PATCH 1573/2232] Exhaustive match to ensure no missing prints for includes


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index b47cc23..accaaee 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -67,43 +67,61 @@ pub(super) fn write(out: &mut OutFile) {
         }
     }
 
-    if include.array {
+    let Includes {
+        custom: _,
+        array,
+        cstddef,
+        cstdint,
+        cstring,
+        exception,
+        iterator,
+        memory,
+        new,
+        string,
+        type_traits,
+        utility,
+        vector,
+        basetsd,
+        content: _,
+    } = *include;
+
+    if array {
         writeln!(out, "#include <array>");
     }
-    if include.cstddef {
+    if cstddef {
         writeln!(out, "#include <cstddef>");
     }
-    if include.cstdint {
+    if cstdint {
         writeln!(out, "#include <cstdint>");
     }
-    if include.cstring {
+    if cstring {
         writeln!(out, "#include <cstring>");
     }
-    if include.exception {
+    if exception {
         writeln!(out, "#include <exception>");
     }
-    if include.iterator {
+    if iterator {
         writeln!(out, "#include <iterator>");
     }
-    if include.memory {
+    if memory {
         writeln!(out, "#include <memory>");
     }
-    if include.new {
+    if new {
         writeln!(out, "#include <new>");
     }
-    if include.string {
+    if string {
         writeln!(out, "#include <string>");
     }
-    if include.type_traits {
+    if type_traits {
         writeln!(out, "#include <type_traits>");
     }
-    if include.utility {
+    if utility {
         writeln!(out, "#include <utility>");
     }
-    if include.vector {
+    if vector {
         writeln!(out, "#include <vector>");
     }
-    if include.basetsd {
+    if basetsd {
         writeln!(out, "#if defined(_WIN32)");
         writeln!(out, "#include <basetsd.h>");
         writeln!(out, "#endif");

From 01ef29a15c5597b420bae1a939dda4599d87ac20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 04:44:31 +0000
Subject: [PATCH 1574/2232] Hide full iterator API from rendered documentation


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 4153170..4f9d74a 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -31,21 +31,21 @@ public:
   iterator begin() const noexcept;
   iterator end() const noexcept;
 };
-
-template <typename T>
-class Slice<T>::iterator final {
-public:
-  using value_type = T;
-  using pointer = T *;
-  using reference = T &;
-
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
-  iterator &operator++() noexcept;
-  iterator operator++(int) noexcept;
-  bool operator==(const iterator &) const noexcept;
-  bool operator!=(const iterator &) const noexcept;
-};
+#
+# template <typename T>
+# class Slice<T>::iterator final {
+# public:
+#   using value_type = T;
+#   using pointer = T *;
+#   using reference = T &;
+#
+#   T &operator*() const noexcept;
+#   T *operator->() const noexcept;
+#   iterator &operator++() noexcept;
+#   iterator operator++(int) noexcept;
+#   bool operator==(const iterator &) const noexcept;
+#   bool operator!=(const iterator &) const noexcept;
+# };
 #
 # } // namespace rust
 ```
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index e1767e5..5820001 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -49,36 +49,36 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 };
-
-template <typename T>
-class Vec<T>::iterator final {
-public:
-  using value_type = T;
-  using pointer = T *;
-  using reference = T &;
-
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
-  iterator &operator++() noexcept;
-  iterator operator++(int) noexcept;
-  bool operator==(const iterator &) const noexcept;
-  bool operator!=(const iterator &) const noexcept;
-};
-
-template <typename T>
-class Vec<T>::const_iterator final {
-public:
-  using value_type = const T;
-  using pointer = const T *;
-  using reference = const T &;
-
-  const T &operator*() const noexcept;
-  const T *operator->() const noexcept;
-  const_iterator &operator++() noexcept;
-  const_iterator operator++(int) noexcept;
-  bool operator==(const const_iterator &) const noexcept;
-  bool operator!=(const const_iterator &) const noexcept;
-};
+#
+# template <typename T>
+# class Vec<T>::iterator final {
+# public:
+#   using value_type = T;
+#   using pointer = T *;
+#   using reference = T &;
+#
+#   T &operator*() const noexcept;
+#   T *operator->() const noexcept;
+#   iterator &operator++() noexcept;
+#   iterator operator++(int) noexcept;
+#   bool operator==(const iterator &) const noexcept;
+#   bool operator!=(const iterator &) const noexcept;
+# };
+#
+# template <typename T>
+# class Vec<T>::const_iterator final {
+# public:
+#   using value_type = const T;
+#   using pointer = const T *;
+#   using reference = const T &;
+#
+#   const T &operator*() const noexcept;
+#   const T *operator->() const noexcept;
+#   const_iterator &operator++() noexcept;
+#   const_iterator operator++(int) noexcept;
+#   bool operator==(const const_iterator &) const noexcept;
+#   bool operator!=(const const_iterator &) const noexcept;
+# };
 #
 # } // namespace rust
 ```

From ff7f5fb8cc33c4ee70098e5a602aace8f47692f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 05:06:33 +0000
Subject: [PATCH 1575/2232] Add String and Str iterators


---

diff --git a/.clang-tidy b/.clang-tidy
index 9962a64..1d45713 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -8,6 +8,7 @@ Checks:
   -cppcoreguidelines-macro-usage,
   -cppcoreguidelines-owning-memory,
   -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+  -cppcoreguidelines-pro-bounds-pointer-arithmetic,
   -cppcoreguidelines-pro-type-const-cast,
   -cppcoreguidelines-pro-type-member-init,
   -cppcoreguidelines-pro-type-reinterpret-cast,
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 7d7d6e8..b0a99b4 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -29,6 +29,13 @@ public:
   const char *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  using iterator = const char *;
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index ac44fb2..47a2b96 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -32,6 +32,16 @@ public:
   const char *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  using iterator = char *;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const String &);
diff --git a/include/cxx.h b/include/cxx.h
index 5725be9..8624233 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -48,6 +48,16 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  using iterator = char *;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   String(unsafe_bitcopy_t, const String &) noexcept;
 
@@ -78,6 +88,13 @@ public:
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
 
+  using iterator = const char *;
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+
 private:
   friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
diff --git a/src/cxx.cc b/src/cxx.cc
index 2a8ba97..ef5db8f 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -122,6 +122,24 @@ size_t String::size() const noexcept { return cxxbridge1$string$len(this); }
 
 size_t String::length() const noexcept { return cxxbridge1$string$len(this); }
 
+String::iterator String::begin() noexcept {
+  return const_cast<char *>(this->data());
+}
+
+String::iterator String::end() noexcept {
+  return const_cast<char *>(this->data()) + this->size();
+}
+
+String::const_iterator String::begin() const noexcept { return this->cbegin(); }
+
+String::const_iterator String::end() const noexcept { return this->cend(); }
+
+String::const_iterator String::cbegin() const noexcept { return this->data(); }
+
+String::const_iterator String::cend() const noexcept {
+  return this->data() + this->size();
+}
+
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
 
@@ -158,6 +176,14 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
+
+Str::const_iterator Str::end() const noexcept { return this->cend(); }
+
+Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
+
+Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From 01a5df6a32f87b0b522c7c7d5182943c2b3ff354 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 05:11:34 +0000
Subject: [PATCH 1576/2232] Merge pull request #517 from dtolnay/striterator


Add String and Str iterators
---

diff --git a/.clang-tidy b/.clang-tidy
index 9962a64..1d45713 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -8,6 +8,7 @@ Checks:
   -cppcoreguidelines-macro-usage,
   -cppcoreguidelines-owning-memory,
   -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+  -cppcoreguidelines-pro-bounds-pointer-arithmetic,
   -cppcoreguidelines-pro-type-const-cast,
   -cppcoreguidelines-pro-type-member-init,
   -cppcoreguidelines-pro-type-reinterpret-cast,
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 7d7d6e8..b0a99b4 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -29,6 +29,13 @@ public:
   const char *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  using iterator = const char *;
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index ac44fb2..47a2b96 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -32,6 +32,16 @@ public:
   const char *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+
+  using iterator = char *;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const String &);
diff --git a/include/cxx.h b/include/cxx.h
index 5725be9..8624233 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -48,6 +48,16 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  using iterator = char *;
+  iterator begin() noexcept;
+  iterator end() noexcept;
+
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   String(unsafe_bitcopy_t, const String &) noexcept;
 
@@ -78,6 +88,13 @@ public:
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
 
+  using iterator = const char *;
+  using const_iterator = const char *;
+  const_iterator begin() const noexcept;
+  const_iterator end() const noexcept;
+  const_iterator cbegin() const noexcept;
+  const_iterator cend() const noexcept;
+
 private:
   friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
diff --git a/src/cxx.cc b/src/cxx.cc
index 2a8ba97..ef5db8f 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -122,6 +122,24 @@ size_t String::size() const noexcept { return cxxbridge1$string$len(this); }
 
 size_t String::length() const noexcept { return cxxbridge1$string$len(this); }
 
+String::iterator String::begin() noexcept {
+  return const_cast<char *>(this->data());
+}
+
+String::iterator String::end() noexcept {
+  return const_cast<char *>(this->data()) + this->size();
+}
+
+String::const_iterator String::begin() const noexcept { return this->cbegin(); }
+
+String::const_iterator String::end() const noexcept { return this->cend(); }
+
+String::const_iterator String::cbegin() const noexcept { return this->data(); }
+
+String::const_iterator String::cend() const noexcept {
+  return this->data() + this->size();
+}
+
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
 
@@ -158,6 +176,14 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
+
+Str::const_iterator Str::end() const noexcept { return this->cend(); }
+
+Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
+
+Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From 1c534cfdc13793312486ca334919a114c9b9ac4a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 26 2020 05:30:22 +0000
Subject: [PATCH 1577/2232] Release 1.0.5


---

diff --git a/Cargo.toml b/Cargo.toml
index 9d66514..63ad1e2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.4" # remember to update html_root_url
+version = "1.0.5" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.4", path = "macro" }
+cxxbridge-macro = { version = "=1.0.5", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.4", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.5", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.4", path = "gen/build" }
+cxx-build = { version = "=1.0.5", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 28c1fe0..a3fba7f 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.4"
+version = "1.0.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 9364808..618b41a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.4"
+version = "1.0.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index c817cbb..1af6ae3 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.4"
+version = "1.0.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 6245519..67aee37 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.4"
+version = "0.7.5"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1a581f2..b843879 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.4"
+version = "1.0.5"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index a803d55..09a5259 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.4")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.5")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 14a5bb9..94bbb0f 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.4"
+version = "1.0.5"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.4"
+version = "1.0.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.4"
+version = "0.7.5"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.4"
+version = "1.0.5"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.4"
+version = "1.0.5"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.4"
+version = "1.0.5"
 dependencies = [
  "cxx",
  "proc-macro2",

From 652cb50e3343129d72c97ab546d051576af65de9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:19:29 +0000
Subject: [PATCH 1578/2232] Add test of duplicate derive on struct


---

diff --git a/tests/ui/derive_duplicate.rs b/tests/ui/derive_duplicate.rs
new file mode 100644
index 0000000..3061f76
--- /dev/null
+++ b/tests/ui/derive_duplicate.rs
@@ -0,0 +1,9 @@
+#[cxx::bridge]
+mod ffi {
+    #[derive(Clone, Clone)]
+    struct Struct {
+        x: usize,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr
new file mode 100644
index 0000000..e0450e2
--- /dev/null
+++ b/tests/ui/derive_duplicate.stderr
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `ffi::Struct`:
+ --> $DIR/derive_duplicate.rs:1:1
+  |
+1 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  | |
+  | first implementation here
+  | conflicting implementation for `ffi::Struct`
+  |
+  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 4a0c53a7b0de7050634a5151491eb7b7ee68b642 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:19:33 +0000
Subject: [PATCH 1579/2232] Expand derives manually where allowed


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
deleted file mode 100644
index 1abc5da..0000000
--- a/macro/src/derive.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use crate::syntax::Derive;
-use proc_macro2::TokenStream;
-use quote::{quote, ToTokens};
-
-pub struct DeriveAttribute<'a>(pub &'a [Derive]);
-
-impl<'a> ToTokens for DeriveAttribute<'a> {
-    fn to_tokens(&self, tokens: &mut TokenStream) {
-        if !self.0.is_empty() {
-            let derives = self.0;
-            tokens.extend(quote!(#[derive(#(#derives),*)]));
-        }
-    }
-}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c735483..92551e6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,11 +1,10 @@
-use crate::derive::DeriveAttribute;
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
-    Struct, Type, TypeAlias, Types,
+    self, check, mangle, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName,
+    Signature, Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -127,7 +126,6 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 fn expand_struct(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let doc = &strct.doc;
-    let derives = DeriveAttribute(&strct.derives);
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         // This span on the pub makes "private type in public interface" errors
@@ -136,9 +134,8 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         quote!(#vis #field)
     });
 
-    quote! {
+    let mut expanded = quote! {
         #doc
-        #derives
         #[repr(C)]
         pub struct #ident {
             #(#fields,)*
@@ -148,7 +145,37 @@ fn expand_struct(strct: &Struct) -> TokenStream {
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
+    };
+
+    let is_copy = strct.derives.contains(&Derive::Copy);
+    for derive in &strct.derives {
+        match derive {
+            Derive::Copy => {
+                expanded.extend(quote! {
+                    impl ::std::marker::Copy for #ident {}
+                });
+            }
+            Derive::Clone => {
+                let body = if is_copy {
+                    quote!(*self)
+                } else {
+                    let fields = strct.fields.iter().map(|field| &field.ident);
+                    quote!(#ident {
+                        #(#fields: ::std::clone::Clone::clone(&self.#fields),)*
+                    })
+                };
+                expanded.extend(quote! {
+                    impl ::std::clone::Clone for #ident {
+                        fn clone(&self) -> Self {
+                            #body
+                        }
+                    }
+                });
+            }
+        }
     }
+
+    expanded
 }
 
 fn expand_enum(enm: &Enum) -> TokenStream {
@@ -166,7 +193,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 
     quote! {
         #doc
-        #[derive(Copy, Clone, PartialEq, Eq)]
+        #[derive(PartialEq, Eq)] // required to be derived in order to be usable in patterns
         #[repr(transparent)]
         pub struct #ident {
             pub repr: #repr,
@@ -181,6 +208,14 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
+
+        impl ::std::marker::Copy for #ident {}
+
+        impl ::std::clone::Clone for #ident {
+            fn clone(&self) -> Self {
+                *self
+            }
+        }
     }
 }
 
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 1de7e6c..6285451 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -10,7 +10,6 @@
 
 extern crate proc_macro;
 
-mod derive;
 mod expand;
 mod syntax;
 mod type_id;
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 435aa20..855e80f 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -15,12 +15,3 @@ impl Derive {
         }
     }
 }
-
-impl AsRef<str> for Derive {
-    fn as_ref(&self) -> &str {
-        match self {
-            Derive::Clone => "Clone",
-            Derive::Copy => "Copy",
-        }
-    }
-}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index d450f73..29899a9 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
-    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
+    SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -93,12 +93,6 @@ impl ToTokens for Array {
     }
 }
 
-impl ToTokens for Derive {
-    fn to_tokens(&self, tokens: &mut TokenStream) {
-        Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
-    }
-}
-
 impl ToTokens for Atom {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr
index e0450e2..0d5de2c 100644
--- a/tests/ui/derive_duplicate.stderr
+++ b/tests/ui/derive_duplicate.stderr
@@ -7,4 +7,4 @@ error[E0119]: conflicting implementations of trait `std::clone::Clone` for type 
   | first implementation here
   | conflicting implementation for `ffi::Struct`
   |
-  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From b247df1d268754ba5ebfa92796b4659156586b1a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:20:49 +0000
Subject: [PATCH 1580/2232] Preserve span on Derive trait impls


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 92551e6..5bac706 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,8 +3,8 @@ use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName,
-    Signature, Struct, Type, TypeAlias, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -147,15 +147,18 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         }
     };
 
-    let is_copy = strct.derives.contains(&Derive::Copy);
+    let is_copy = strct
+        .derives
+        .iter()
+        .any(|derive| derive.what == Trait::Copy);
     for derive in &strct.derives {
-        match derive {
-            Derive::Copy => {
-                expanded.extend(quote! {
+        match derive.what {
+            Trait::Copy => {
+                expanded.extend(quote_spanned! {derive.span=>
                     impl ::std::marker::Copy for #ident {}
                 });
             }
-            Derive::Clone => {
+            Trait::Clone => {
                 let body = if is_copy {
                     quote!(*self)
                 } else {
@@ -164,7 +167,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
                         #(#fields: ::std::clone::Clone::clone(&self.#fields),)*
                     })
                 };
-                expanded.extend(quote! {
+                expanded.extend(quote_spanned! {derive.span=>
                     impl ::std::clone::Clone for #ident {
                         fn clone(&self) -> Self {
                             #body
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 855e80f..501dd61 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -1,17 +1,31 @@
-use proc_macro2::Ident;
+use proc_macro2::{Ident, Span};
+
+#[derive(Copy, Clone)]
+pub struct Derive {
+    pub what: Trait,
+    pub span: Span,
+}
 
 #[derive(Copy, Clone, PartialEq)]
-pub enum Derive {
+pub enum Trait {
     Clone,
     Copy,
 }
 
 impl Derive {
     pub fn from(ident: &Ident) -> Option<Self> {
-        match ident.to_string().as_str() {
-            "Clone" => Some(Derive::Clone),
-            "Copy" => Some(Derive::Copy),
-            _ => None,
-        }
+        let what = match ident.to_string().as_str() {
+            "Clone" => Trait::Clone,
+            "Copy" => Trait::Copy,
+            _ => return None,
+        };
+        let span = ident.span();
+        Some(Derive { what, span })
+    }
+}
+
+impl PartialEq<Trait> for Derive {
+    fn eq(&self, other: &Trait) -> bool {
+        self.what == *other
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 69b77bc..17b290a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -33,7 +33,7 @@ use syn::token::{Brace, Bracket, Paren};
 use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
-pub use self::derive::Derive;
+pub use self::derive::{Derive, Trait};
 pub use self::doc::Doc;
 pub use self::parse::parse_items;
 pub use self::types::Types;
diff --git a/syntax/types.rs b/syntax/types.rs
index 8c628b3..5fe63ff 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,7 @@ use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
-    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+    toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Trait, Type,
     TypeAlias,
 };
 use proc_macro2::Ident;
@@ -261,7 +261,7 @@ impl<'a> Types<'a> {
 
     pub fn is_pod(&self, strct: &Struct) -> bool {
         for derive in &strct.derives {
-            if *derive == Derive::Copy {
+            if derive.what == Trait::Copy {
                 return true;
             }
         }
diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr
index 0d5de2c..4eefc24 100644
--- a/tests/ui/derive_duplicate.stderr
+++ b/tests/ui/derive_duplicate.stderr
@@ -1,10 +1,7 @@
 error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `ffi::Struct`:
- --> $DIR/derive_duplicate.rs:1:1
+ --> $DIR/derive_duplicate.rs:3:21
   |
-1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  | |
-  | first implementation here
-  | conflicting implementation for `ffi::Struct`
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+3 |     #[derive(Clone, Clone)]
+  |              -----  ^^^^^ conflicting implementation for `ffi::Struct`
+  |              |
+  |              first implementation here

From 4d73379753513d5ae6d98f936873d739f92e7d48 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:24:22 +0000
Subject: [PATCH 1581/2232] Add ui test of derives that fail due to field types


---

diff --git a/tests/ui/derive_nonclone.rs b/tests/ui/derive_nonclone.rs
new file mode 100644
index 0000000..5811028
--- /dev/null
+++ b/tests/ui/derive_nonclone.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    #[derive(Clone)]
+    struct TryClone {
+        other: Other,
+    }
+
+    struct Other {
+        x: usize,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/derive_nonclone.stderr b/tests/ui/derive_nonclone.stderr
new file mode 100644
index 0000000..f72c1e2
--- /dev/null
+++ b/tests/ui/derive_nonclone.stderr
@@ -0,0 +1,8 @@
+error[E0277]: the trait bound `ffi::Other: Clone` is not satisfied
+ --> $DIR/derive_nonclone.rs:1:1
+  |
+1 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `ffi::Other`
+  |
+  = note: required by `clone`
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/derive_noncopy.rs b/tests/ui/derive_noncopy.rs
new file mode 100644
index 0000000..ae705fd
--- /dev/null
+++ b/tests/ui/derive_noncopy.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    #[derive(Copy)]
+    struct TryCopy {
+        other: Other,
+    }
+
+    struct Other {
+        x: usize,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/derive_noncopy.stderr b/tests/ui/derive_noncopy.stderr
new file mode 100644
index 0000000..d641028
--- /dev/null
+++ b/tests/ui/derive_noncopy.stderr
@@ -0,0 +1,8 @@
+error[E0204]: the trait `Copy` may not be implemented for this type
+ --> $DIR/derive_noncopy.rs:3:14
+  |
+3 |     #[derive(Copy)]
+  |              ^^^^
+4 |     struct TryCopy {
+5 |         other: Other,
+  |         ------------ this field does not implement `Copy`

From f3b89fb23a9b97d10b76f974971f720bbf56583f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:32:30 +0000
Subject: [PATCH 1582/2232] Preserve span of fields in derived Clone impl


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 5bac706..4e59aad 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -163,8 +163,14 @@ fn expand_struct(strct: &Struct) -> TokenStream {
                     quote!(*self)
                 } else {
                     let fields = strct.fields.iter().map(|field| &field.ident);
-                    quote!(#ident {
-                        #(#fields: ::std::clone::Clone::clone(&self.#fields),)*
+                    let values = strct.fields.iter().map(|field| {
+                        let ident = &field.ident;
+                        let ty = field.ty.to_token_stream();
+                        let span = ty.into_iter().last().unwrap().span();
+                        quote_spanned!(span=> &self.#ident)
+                    });
+                    quote_spanned!(derive.span=> #ident {
+                        #(#fields: ::std::clone::Clone::clone(#values),)*
                     })
                 };
                 expanded.extend(quote_spanned! {derive.span=>
diff --git a/tests/ui/derive_nonclone.stderr b/tests/ui/derive_nonclone.stderr
index f72c1e2..04eae4f 100644
--- a/tests/ui/derive_nonclone.stderr
+++ b/tests/ui/derive_nonclone.stderr
@@ -1,8 +1,7 @@
 error[E0277]: the trait bound `ffi::Other: Clone` is not satisfied
- --> $DIR/derive_nonclone.rs:1:1
+ --> $DIR/derive_nonclone.rs:5:9
   |
-1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `ffi::Other`
+5 |         other: Other,
+  |         ^^^^^^^^^^^^ the trait `Clone` is not implemented for `ffi::Other`
   |
   = note: required by `clone`
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From d8ad9702707715a1de0975c780a0d106f0022ad1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:44:05 +0000
Subject: [PATCH 1583/2232] Extract derive implementations to module


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
new file mode 100644
index 0000000..7a1fbdb
--- /dev/null
+++ b/macro/src/derive.rs
@@ -0,0 +1,48 @@
+use crate::syntax::{Struct, Trait};
+use proc_macro2::TokenStream;
+use quote::{quote, quote_spanned, ToTokens};
+
+pub fn expand_struct(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let mut expanded = TokenStream::new();
+
+    let is_copy = strct
+        .derives
+        .iter()
+        .any(|derive| derive.what == Trait::Copy);
+
+    for derive in &strct.derives {
+        match derive.what {
+            Trait::Copy => {
+                expanded.extend(quote_spanned! {derive.span=>
+                    impl ::std::marker::Copy for #ident {}
+                });
+            }
+            Trait::Clone => {
+                let body = if is_copy {
+                    quote!(*self)
+                } else {
+                    let fields = strct.fields.iter().map(|field| &field.ident);
+                    let values = strct.fields.iter().map(|field| {
+                        let ident = &field.ident;
+                        let ty = field.ty.to_token_stream();
+                        let span = ty.into_iter().last().unwrap().span();
+                        quote_spanned!(span=> &self.#ident)
+                    });
+                    quote_spanned!(derive.span=> #ident {
+                        #(#fields: ::std::clone::Clone::clone(#values),)*
+                    })
+                };
+                expanded.extend(quote_spanned! {derive.span=>
+                    impl ::std::clone::Clone for #ident {
+                        fn clone(&self) -> Self {
+                            #body
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    expanded
+}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4e59aad..411f87e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,10 +1,11 @@
+use crate::derive;
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
-    Struct, Trait, Type, TypeAlias, Types,
+    Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -133,8 +134,9 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         let vis = Token![pub](field.ident.span());
         quote!(#vis #field)
     });
+    let derived_traits = derive::expand_struct(strct);
 
-    let mut expanded = quote! {
+    quote! {
         #doc
         #[repr(C)]
         pub struct #ident {
@@ -145,46 +147,9 @@ fn expand_struct(strct: &Struct) -> TokenStream {
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
-    };
 
-    let is_copy = strct
-        .derives
-        .iter()
-        .any(|derive| derive.what == Trait::Copy);
-    for derive in &strct.derives {
-        match derive.what {
-            Trait::Copy => {
-                expanded.extend(quote_spanned! {derive.span=>
-                    impl ::std::marker::Copy for #ident {}
-                });
-            }
-            Trait::Clone => {
-                let body = if is_copy {
-                    quote!(*self)
-                } else {
-                    let fields = strct.fields.iter().map(|field| &field.ident);
-                    let values = strct.fields.iter().map(|field| {
-                        let ident = &field.ident;
-                        let ty = field.ty.to_token_stream();
-                        let span = ty.into_iter().last().unwrap().span();
-                        quote_spanned!(span=> &self.#ident)
-                    });
-                    quote_spanned!(derive.span=> #ident {
-                        #(#fields: ::std::clone::Clone::clone(#values),)*
-                    })
-                };
-                expanded.extend(quote_spanned! {derive.span=>
-                    impl ::std::clone::Clone for #ident {
-                        fn clone(&self) -> Self {
-                            #body
-                        }
-                    }
-                });
-            }
-        }
+        #derived_traits
     }
-
-    expanded
 }
 
 fn expand_enum(enm: &Enum) -> TokenStream {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 6285451..1de7e6c 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -10,6 +10,7 @@
 
 extern crate proc_macro;
 
+mod derive;
 mod expand;
 mod syntax;
 mod type_id;

From 2c24e5cb8446b8ad9b63cfb44917d154eb84682d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:47:41 +0000
Subject: [PATCH 1584/2232] Refactor struct derive implementations


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 7a1fbdb..3010dc6 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -1,48 +1,57 @@
 use crate::syntax::{Struct, Trait};
-use proc_macro2::TokenStream;
+use proc_macro2::{Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
 pub fn expand_struct(strct: &Struct) -> TokenStream {
-    let ident = &strct.name.rust;
     let mut expanded = TokenStream::new();
 
+    for derive in &strct.derives {
+        let span = derive.span;
+        match derive.what {
+            Trait::Copy => expanded.extend(struct_copy(strct, span)),
+            Trait::Clone => expanded.extend(struct_clone(strct, span)),
+        }
+    }
+
+    expanded
+}
+
+fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::marker::Copy for #ident {}
+    }
+}
+
+fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+
     let is_copy = strct
         .derives
         .iter()
         .any(|derive| derive.what == Trait::Copy);
 
-    for derive in &strct.derives {
-        match derive.what {
-            Trait::Copy => {
-                expanded.extend(quote_spanned! {derive.span=>
-                    impl ::std::marker::Copy for #ident {}
-                });
-            }
-            Trait::Clone => {
-                let body = if is_copy {
-                    quote!(*self)
-                } else {
-                    let fields = strct.fields.iter().map(|field| &field.ident);
-                    let values = strct.fields.iter().map(|field| {
-                        let ident = &field.ident;
-                        let ty = field.ty.to_token_stream();
-                        let span = ty.into_iter().last().unwrap().span();
-                        quote_spanned!(span=> &self.#ident)
-                    });
-                    quote_spanned!(derive.span=> #ident {
-                        #(#fields: ::std::clone::Clone::clone(#values),)*
-                    })
-                };
-                expanded.extend(quote_spanned! {derive.span=>
-                    impl ::std::clone::Clone for #ident {
-                        fn clone(&self) -> Self {
-                            #body
-                        }
-                    }
-                });
+    let body = if is_copy {
+        quote!(*self)
+    } else {
+        let fields = strct.fields.iter().map(|field| &field.ident);
+        let values = strct.fields.iter().map(|field| {
+            let ident = &field.ident;
+            let ty = field.ty.to_token_stream();
+            let span = ty.into_iter().last().unwrap().span();
+            quote_spanned!(span=> &self.#ident)
+        });
+        quote_spanned!(span=> #ident {
+            #(#fields: ::std::clone::Clone::clone(#values),)*
+        })
+    };
+
+    quote_spanned! {span=>
+        impl ::std::clone::Clone for #ident {
+            fn clone(&self) -> Self {
+                #body
             }
         }
     }
-
-    expanded
 }

From 0521373464a450d2a05b191900cfabf90268e01e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 20:52:12 +0000
Subject: [PATCH 1585/2232] Refer to std derives by absolute path


This prevents hijacking if the caller's crate has a macro in
scope (via #[macro_use]) with the same name.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 411f87e..09373ff 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -164,10 +164,15 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
+    let derives = quote! {
+        // Required to be derived in order for the enum's "variants" to be
+        // usable in patterns.
+        #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
+    };
 
     quote! {
         #doc
-        #[derive(PartialEq, Eq)] // required to be derived in order to be usable in patterns
+        #derives
         #[repr(transparent)]
         pub struct #ident {
             pub repr: #repr,

From fbc466998907203b18cd8435a50e0655ccd8ad0a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 21:08:45 +0000
Subject: [PATCH 1586/2232] Handle derives on shared enums


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 3010dc6..8988012 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{Struct, Trait};
+use crate::syntax::{Enum, Struct, Trait};
 use proc_macro2::{Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
@@ -16,6 +16,36 @@ pub fn expand_struct(strct: &Struct) -> TokenStream {
     expanded
 }
 
+pub fn expand_enum(enm: &Enum) -> TokenStream {
+    let mut expanded = TokenStream::new();
+    let mut has_copy = false;
+    let mut has_clone = false;
+
+    for derive in &enm.derives {
+        let span = derive.span;
+        match derive.what {
+            Trait::Copy => {
+                expanded.extend(enum_copy(enm, span));
+                has_copy = true;
+            }
+            Trait::Clone => {
+                expanded.extend(enum_clone(enm, span));
+                has_clone = true;
+            }
+        }
+    }
+
+    let span = enm.name.rust.span();
+    if !has_copy {
+        expanded.extend(enum_copy(enm, span));
+    }
+    if !has_clone {
+        expanded.extend(enum_clone(enm, span));
+    }
+
+    expanded
+}
+
 fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
 
@@ -55,3 +85,23 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
         }
     }
 }
+
+fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::marker::Copy for #ident {}
+    }
+}
+
+fn enum_clone(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::clone::Clone for #ident {
+            fn clone(&self) -> Self {
+                *self
+            }
+        }
+    }
+}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 09373ff..2917820 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -169,6 +169,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         // usable in patterns.
         #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
     };
+    let derived_traits = derive::expand_enum(enm);
 
     quote! {
         #doc
@@ -188,13 +189,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             type Kind = ::cxx::kind::Trivial;
         }
 
-        impl ::std::marker::Copy for #ident {}
-
-        impl ::std::clone::Clone for #ident {
-            fn clone(&self) -> Self {
-                *self
-            }
-        }
+        #derived_traits
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 17b290a..744963b 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -85,6 +85,7 @@ pub struct Struct {
 
 pub struct Enum {
     pub doc: Doc,
+    pub derives: Vec<Derive>,
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f1a330c..a009e19 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -126,6 +126,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     }
 
     let mut doc = Doc::new();
+    let mut derives = Vec::new();
     let mut repr = None;
     let mut namespace = namespace.clone();
     attrs::parse(
@@ -133,6 +134,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         &item.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
+            derives: Some(&mut derives),
             repr: Some(&mut repr),
             namespace: Some(&mut namespace),
             ..Default::default()
@@ -188,6 +190,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
 
     Ok(Api::Enum(Enum {
         doc,
+        derives,
         enum_token,
         name: Pair::new(namespace, item.ident),
         brace_token,

From f84c98bdb728df6496f755659382430a2959c03b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 21:26:54 +0000
Subject: [PATCH 1587/2232] Implement derive(Debug) on shared structs and enums


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 8988012..87f8ec5 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{Enum, Struct, Trait};
-use proc_macro2::{Span, TokenStream};
+use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
 pub fn expand_struct(strct: &Struct) -> TokenStream {
@@ -10,6 +10,7 @@ pub fn expand_struct(strct: &Struct) -> TokenStream {
         match derive.what {
             Trait::Copy => expanded.extend(struct_copy(strct, span)),
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
+            Trait::Debug => expanded.extend(struct_debug(strct, span)),
         }
     }
 
@@ -32,6 +33,7 @@ pub fn expand_enum(enm: &Enum) -> TokenStream {
                 expanded.extend(enum_clone(enm, span));
                 has_clone = true;
             }
+            Trait::Debug => expanded.extend(enum_debug(enm, span)),
         }
     }
 
@@ -86,6 +88,23 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+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 field_names = fields.clone().map(Ident::to_string);
+
+    quote_spanned! {span=>
+        impl ::std::fmt::Debug for #ident {
+            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                formatter.debug_struct(#struct_name)
+                    #(.field(#field_names, &self.#fields))*
+                    .finish()
+            }
+        }
+    }
+}
+
 fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
 
@@ -105,3 +124,26 @@ fn enum_clone(enm: &Enum, span: Span) -> TokenStream {
         }
     }
 }
+
+fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+    let variants = enm.variants.iter().map(|variant| {
+        let variant = &variant.ident;
+        let name = variant.to_string();
+        quote_spanned! {span=>
+            #ident::#variant => formatter.write_str(#name),
+        }
+    });
+    let fallback = format!("{}({{}})", ident);
+
+    quote_spanned! {span=>
+        impl ::std::fmt::Debug for #ident {
+            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                match *self {
+                    #(#variants)*
+                    _ => ::std::write!(formatter, #fallback, self.repr),
+                }
+            }
+        }
+    }
+}
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 501dd61..75fc6b1 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -10,6 +10,7 @@ pub struct Derive {
 pub enum Trait {
     Clone,
     Copy,
+    Debug,
 }
 
 impl Derive {
@@ -17,6 +18,7 @@ impl Derive {
         let what = match ident.to_string().as_str() {
             "Clone" => Trait::Clone,
             "Copy" => Trait::Copy,
+            "Debug" => Trait::Debug,
             _ => return None,
         };
         let span = ident.span();

From 990eb3cf82ca88c91682d00e85ea1f74672c5e89 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 21:26:54 +0000
Subject: [PATCH 1588/2232] Test Debug impls


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 41f129a..0d96038 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,7 +15,7 @@ use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    #[derive(Clone)]
+    #[derive(Clone, Debug)]
     struct Shared {
         z: usize,
     }
@@ -24,6 +24,7 @@ pub mod ffi {
         msg: String,
     }
 
+    #[derive(Debug)]
     enum Enum {
         AVal,
         BVal = 2020,
diff --git a/tests/test.rs b/tests/test.rs
index b4c39fa..1b9a88e 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -227,6 +227,13 @@ fn test_enum_representations() {
     assert_eq!(2021, ffi::Enum::CVal.repr);
 }
 
+#[test]
+fn test_debug() {
+    assert_eq!("Shared { z: 1 }", format!("{:?}", ffi::Shared { z: 1 }));
+    assert_eq!("BVal", format!("{:?}", ffi::Enum::BVal));
+    assert_eq!("Enum(9)", format!("{:?}", ffi::Enum { repr: 9 }));
+}
+
 #[no_mangle]
 extern "C" fn cxx_test_suite_get_box() -> *mut R {
     Box::into_raw(Box::new(R(2020usize)))

From f4b9334258bd56f763ab436f9347329895243906 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 22:01:15 +0000
Subject: [PATCH 1589/2232] Parse remaining derives after the first unsupported


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index af73b7a..967d9fb 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -29,7 +29,7 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 Err(err) => return cx.push(err),
             }
         } else if attr.path.is_ident("derive") {
-            match attr.parse_args_with(parse_derive_attribute) {
+            match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
                 Ok(attr) => {
                     if let Some(derives) = &mut parser.derives {
                         derives.extend(attr);
@@ -89,19 +89,20 @@ fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
     Ok(lit)
 }
 
-fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Derive>> {
-    input
-        .parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?
-        .into_iter()
-        .map(|path| {
-            if let Some(ident) = path.get_ident() {
-                if let Some(derive) = Derive::from(ident) {
-                    return Ok(derive);
-                }
+fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result<Vec<Derive>> {
+    let paths = input.parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?;
+
+    let mut derives = Vec::new();
+    for path in paths {
+        if let Some(ident) = path.get_ident() {
+            if let Some(derive) = Derive::from(ident) {
+                derives.push(derive);
+                continue;
             }
-            Err(Error::new_spanned(path, "unsupported derive"))
-        })
-        .collect()
+        }
+        cx.error(path, "unsupported derive");
+    }
+    Ok(derives)
 }
 
 fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {

From bc047bb26ea082d9788440ad6ab2ca6983222081 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 22:30:18 +0000
Subject: [PATCH 1590/2232] Add helper for querying derived traits


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 87f8ec5..2109a1f 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{Enum, Struct, Trait};
+use crate::syntax::{derive, Enum, Struct, Trait};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
@@ -59,12 +59,7 @@ fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
 fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
 
-    let is_copy = strct
-        .derives
-        .iter()
-        .any(|derive| derive.what == Trait::Copy);
-
-    let body = if is_copy {
+    let body = if derive::contains(&strct.derives, Trait::Copy) {
         quote!(*self)
     } else {
         let fields = strct.fields.iter().map(|field| &field.ident);
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 75fc6b1..4522e68 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -31,3 +31,7 @@ impl PartialEq<Trait> for Derive {
         self.what == *other
     }
 }
+
+pub fn contains(derives: &[Derive], query: Trait) -> bool {
+    derives.iter().any(|derive| derive.what == query)
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 744963b..bd7efc0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -3,7 +3,7 @@
 pub mod atom;
 mod attrs;
 pub mod check;
-mod derive;
+pub mod derive;
 mod discriminant;
 mod doc;
 pub mod error;
diff --git a/syntax/types.rs b/syntax/types.rs
index 5fe63ff..c98fe85 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,8 +3,8 @@ use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
-    toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Trait, Type,
-    TypeAlias,
+    derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Trait,
+    Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -260,12 +260,7 @@ impl<'a> Types<'a> {
     }
 
     pub fn is_pod(&self, strct: &Struct) -> bool {
-        for derive in &strct.derives {
-            if derive.what == Trait::Copy {
-                return true;
-            }
-        }
-        false
+        derive::contains(&strct.derives, Trait::Copy)
     }
 
     // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if

From ad3db808d0198e20ad75d6f744a4e926ae660e60 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 22:45:49 +0000
Subject: [PATCH 1591/2232] Handle trailing comma in join macro


---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 84e3398..480a0ff 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -5,8 +5,8 @@ use proc_macro2::Ident;
 const CXXBRIDGE: &str = "cxxbridge1";
 
 macro_rules! join {
-    ($($segment:expr),*) => {
-        symbol::join(&[$(&$segment),*])
+    ($($segment:expr),+ $(,)?) => {
+        symbol::join(&[$(&$segment),+])
     };
 }
 
@@ -18,7 +18,7 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
                 efn.name.namespace,
                 CXXBRIDGE,
                 receiver_ident.cxx,
-                efn.name.rust
+                efn.name.rust,
             )
         }
         None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),

From 982158b9e4a772a57fea10f14272ce2142bbd34f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:58:55 +0000
Subject: [PATCH 1592/2232] Suppress clippy single_match lint


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 1de7e6c..89f2549 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -4,6 +4,7 @@
     clippy::new_without_default,
     clippy::nonminimal_bool,
     clippy::or_fun_call,
+    clippy::single_match,
     clippy::toplevel_ref_arg,
     clippy::useless_let_if_seq
 )]

From b3d7bb12fb55dee7b09095b1ecefe02c8a92c0dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:59:03 +0000
Subject: [PATCH 1593/2232] Move PartialEq related derive logic to derive module


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 2109a1f..22c05cc 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -17,7 +17,7 @@ pub fn expand_struct(strct: &Struct) -> TokenStream {
     expanded
 }
 
-pub fn expand_enum(enm: &Enum) -> TokenStream {
+pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut has_copy = false;
     let mut has_clone = false;
@@ -45,6 +45,12 @@ pub fn expand_enum(enm: &Enum) -> TokenStream {
         expanded.extend(enum_clone(enm, span));
     }
 
+    *actual_derives = Some(quote! {
+        // Required to be derived in order for the enum's "variants" to be
+        // usable in patterns.
+        #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
+    });
+
     expanded
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2917820..cc55101 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -164,12 +164,8 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
-    let derives = quote! {
-        // Required to be derived in order for the enum's "variants" to be
-        // usable in patterns.
-        #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
-    };
-    let derived_traits = derive::expand_enum(enm);
+    let mut derives = None;
+    let derived_traits = derive::expand_enum(enm, &mut derives);
 
     quote! {
         #doc

From a3619e92f73faf29e6dc3014d35a71596c1d2764 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:59:03 +0000
Subject: [PATCH 1594/2232] Prepare for PartialEq derives on structs


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 22c05cc..d896afb 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -2,7 +2,7 @@ use crate::syntax::{derive, Enum, Struct, Trait};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
-pub fn expand_struct(strct: &Struct) -> TokenStream {
+pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
 
     for derive in &strct.derives {
@@ -14,6 +14,8 @@ pub fn expand_struct(strct: &Struct) -> TokenStream {
         }
     }
 
+    *actual_derives = None;
+
     expanded
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index cc55101..62ab95f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -134,10 +134,12 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         let vis = Token![pub](field.ident.span());
         quote!(#vis #field)
     });
-    let derived_traits = derive::expand_struct(strct);
+    let mut derives = None;
+    let derived_traits = derive::expand_struct(strct, &mut derives);
 
     quote! {
         #doc
+        #derives
         #[repr(C)]
         pub struct #ident {
             #(#fields,)*

From 21466dfe281229a5fbce22e6effda6125266e131 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:59:03 +0000
Subject: [PATCH 1595/2232] Allow derive(PartialEq, Eq) on shared types


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index d896afb..91d4c64 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -4,6 +4,7 @@ use quote::{quote, quote_spanned, ToTokens};
 
 pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
+    let mut traits = Vec::new();
 
     for derive in &strct.derives {
         let span = derive.span;
@@ -11,18 +12,27 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Copy => expanded.extend(struct_copy(strct, span)),
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
+            Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
         }
     }
 
-    *actual_derives = None;
+    if traits.is_empty() {
+        *actual_derives = None;
+    } else {
+        *actual_derives = Some(quote!(#[derive(#(#traits),*)]));
+    }
 
     expanded
 }
 
 pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
+    let mut traits = Vec::new();
     let mut has_copy = false;
     let mut has_clone = false;
+    let mut has_eq = false;
+    let mut has_partial_eq = false;
 
     for derive in &enm.derives {
         let span = derive.span;
@@ -36,6 +46,14 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 has_clone = true;
             }
             Trait::Debug => expanded.extend(enum_debug(enm, span)),
+            Trait::Eq => {
+                traits.push(quote_spanned!(span=> ::std::cmp::Eq));
+                has_eq = true;
+            }
+            Trait::PartialEq => {
+                traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
+                has_partial_eq = true;
+            }
         }
     }
 
@@ -46,12 +64,16 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
     if !has_clone {
         expanded.extend(enum_clone(enm, span));
     }
-
-    *actual_derives = Some(quote! {
+    if !has_eq {
         // Required to be derived in order for the enum's "variants" to be
         // usable in patterns.
-        #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
-    });
+        traits.push(quote!(::std::cmp::Eq));
+    }
+    if !has_partial_eq {
+        traits.push(quote!(::std::cmp::PartialEq));
+    }
+
+    *actual_derives = Some(quote!(#[derive(#(#traits),*)]));
 
     expanded
 }
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 4522e68..d258cc7 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -11,6 +11,8 @@ pub enum Trait {
     Clone,
     Copy,
     Debug,
+    Eq,
+    PartialEq,
 }
 
 impl Derive {
@@ -19,6 +21,8 @@ impl Derive {
             "Clone" => Trait::Clone,
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
+            "Eq" => Trait::Eq,
+            "PartialEq" => Trait::PartialEq,
             _ => return None,
         };
         let span = ident.span();

From b960ed26af5028cca554b681d97a08c86472f0a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:59:03 +0000
Subject: [PATCH 1596/2232] Emit operator== for structs with derive(PartialEq)


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 60936a0..54c0bba 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,8 +5,8 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct, Type, Types,
-    Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct,
+    Trait, Type, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
@@ -128,6 +128,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     if !out.header {
         for api in apis {
             match api {
+                Api::Struct(strct) => write_struct_operator_decls(out, strct),
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
                 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
                 _ => {}
@@ -136,9 +137,13 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     }
 
     for api in apis {
-        if let Api::RustFunction(efn) = api {
-            out.next_section();
-            write_rust_function_shim(out, efn);
+        match api {
+            Api::Struct(strct) => write_struct_operators(out, strct),
+            Api::RustFunction(efn) => {
+                out.next_section();
+                write_rust_function_shim(out, efn);
+            }
+            _ => {}
         }
     }
 }
@@ -175,6 +180,8 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 }
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
+    let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
+
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -188,7 +195,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
-    if !methods.is_empty() {
+    if !methods.is_empty() || operator_eq {
         writeln!(out);
     }
     for method in methods {
@@ -198,6 +205,18 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
+    if operator_eq {
+        writeln!(
+            out,
+            "  bool operator==(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator!=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+    }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
@@ -330,6 +349,50 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     );
 }
 
+fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+    out.set_namespace(&strct.name.namespace);
+    out.begin_block(Block::ExternC);
+
+    if derive::contains(&strct.derives, Trait::PartialEq) {
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+    }
+
+    out.end_block(Block::ExternC);
+}
+
+fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+    if out.header {
+        return;
+    }
+
+    out.set_namespace(&strct.name.namespace);
+
+    if derive::contains(&strct.derives, Trait::PartialEq) {
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator==(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator!=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        writeln!(out, "  return !(*this == rhs);");
+        writeln!(out, "}}");
+    }
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 91d4c64..28dfae3 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -2,6 +2,8 @@ use crate::syntax::{derive, Enum, Struct, Trait};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
+pub use crate::syntax::derive::*;
+
 pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut traits = Vec::new();
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 62ab95f..bd1aefa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -5,7 +5,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
-    Struct, Type, TypeAlias, Types,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -40,7 +40,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Struct(strct) => {
+                expanded.extend(expand_struct(strct));
+                hidden.extend(expand_struct_operators(strct));
+            }
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.name.rust;
@@ -154,6 +157,30 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     }
 }
 
+fn expand_struct_operators(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let mut operators = TokenStream::new();
+
+    for derive in &strct.derives {
+        let span = derive.span;
+        match derive.what {
+            Trait::PartialEq => operators.extend({
+                let link_name = mangle::operator(&strct.name, "__operator_eq");
+                quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn __operator_eq(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs == *rhs
+                    }
+                }
+            }),
+            _ => {}
+        }
+    }
+
+    operators
+}
+
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 480a0ff..ef605ef 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,5 +1,5 @@
 use crate::syntax::symbol::{self, Symbol};
-use crate::syntax::{ExternFn, Types};
+use crate::syntax::{ExternFn, Pair, Types};
 use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge1";
@@ -25,6 +25,10 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
     }
 }
 
+pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
+    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, operator)
+}
+
 // 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)

From 5f2b8ca2db3d662d6ec280d72e0c893cdf9d729a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 27 2020 23:59:04 +0000
Subject: [PATCH 1597/2232] Add test of struct PartialEq operator==


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0d96038..0ad753d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,7 +15,7 @@ use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    #[derive(Clone, Debug)]
+    #[derive(Clone, Debug, PartialEq, Eq)]
     struct Shared {
         z: usize,
     }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7cd84b8..340dc9c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -653,6 +653,9 @@ extern "C" const char *cxx_run_test() noexcept {
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 
+  ASSERT(Shared{1} == Shared{1});
+  ASSERT(Shared{1} != Shared{2});
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 3eeacdb077587d3912cf880997b26a45d01d97ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 00:13:24 +0000
Subject: [PATCH 1598/2232] Merge pull request #518 from dtolnay/operator-eq


Emit operator== for shared structs with derive(PartialEq)
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 60936a0..54c0bba 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,8 +5,8 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct, Type, Types,
-    Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct,
+    Trait, Type, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
@@ -128,6 +128,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     if !out.header {
         for api in apis {
             match api {
+                Api::Struct(strct) => write_struct_operator_decls(out, strct),
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
                 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
                 _ => {}
@@ -136,9 +137,13 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     }
 
     for api in apis {
-        if let Api::RustFunction(efn) = api {
-            out.next_section();
-            write_rust_function_shim(out, efn);
+        match api {
+            Api::Struct(strct) => write_struct_operators(out, strct),
+            Api::RustFunction(efn) => {
+                out.next_section();
+                write_rust_function_shim(out, efn);
+            }
+            _ => {}
         }
     }
 }
@@ -175,6 +180,8 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 }
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
+    let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
+
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -188,7 +195,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
-    if !methods.is_empty() {
+    if !methods.is_empty() || operator_eq {
         writeln!(out);
     }
     for method in methods {
@@ -198,6 +205,18 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
+    if operator_eq {
+        writeln!(
+            out,
+            "  bool operator==(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator!=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+    }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
@@ -330,6 +349,50 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     );
 }
 
+fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+    out.set_namespace(&strct.name.namespace);
+    out.begin_block(Block::ExternC);
+
+    if derive::contains(&strct.derives, Trait::PartialEq) {
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+    }
+
+    out.end_block(Block::ExternC);
+}
+
+fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
+    if out.header {
+        return;
+    }
+
+    out.set_namespace(&strct.name.namespace);
+
+    if derive::contains(&strct.derives, Trait::PartialEq) {
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator==(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator!=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        writeln!(out, "  return !(*this == rhs);");
+        writeln!(out, "}}");
+    }
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 2109a1f..28dfae3 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -2,8 +2,11 @@ use crate::syntax::{derive, Enum, Struct, Trait};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote, quote_spanned, ToTokens};
 
-pub fn expand_struct(strct: &Struct) -> TokenStream {
+pub use crate::syntax::derive::*;
+
+pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
+    let mut traits = Vec::new();
 
     for derive in &strct.derives {
         let span = derive.span;
@@ -11,16 +14,27 @@ pub fn expand_struct(strct: &Struct) -> TokenStream {
             Trait::Copy => expanded.extend(struct_copy(strct, span)),
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
+            Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
         }
     }
 
+    if traits.is_empty() {
+        *actual_derives = None;
+    } else {
+        *actual_derives = Some(quote!(#[derive(#(#traits),*)]));
+    }
+
     expanded
 }
 
-pub fn expand_enum(enm: &Enum) -> TokenStream {
+pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> TokenStream {
     let mut expanded = TokenStream::new();
+    let mut traits = Vec::new();
     let mut has_copy = false;
     let mut has_clone = false;
+    let mut has_eq = false;
+    let mut has_partial_eq = false;
 
     for derive in &enm.derives {
         let span = derive.span;
@@ -34,6 +48,14 @@ pub fn expand_enum(enm: &Enum) -> TokenStream {
                 has_clone = true;
             }
             Trait::Debug => expanded.extend(enum_debug(enm, span)),
+            Trait::Eq => {
+                traits.push(quote_spanned!(span=> ::std::cmp::Eq));
+                has_eq = true;
+            }
+            Trait::PartialEq => {
+                traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
+                has_partial_eq = true;
+            }
         }
     }
 
@@ -44,6 +66,16 @@ pub fn expand_enum(enm: &Enum) -> TokenStream {
     if !has_clone {
         expanded.extend(enum_clone(enm, span));
     }
+    if !has_eq {
+        // Required to be derived in order for the enum's "variants" to be
+        // usable in patterns.
+        traits.push(quote!(::std::cmp::Eq));
+    }
+    if !has_partial_eq {
+        traits.push(quote!(::std::cmp::PartialEq));
+    }
+
+    *actual_derives = Some(quote!(#[derive(#(#traits),*)]));
 
     expanded
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2917820..bd1aefa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -5,7 +5,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
-    Struct, Type, TypeAlias, Types,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -40,7 +40,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
     for api in apis {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
-            Api::Struct(strct) => expanded.extend(expand_struct(strct)),
+            Api::Struct(strct) => {
+                expanded.extend(expand_struct(strct));
+                hidden.extend(expand_struct_operators(strct));
+            }
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 let ident = &ety.name.rust;
@@ -134,10 +137,12 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         let vis = Token![pub](field.ident.span());
         quote!(#vis #field)
     });
-    let derived_traits = derive::expand_struct(strct);
+    let mut derives = None;
+    let derived_traits = derive::expand_struct(strct, &mut derives);
 
     quote! {
         #doc
+        #derives
         #[repr(C)]
         pub struct #ident {
             #(#fields,)*
@@ -152,6 +157,30 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     }
 }
 
+fn expand_struct_operators(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let mut operators = TokenStream::new();
+
+    for derive in &strct.derives {
+        let span = derive.span;
+        match derive.what {
+            Trait::PartialEq => operators.extend({
+                let link_name = mangle::operator(&strct.name, "__operator_eq");
+                quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn __operator_eq(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs == *rhs
+                    }
+                }
+            }),
+            _ => {}
+        }
+    }
+
+    operators
+}
+
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
@@ -164,12 +193,8 @@ fn expand_enum(enm: &Enum) -> TokenStream {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
-    let derives = quote! {
-        // Required to be derived in order for the enum's "variants" to be
-        // usable in patterns.
-        #[derive(::std::cmp::PartialEq, ::std::cmp::Eq)]
-    };
-    let derived_traits = derive::expand_enum(enm);
+    let mut derives = None;
+    let derived_traits = derive::expand_enum(enm, &mut derives);
 
     quote! {
         #doc
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 4522e68..d258cc7 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -11,6 +11,8 @@ pub enum Trait {
     Clone,
     Copy,
     Debug,
+    Eq,
+    PartialEq,
 }
 
 impl Derive {
@@ -19,6 +21,8 @@ impl Derive {
             "Clone" => Trait::Clone,
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
+            "Eq" => Trait::Eq,
+            "PartialEq" => Trait::PartialEq,
             _ => return None,
         };
         let span = ident.span();
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 480a0ff..ef605ef 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,5 +1,5 @@
 use crate::syntax::symbol::{self, Symbol};
-use crate::syntax::{ExternFn, Types};
+use crate::syntax::{ExternFn, Pair, Types};
 use proc_macro2::Ident;
 
 const CXXBRIDGE: &str = "cxxbridge1";
@@ -25,6 +25,10 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
     }
 }
 
+pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
+    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, operator)
+}
+
 // 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)
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0d96038..0ad753d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,7 +15,7 @@ use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    #[derive(Clone, Debug)]
+    #[derive(Clone, Debug, PartialEq, Eq)]
     struct Shared {
         z: usize,
     }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7cd84b8..340dc9c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -653,6 +653,9 @@ extern "C" const char *cxx_run_test() noexcept {
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
 
+  ASSERT(Shared{1} == Shared{1});
+  ASSERT(Shared{1} != Shared{2});
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From ec9b4ba0a6707be8516169f68f289caf35d80733 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 00:57:06 +0000
Subject: [PATCH 1599/2232] Avoid function name collision on __operator_eq


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index bd1aefa..4bd955a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -166,10 +166,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
         match derive.what {
             Trait::PartialEq => operators.extend({
                 let link_name = mangle::operator(&strct.name, "__operator_eq");
+                let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
                 quote_spanned! {span=>
                     #[doc(hidden)]
                     #[export_name = #link_name]
-                    extern "C" fn __operator_eq(lhs: &#ident, rhs: &#ident) -> bool {
+                    extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
                         *lhs == *rhs
                     }
                 }

From a6f3b6f4ec21b3ecb65c2692c5677d88457c6d8b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:00:20 +0000
Subject: [PATCH 1600/2232] Implement operator!= using a distinct symbol from operator==


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 54c0bba..81eeef0 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -360,6 +360,15 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
             "bool {}(const {1} &, const {1} &) noexcept;",
             link_name, strct.name.cxx,
         );
+
+        if !derive::contains(&strct.derives, Trait::Eq) {
+            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+        }
     }
 
     out.end_block(Block::ExternC);
@@ -373,22 +382,28 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     out.set_namespace(&strct.name.namespace);
 
     if derive::contains(&strct.derives, Trait::PartialEq) {
-        let link_name = mangle::operator(&strct.name, "__operator_eq");
         out.next_section();
         writeln!(
             out,
             "bool {0}::operator==(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
         writeln!(out, "  return {}(*this, rhs);", link_name);
         writeln!(out, "}}");
+
         out.next_section();
         writeln!(
             out,
             "bool {0}::operator!=(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
-        writeln!(out, "  return !(*this == rhs);");
+        if derive::contains(&strct.derives, Trait::Eq) {
+            writeln!(out, "  return !(*this == rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
         writeln!(out, "}}");
     }
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4bd955a..5020a39 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -164,17 +164,29 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
     for derive in &strct.derives {
         let span = derive.span;
         match derive.what {
-            Trait::PartialEq => operators.extend({
+            Trait::PartialEq => {
                 let link_name = mangle::operator(&strct.name, "__operator_eq");
                 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
-                quote_spanned! {span=>
+                operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
                     #[export_name = #link_name]
                     extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
                         *lhs == *rhs
                     }
+                });
+
+                if !derive::contains(&strct.derives, Trait::Eq) {
+                    let link_name = mangle::operator(&strct.name, "__operator_ne");
+                    let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs != *rhs
+                        }
+                    });
                 }
-            }),
+            }
             _ => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0ad753d..021b0c3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -20,6 +20,7 @@ pub mod ffi {
         z: usize,
     }
 
+    #[derive(PartialEq)]
     struct SharedString {
         msg: String,
     }

From bb6898536c42c9255fbcc4efdc6caf36d4349203 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:12:42 +0000
Subject: [PATCH 1601/2232] Merge pull request #519 from dtolnay/operator-ne


Implement operator!= using a distinct symbol from operator==
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 54c0bba..81eeef0 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -360,6 +360,15 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
             "bool {}(const {1} &, const {1} &) noexcept;",
             link_name, strct.name.cxx,
         );
+
+        if !derive::contains(&strct.derives, Trait::Eq) {
+            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+        }
     }
 
     out.end_block(Block::ExternC);
@@ -373,22 +382,28 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     out.set_namespace(&strct.name.namespace);
 
     if derive::contains(&strct.derives, Trait::PartialEq) {
-        let link_name = mangle::operator(&strct.name, "__operator_eq");
         out.next_section();
         writeln!(
             out,
             "bool {0}::operator==(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
+        let link_name = mangle::operator(&strct.name, "__operator_eq");
         writeln!(out, "  return {}(*this, rhs);", link_name);
         writeln!(out, "}}");
+
         out.next_section();
         writeln!(
             out,
             "bool {0}::operator!=(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
-        writeln!(out, "  return !(*this == rhs);");
+        if derive::contains(&strct.derives, Trait::Eq) {
+            writeln!(out, "  return !(*this == rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
         writeln!(out, "}}");
     }
 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4bd955a..5020a39 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -164,17 +164,29 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
     for derive in &strct.derives {
         let span = derive.span;
         match derive.what {
-            Trait::PartialEq => operators.extend({
+            Trait::PartialEq => {
                 let link_name = mangle::operator(&strct.name, "__operator_eq");
                 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
-                quote_spanned! {span=>
+                operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
                     #[export_name = #link_name]
                     extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
                         *lhs == *rhs
                     }
+                });
+
+                if !derive::contains(&strct.derives, Trait::Eq) {
+                    let link_name = mangle::operator(&strct.name, "__operator_ne");
+                    let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs != *rhs
+                        }
+                    });
                 }
-            }),
+            }
             _ => {}
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0ad753d..021b0c3 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -20,6 +20,7 @@ pub mod ffi {
         z: usize,
     }
 
+    #[derive(PartialEq)]
     struct SharedString {
         msg: String,
     }

From 577135e79a32ccb927dc958e2225c69bc0238772 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:17:51 +0000
Subject: [PATCH 1602/2232] Support derive(PartialOrd, Ord)


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 28dfae3..91a5d9d 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -15,7 +15,9 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
+            Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
         }
     }
 
@@ -52,10 +54,12 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
+            Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
                 has_partial_eq = true;
             }
+            Trait::PartialOrd => expanded.extend(enum_partial_ord(enm, span)),
         }
     }
 
@@ -132,6 +136,54 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+    let fields = strct.fields.iter().map(|field| &field.ident);
+
+    quote_spanned! {span=>
+        impl ::std::cmp::Ord for #ident {
+            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+                #(
+                    match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) {
+                        ::std::cmp::Ordering::Equal => {}
+                        ordering => return ordering,
+                    }
+                )*
+                ::std::cmp::Ordering::Equal
+            }
+        }
+    }
+}
+
+fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+
+    let body = if derive::contains(&strct.derives, Trait::Ord) {
+        quote! {
+            ::std::option::Option::Some(::std::cmp::Ord::cmp(self, other))
+        }
+    } else {
+        let fields = strct.fields.iter().map(|field| &field.ident);
+        quote! {
+            #(
+                match ::std::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) {
+                    ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {}
+                    ordering => return ordering,
+                }
+            )*
+            ::std::option::Option::Some(::std::cmp::Ordering::Equal)
+        }
+    };
+
+    quote_spanned! {span=>
+        impl ::std::cmp::PartialOrd for #ident {
+            fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+                #body
+            }
+        }
+    }
+}
+
 fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
 
@@ -174,3 +226,27 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
         }
     }
 }
+
+fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::cmp::Ord for #ident {
+            pub fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+                ::std::cmp::Ord::cmp(&self.repr, &other.repr)
+            }
+        }
+    }
+}
+
+fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::cmp::PartialOrd for #ident {
+            pub fn cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+                ::std::cmp::PartialOrd::cmp(&self.repr, &other.repr)
+            }
+        }
+    }
+}
diff --git a/syntax/derive.rs b/syntax/derive.rs
index d258cc7..1099967 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -12,7 +12,9 @@ pub enum Trait {
     Copy,
     Debug,
     Eq,
+    Ord,
     PartialEq,
+    PartialOrd,
 }
 
 impl Derive {
@@ -22,7 +24,9 @@ impl Derive {
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
             "Eq" => Trait::Eq,
+            "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
+            "PartialOrd" => Trait::PartialOrd,
             _ => return None,
         };
         let span = ident.span();
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 021b0c3..cb0f916 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,12 +15,12 @@ use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    #[derive(Clone, Debug, PartialEq, Eq)]
+    #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
     struct Shared {
         z: usize,
     }
 
-    #[derive(PartialEq)]
+    #[derive(PartialEq, PartialOrd)]
     struct SharedString {
         msg: String,
     }

From 843893535613d4649138cc3cf5de7fb37bfbcf6f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:17:52 +0000
Subject: [PATCH 1603/2232] Wire up comparison operators


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 81eeef0..2fd0f70 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -181,6 +181,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
     let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
+    let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd);
 
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
@@ -190,14 +191,17 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         writeln!(out, "//{}", line);
     }
     writeln!(out, "struct {} final {{", strct.name.cxx);
+
     for field in &strct.fields {
         write!(out, "  ");
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
-    if !methods.is_empty() || operator_eq {
+
+    if !methods.is_empty() || operator_eq || operator_ord {
         writeln!(out);
     }
+
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
@@ -205,6 +209,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
+
     if operator_eq {
         writeln!(
             out,
@@ -217,6 +222,30 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
             strct.name.cxx,
         );
     }
+
+    if operator_ord {
+        writeln!(
+            out,
+            "  bool operator<(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator<=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator>(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator>=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+    }
+
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
@@ -371,6 +400,38 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
     }
 
+    if derive::contains(&strct.derives, Trait::PartialOrd) {
+        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+
+        let link_name = mangle::operator(&strct.name, "__operator_le");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+
+        if !derive::contains(&strct.derives, Trait::Ord) {
+            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+
+            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+        }
+    }
+
     out.end_block(Block::ExternC);
 }
 
@@ -406,6 +467,56 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
         writeln!(out, "}}");
     }
+
+    if derive::contains(&strct.derives, Trait::PartialOrd) {
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator<(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator<=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        let link_name = mangle::operator(&strct.name, "__operator_le");
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator>(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        if derive::contains(&strct.derives, Trait::Ord) {
+            writeln!(out, "  return !(*this <= rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator>=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        if derive::contains(&strct.derives, Trait::Ord) {
+            writeln!(out, "  return !(*this < rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
+        writeln!(out, "}}");
+    }
 }
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 5020a39..2b9c7d4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -187,6 +187,49 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                     });
                 }
             }
+            Trait::PartialOrd => {
+                let link_name = mangle::operator(&strct.name, "__operator_lt");
+                let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs < *rhs
+                    }
+                });
+
+                let link_name = mangle::operator(&strct.name, "__operator_le");
+                let local_name = format_ident!("__operator_le_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs <= *rhs
+                    }
+                });
+
+                if !derive::contains(&strct.derives, Trait::Ord) {
+                    let link_name = mangle::operator(&strct.name, "__operator_gt");
+                    let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs > *rhs
+                        }
+                    });
+
+                    let link_name = mangle::operator(&strct.name, "__operator_ge");
+                    let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs >= *rhs
+                        }
+                    });
+                }
+            }
             _ => {}
         }
     }

From a7fff7a93e4430616753990ece5d9dd23b24bb02 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:27:14 +0000
Subject: [PATCH 1604/2232] Merge pull request #520 from dtolnay/operator-ord


Support derive(PartialOrd, Ord)
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 81eeef0..2fd0f70 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -181,6 +181,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
 
 fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&ExternFn]) {
     let operator_eq = derive::contains(&strct.derives, Trait::PartialEq);
+    let operator_ord = derive::contains(&strct.derives, Trait::PartialOrd);
 
     out.set_namespace(&strct.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", strct.name.to_symbol());
@@ -190,14 +191,17 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         writeln!(out, "//{}", line);
     }
     writeln!(out, "struct {} final {{", strct.name.cxx);
+
     for field in &strct.fields {
         write!(out, "  ");
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);
     }
-    if !methods.is_empty() || operator_eq {
+
+    if !methods.is_empty() || operator_eq || operator_ord {
         writeln!(out);
     }
+
     for method in methods {
         write!(out, "  ");
         let sig = &method.sig;
@@ -205,6 +209,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         write_rust_function_shim_decl(out, &local_name, sig, false);
         writeln!(out, ";");
     }
+
     if operator_eq {
         writeln!(
             out,
@@ -217,6 +222,30 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
             strct.name.cxx,
         );
     }
+
+    if operator_ord {
+        writeln!(
+            out,
+            "  bool operator<(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator<=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator>(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+        writeln!(
+            out,
+            "  bool operator>=(const {} &) const noexcept;",
+            strct.name.cxx,
+        );
+    }
+
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
@@ -371,6 +400,38 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
     }
 
+    if derive::contains(&strct.derives, Trait::PartialOrd) {
+        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+
+        let link_name = mangle::operator(&strct.name, "__operator_le");
+        writeln!(
+            out,
+            "bool {}(const {1} &, const {1} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+
+        if !derive::contains(&strct.derives, Trait::Ord) {
+            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+
+            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            writeln!(
+                out,
+                "bool {}(const {1} &, const {1} &) noexcept;",
+                link_name, strct.name.cxx,
+            );
+        }
+    }
+
     out.end_block(Block::ExternC);
 }
 
@@ -406,6 +467,56 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
         writeln!(out, "}}");
     }
+
+    if derive::contains(&strct.derives, Trait::PartialOrd) {
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator<(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator<=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        let link_name = mangle::operator(&strct.name, "__operator_le");
+        writeln!(out, "  return {}(*this, rhs);", link_name);
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator>(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        if derive::contains(&strct.derives, Trait::Ord) {
+            writeln!(out, "  return !(*this <= rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
+        writeln!(out, "}}");
+
+        out.next_section();
+        writeln!(
+            out,
+            "bool {0}::operator>=(const {0} &rhs) const noexcept {{",
+            strct.name.cxx,
+        );
+        if derive::contains(&strct.derives, Trait::Ord) {
+            writeln!(out, "  return !(*this < rhs);");
+        } else {
+            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            writeln!(out, "  return {}(*this, rhs);", link_name);
+        }
+        writeln!(out, "}}");
+    }
 }
 
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 28dfae3..91a5d9d 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -15,7 +15,9 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
+            Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
         }
     }
 
@@ -52,10 +54,12 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
+            Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
                 has_partial_eq = true;
             }
+            Trait::PartialOrd => expanded.extend(enum_partial_ord(enm, span)),
         }
     }
 
@@ -132,6 +136,54 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+    let fields = strct.fields.iter().map(|field| &field.ident);
+
+    quote_spanned! {span=>
+        impl ::std::cmp::Ord for #ident {
+            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+                #(
+                    match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) {
+                        ::std::cmp::Ordering::Equal => {}
+                        ordering => return ordering,
+                    }
+                )*
+                ::std::cmp::Ordering::Equal
+            }
+        }
+    }
+}
+
+fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+
+    let body = if derive::contains(&strct.derives, Trait::Ord) {
+        quote! {
+            ::std::option::Option::Some(::std::cmp::Ord::cmp(self, other))
+        }
+    } else {
+        let fields = strct.fields.iter().map(|field| &field.ident);
+        quote! {
+            #(
+                match ::std::cmp::PartialOrd::partial_cmp(&self.#fields, &other.#fields) {
+                    ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {}
+                    ordering => return ordering,
+                }
+            )*
+            ::std::option::Option::Some(::std::cmp::Ordering::Equal)
+        }
+    };
+
+    quote_spanned! {span=>
+        impl ::std::cmp::PartialOrd for #ident {
+            fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+                #body
+            }
+        }
+    }
+}
+
 fn enum_copy(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
 
@@ -174,3 +226,27 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
         }
     }
 }
+
+fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::cmp::Ord for #ident {
+            pub fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+                ::std::cmp::Ord::cmp(&self.repr, &other.repr)
+            }
+        }
+    }
+}
+
+fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::cmp::PartialOrd for #ident {
+            pub fn cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+                ::std::cmp::PartialOrd::cmp(&self.repr, &other.repr)
+            }
+        }
+    }
+}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 5020a39..2b9c7d4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -187,6 +187,49 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                     });
                 }
             }
+            Trait::PartialOrd => {
+                let link_name = mangle::operator(&strct.name, "__operator_lt");
+                let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs < *rhs
+                    }
+                });
+
+                let link_name = mangle::operator(&strct.name, "__operator_le");
+                let local_name = format_ident!("__operator_le_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                        *lhs <= *rhs
+                    }
+                });
+
+                if !derive::contains(&strct.derives, Trait::Ord) {
+                    let link_name = mangle::operator(&strct.name, "__operator_gt");
+                    let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs > *rhs
+                        }
+                    });
+
+                    let link_name = mangle::operator(&strct.name, "__operator_ge");
+                    let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
+                    operators.extend(quote_spanned! {span=>
+                        #[doc(hidden)]
+                        #[export_name = #link_name]
+                        extern "C" fn #local_name(lhs: &#ident, rhs: &#ident) -> bool {
+                            *lhs >= *rhs
+                        }
+                    });
+                }
+            }
             _ => {}
         }
     }
diff --git a/syntax/derive.rs b/syntax/derive.rs
index d258cc7..1099967 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -12,7 +12,9 @@ pub enum Trait {
     Copy,
     Debug,
     Eq,
+    Ord,
     PartialEq,
+    PartialOrd,
 }
 
 impl Derive {
@@ -22,7 +24,9 @@ impl Derive {
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
             "Eq" => Trait::Eq,
+            "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
+            "PartialOrd" => Trait::PartialOrd,
             _ => return None,
         };
         let span = ident.span();
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 021b0c3..cb0f916 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -15,12 +15,12 @@ use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
-    #[derive(Clone, Debug, PartialEq, Eq)]
+    #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
     struct Shared {
         z: usize,
     }
 
-    #[derive(PartialEq)]
+    #[derive(PartialEq, PartialOrd)]
     struct SharedString {
         msg: String,
     }

From b600e4f348ee4ec1a63f259b01c6cea6593c7968 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:27:48 +0000
Subject: [PATCH 1605/2232] Add span-preserving ToTokens for Derive


---

diff --git a/syntax/derive.rs b/syntax/derive.rs
index 1099967..813cf26 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -40,6 +40,20 @@ impl PartialEq<Trait> for Derive {
     }
 }
 
+impl AsRef<str> for Trait {
+    fn as_ref(&self) -> &str {
+        match self {
+            Trait::Clone => "Clone",
+            Trait::Copy => "Copy",
+            Trait::Debug => "Debug",
+            Trait::Eq => "Eq",
+            Trait::Ord => "Ord",
+            Trait::PartialEq => "PartialEq",
+            Trait::PartialOrd => "PartialOrd",
+        }
+    }
+}
+
 pub fn contains(derives: &[Derive], query: Trait) -> bool {
     derives.iter().any(|derive| derive.what == query)
 }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 29899a9..377fd4c 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
-    SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
+    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -99,6 +99,12 @@ impl ToTokens for Atom {
     }
 }
 
+impl ToTokens for Derive {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Ident::new(self.what.as_ref(), self.span).to_tokens(tokens);
+    }
+}
+
 impl ToTokens for ExternType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.

From a6a9e94e08c798fee04952d7705cfa11bec7ad52 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:28:55 +0000
Subject: [PATCH 1606/2232] Support derive(Default) on structs


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 91a5d9d..be8ad82 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -14,6 +14,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Copy => expanded.extend(struct_copy(strct, span)),
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
+            Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
@@ -50,6 +51,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 has_clone = true;
             }
             Trait::Debug => expanded.extend(enum_debug(enm, span)),
+            Trait::Default => unreachable!(),
             Trait::Eq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
@@ -136,6 +138,23 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+fn struct_default(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+    let fields = strct.fields.iter().map(|field| &field.ident);
+
+    quote_spanned! {span=>
+        impl ::std::default::Default for #ident {
+            fn default() -> Self {
+                #ident {
+                    #(
+                        #fields: ::std::default::Default::default(),
+                    )*
+                }
+            }
+        }
+    }
+}
+
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
     let fields = strct.fields.iter().map(|field| &field.ident);
diff --git a/syntax/check.rs b/syntax/check.rs
index 85db248..725105d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Ty1, Type, Types,
+    SliceRef, Struct, Trait, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -256,6 +256,15 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
             "explicit #[repr(...)] is required for enum without any variants",
         );
     }
+
+    for derive in &enm.derives {
+        if derive.what == Trait::Default {
+            cx.error(
+                derive,
+                "derive(Default) on shared enums is not supported yet",
+            );
+        }
+    }
 }
 
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 813cf26..a8b6bde 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -11,6 +11,7 @@ pub enum Trait {
     Clone,
     Copy,
     Debug,
+    Default,
     Eq,
     Ord,
     PartialEq,
@@ -23,6 +24,7 @@ impl Derive {
             "Clone" => Trait::Clone,
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
+            "Default" => Trait::Default,
             "Eq" => Trait::Eq,
             "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
@@ -46,6 +48,7 @@ impl AsRef<str> for Trait {
             Trait::Clone => "Clone",
             Trait::Copy => "Copy",
             Trait::Debug => "Debug",
+            Trait::Default => "Default",
             Trait::Eq => "Eq",
             Trait::Ord => "Ord",
             Trait::PartialEq => "PartialEq",

From ac03d4b6a261060c1280a728de5709110e4517f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:41:46 +0000
Subject: [PATCH 1607/2232] Merge pull request #521 from dtolnay/derive-default


Support derive(Default) on structs
---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 91a5d9d..be8ad82 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -14,6 +14,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Copy => expanded.extend(struct_copy(strct, span)),
             Trait::Clone => expanded.extend(struct_clone(strct, span)),
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
+            Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
@@ -50,6 +51,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 has_clone = true;
             }
             Trait::Debug => expanded.extend(enum_debug(enm, span)),
+            Trait::Default => unreachable!(),
             Trait::Eq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
@@ -136,6 +138,23 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+fn struct_default(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+    let fields = strct.fields.iter().map(|field| &field.ident);
+
+    quote_spanned! {span=>
+        impl ::std::default::Default for #ident {
+            fn default() -> Self {
+                #ident {
+                    #(
+                        #fields: ::std::default::Default::default(),
+                    )*
+                }
+            }
+        }
+    }
+}
+
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
     let fields = strct.fields.iter().map(|field| &field.ident);
diff --git a/syntax/check.rs b/syntax/check.rs
index 85db248..725105d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Ty1, Type, Types,
+    SliceRef, Struct, Trait, Ty1, Type, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -256,6 +256,15 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
             "explicit #[repr(...)] is required for enum without any variants",
         );
     }
+
+    for derive in &enm.derives {
+        if derive.what == Trait::Default {
+            cx.error(
+                derive,
+                "derive(Default) on shared enums is not supported yet",
+            );
+        }
+    }
 }
 
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 813cf26..a8b6bde 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -11,6 +11,7 @@ pub enum Trait {
     Clone,
     Copy,
     Debug,
+    Default,
     Eq,
     Ord,
     PartialEq,
@@ -23,6 +24,7 @@ impl Derive {
             "Clone" => Trait::Clone,
             "Copy" => Trait::Copy,
             "Debug" => Trait::Debug,
+            "Default" => Trait::Default,
             "Eq" => Trait::Eq,
             "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
@@ -46,6 +48,7 @@ impl AsRef<str> for Trait {
             Trait::Clone => "Clone",
             Trait::Copy => "Copy",
             Trait::Debug => "Debug",
+            Trait::Default => "Default",
             Trait::Eq => "Eq",
             Trait::Ord => "Ord",
             Trait::PartialEq => "PartialEq",

From a05f9402db07ff1dcc58657b03f079eaca636929 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 01:44:18 +0000
Subject: [PATCH 1608/2232] Tweak operator symbol mangling


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2fd0f70..ab9d3c0 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -383,7 +383,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     out.begin_block(Block::ExternC);
 
     if derive::contains(&strct.derives, Trait::PartialEq) {
-        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        let link_name = mangle::operator(&strct.name, "eq");
         writeln!(
             out,
             "bool {}(const {1} &, const {1} &) noexcept;",
@@ -391,7 +391,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         );
 
         if !derive::contains(&strct.derives, Trait::Eq) {
-            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            let link_name = mangle::operator(&strct.name, "ne");
             writeln!(
                 out,
                 "bool {}(const {1} &, const {1} &) noexcept;",
@@ -401,14 +401,14 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     }
 
     if derive::contains(&strct.derives, Trait::PartialOrd) {
-        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        let link_name = mangle::operator(&strct.name, "lt");
         writeln!(
             out,
             "bool {}(const {1} &, const {1} &) noexcept;",
             link_name, strct.name.cxx,
         );
 
-        let link_name = mangle::operator(&strct.name, "__operator_le");
+        let link_name = mangle::operator(&strct.name, "le");
         writeln!(
             out,
             "bool {}(const {1} &, const {1} &) noexcept;",
@@ -416,14 +416,14 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         );
 
         if !derive::contains(&strct.derives, Trait::Ord) {
-            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            let link_name = mangle::operator(&strct.name, "gt");
             writeln!(
                 out,
                 "bool {}(const {1} &, const {1} &) noexcept;",
                 link_name, strct.name.cxx,
             );
 
-            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            let link_name = mangle::operator(&strct.name, "ge");
             writeln!(
                 out,
                 "bool {}(const {1} &, const {1} &) noexcept;",
@@ -449,7 +449,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
             "bool {0}::operator==(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
-        let link_name = mangle::operator(&strct.name, "__operator_eq");
+        let link_name = mangle::operator(&strct.name, "eq");
         writeln!(out, "  return {}(*this, rhs);", link_name);
         writeln!(out, "}}");
 
@@ -462,7 +462,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         if derive::contains(&strct.derives, Trait::Eq) {
             writeln!(out, "  return !(*this == rhs);");
         } else {
-            let link_name = mangle::operator(&strct.name, "__operator_ne");
+            let link_name = mangle::operator(&strct.name, "ne");
             writeln!(out, "  return {}(*this, rhs);", link_name);
         }
         writeln!(out, "}}");
@@ -475,7 +475,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
             "bool {0}::operator<(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
-        let link_name = mangle::operator(&strct.name, "__operator_lt");
+        let link_name = mangle::operator(&strct.name, "lt");
         writeln!(out, "  return {}(*this, rhs);", link_name);
         writeln!(out, "}}");
 
@@ -485,7 +485,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
             "bool {0}::operator<=(const {0} &rhs) const noexcept {{",
             strct.name.cxx,
         );
-        let link_name = mangle::operator(&strct.name, "__operator_le");
+        let link_name = mangle::operator(&strct.name, "le");
         writeln!(out, "  return {}(*this, rhs);", link_name);
         writeln!(out, "}}");
 
@@ -498,7 +498,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         if derive::contains(&strct.derives, Trait::Ord) {
             writeln!(out, "  return !(*this <= rhs);");
         } else {
-            let link_name = mangle::operator(&strct.name, "__operator_gt");
+            let link_name = mangle::operator(&strct.name, "gt");
             writeln!(out, "  return {}(*this, rhs);", link_name);
         }
         writeln!(out, "}}");
@@ -512,7 +512,7 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         if derive::contains(&strct.derives, Trait::Ord) {
             writeln!(out, "  return !(*this < rhs);");
         } else {
-            let link_name = mangle::operator(&strct.name, "__operator_ge");
+            let link_name = mangle::operator(&strct.name, "ge");
             writeln!(out, "  return {}(*this, rhs);", link_name);
         }
         writeln!(out, "}}");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2b9c7d4..e065a55 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -165,7 +165,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
         let span = derive.span;
         match derive.what {
             Trait::PartialEq => {
-                let link_name = mangle::operator(&strct.name, "__operator_eq");
+                let link_name = mangle::operator(&strct.name, "eq");
                 let local_name = format_ident!("__operator_eq_{}", strct.name.rust);
                 operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
@@ -176,7 +176,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                 });
 
                 if !derive::contains(&strct.derives, Trait::Eq) {
-                    let link_name = mangle::operator(&strct.name, "__operator_ne");
+                    let link_name = mangle::operator(&strct.name, "ne");
                     let local_name = format_ident!("__operator_ne_{}", strct.name.rust);
                     operators.extend(quote_spanned! {span=>
                         #[doc(hidden)]
@@ -188,7 +188,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                 }
             }
             Trait::PartialOrd => {
-                let link_name = mangle::operator(&strct.name, "__operator_lt");
+                let link_name = mangle::operator(&strct.name, "lt");
                 let local_name = format_ident!("__operator_lt_{}", strct.name.rust);
                 operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
@@ -198,7 +198,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                     }
                 });
 
-                let link_name = mangle::operator(&strct.name, "__operator_le");
+                let link_name = mangle::operator(&strct.name, "le");
                 let local_name = format_ident!("__operator_le_{}", strct.name.rust);
                 operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
@@ -209,7 +209,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                 });
 
                 if !derive::contains(&strct.derives, Trait::Ord) {
-                    let link_name = mangle::operator(&strct.name, "__operator_gt");
+                    let link_name = mangle::operator(&strct.name, "gt");
                     let local_name = format_ident!("__operator_gt_{}", strct.name.rust);
                     operators.extend(quote_spanned! {span=>
                         #[doc(hidden)]
@@ -219,7 +219,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                         }
                     });
 
-                    let link_name = mangle::operator(&strct.name, "__operator_ge");
+                    let link_name = mangle::operator(&strct.name, "ge");
                     let local_name = format_ident!("__operator_ge_{}", strct.name.rust);
                     operators.extend(quote_spanned! {span=>
                         #[doc(hidden)]
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index ef605ef..26cd3c0 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -26,7 +26,7 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
 }
 
 pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
-    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, operator)
+    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, "operator", operator)
 }
 
 // The C half of a function pointer trampoline.

From 7da38209bfd4977e825ed67bdb83ae0b8aa4fb4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 02:09:44 +0000
Subject: [PATCH 1609/2232] Support derive(Hash)


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ab9d3c0..873904d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -134,6 +134,8 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 _ => {}
             }
         }
+
+        write_std_specializations(out, apis);
     }
 
     for api in apis {
@@ -148,6 +150,36 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     }
 }
 
+fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
+    out.set_namespace(Default::default());
+    out.begin_block(Block::Namespace("std"));
+
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            if derive::contains(&strct.derives, Trait::Hash) {
+                out.next_section();
+                let qualified = strct.name.to_fully_qualified();
+                writeln!(out, "template <> struct hash<{}> {{", qualified);
+                writeln!(
+                    out,
+                    "  size_t operator()(const {} &self) const noexcept {{",
+                    qualified,
+                );
+                let link_name = mangle::operator(&strct.name, "hash");
+                write!(out, "    return ::");
+                for name in &strct.name.namespace {
+                    write!(out, "{}::", name);
+                }
+                writeln!(out, "{}(self);", link_name);
+                writeln!(out, "  }}");
+                writeln!(out, "}};");
+            }
+        }
+    }
+
+    out.end_block(Block::Namespace("std"));
+}
+
 fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     for api in apis {
         if let Api::Include(include) = api {
@@ -432,6 +464,15 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
     }
 
+    if derive::contains(&strct.derives, Trait::Hash) {
+        let link_name = mangle::operator(&strct.name, "hash");
+        writeln!(
+            out,
+            "size_t {}(const {} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+    }
+
     out.end_block(Block::ExternC);
 }
 
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index be8ad82..f614add 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -16,6 +16,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::Hash => expanded.extend(struct_hash(strct, span)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
             Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
@@ -56,6 +57,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
+            Trait::Hash => expanded.extend(enum_hash(enm, span)),
             Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
@@ -155,6 +157,21 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
+fn struct_hash(strct: &Struct, span: Span) -> TokenStream {
+    let ident = &strct.name.rust;
+    let fields = strct.fields.iter().map(|field| &field.ident);
+
+    quote_spanned! {span=>
+        impl ::std::hash::Hash for #ident {
+            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
+                #(
+                    ::std::hash::Hash::hash(&self.#fields, state);
+                )*
+            }
+        }
+    }
+}
+
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
     let fields = strct.fields.iter().map(|field| &field.ident);
@@ -246,6 +263,18 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
     }
 }
 
+fn enum_hash(enm: &Enum, span: Span) -> TokenStream {
+    let ident = &enm.name.rust;
+
+    quote_spanned! {span=>
+        impl ::std::hash::Hash for #ident {
+            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
+                ::std::hash::Hash::hash(&self.repr, state);
+            }
+        }
+    }
+}
+
 fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e065a55..c218267 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -230,6 +230,19 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                     });
                 }
             }
+            Trait::Hash => {
+                let link_name = mangle::operator(&strct.name, "hash");
+                let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(this: &#ident) -> usize {
+                        let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
+                        ::std::hash::Hash::hash(this, &mut hasher);
+                        ::std::hash::Hasher::finish(&hasher) as usize
+                    }
+                });
+            }
             _ => {}
         }
     }
diff --git a/syntax/derive.rs b/syntax/derive.rs
index a8b6bde..1121211 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -13,6 +13,7 @@ pub enum Trait {
     Debug,
     Default,
     Eq,
+    Hash,
     Ord,
     PartialEq,
     PartialOrd,
@@ -26,6 +27,7 @@ impl Derive {
             "Debug" => Trait::Debug,
             "Default" => Trait::Default,
             "Eq" => Trait::Eq,
+            "Hash" => Trait::Hash,
             "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
             "PartialOrd" => Trait::PartialOrd,
@@ -50,6 +52,7 @@ impl AsRef<str> for Trait {
             Trait::Debug => "Debug",
             Trait::Default => "Default",
             Trait::Eq => "Eq",
+            Trait::Hash => "Hash",
             Trait::Ord => "Ord",
             Trait::PartialEq => "PartialEq",
             Trait::PartialOrd => "PartialOrd",
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 26cd3c0..0d395e3 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -26,7 +26,13 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
 }
 
 pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
-    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, "operator", operator)
+    join!(
+        receiver.namespace,
+        CXXBRIDGE,
+        receiver.cxx,
+        "operator",
+        operator,
+    )
 }
 
 // The C half of a function pointer trampoline.
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cb0f916..5427b89 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -25,7 +25,7 @@ pub mod ffi {
         msg: String,
     }
 
-    #[derive(Debug)]
+    #[derive(Debug, Hash)]
     enum Enum {
         AVal,
         BVal = 2020,
@@ -64,6 +64,7 @@ pub mod ffi {
     }
 
     #[namespace = "second"]
+    #[derive(Hash)]
     struct Second {
         i: i32,
         e: COwnedEnum,
@@ -184,6 +185,7 @@ pub mod ffi {
     }
 
     #[repr(u32)]
+    #[derive(Hash)]
     enum COwnedEnum {
         CVal1,
         CVal2,

From afdf3d736482fcc267824dee4cee883697d50e3b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 02:22:40 +0000
Subject: [PATCH 1610/2232] Use standard library's Hash derive


This avoids Clippy derive_hash_xor_eq warnings in generated code:

    error: you are implementing `Hash` explicitly but have derived `PartialEq`
      --> tests/ffi/lib.rs:28:21
       |
    28 |     #[derive(Debug, Hash)]
       |                     ^^^^
       |
       = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
    note: `PartialEq` implemented here
      --> tests/ffi/lib.rs:16:1
       |
    16 | #[cxx::bridge(namespace = "tests")]
       | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
       = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index f614add..a015ed0 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -16,7 +16,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
-            Trait::Hash => expanded.extend(struct_hash(strct, span)),
+            Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
             Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
@@ -57,7 +57,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
-            Trait::Hash => expanded.extend(enum_hash(enm, span)),
+            Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
@@ -157,21 +157,6 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream {
     }
 }
 
-fn struct_hash(strct: &Struct, span: Span) -> TokenStream {
-    let ident = &strct.name.rust;
-    let fields = strct.fields.iter().map(|field| &field.ident);
-
-    quote_spanned! {span=>
-        impl ::std::hash::Hash for #ident {
-            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
-                #(
-                    ::std::hash::Hash::hash(&self.#fields, state);
-                )*
-            }
-        }
-    }
-}
-
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
     let fields = strct.fields.iter().map(|field| &field.ident);
@@ -263,18 +248,6 @@ fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
     }
 }
 
-fn enum_hash(enm: &Enum, span: Span) -> TokenStream {
-    let ident = &enm.name.rust;
-
-    quote_spanned! {span=>
-        impl ::std::hash::Hash for #ident {
-            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
-                ::std::hash::Hash::hash(&self.repr, state);
-            }
-        }
-    }
-}
-
 fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
 

From 9008623a1ef59a0a7a2bde5b7f6d396cd930ea47 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 02:29:06 +0000
Subject: [PATCH 1611/2232] Merge pull request #522 from dtolnay/derive-hash


Support derive(Hash)
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ab9d3c0..873904d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -134,6 +134,8 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 _ => {}
             }
         }
+
+        write_std_specializations(out, apis);
     }
 
     for api in apis {
@@ -148,6 +150,36 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     }
 }
 
+fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
+    out.set_namespace(Default::default());
+    out.begin_block(Block::Namespace("std"));
+
+    for api in apis {
+        if let Api::Struct(strct) = api {
+            if derive::contains(&strct.derives, Trait::Hash) {
+                out.next_section();
+                let qualified = strct.name.to_fully_qualified();
+                writeln!(out, "template <> struct hash<{}> {{", qualified);
+                writeln!(
+                    out,
+                    "  size_t operator()(const {} &self) const noexcept {{",
+                    qualified,
+                );
+                let link_name = mangle::operator(&strct.name, "hash");
+                write!(out, "    return ::");
+                for name in &strct.name.namespace {
+                    write!(out, "{}::", name);
+                }
+                writeln!(out, "{}(self);", link_name);
+                writeln!(out, "  }}");
+                writeln!(out, "}};");
+            }
+        }
+    }
+
+    out.end_block(Block::Namespace("std"));
+}
+
 fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
     for api in apis {
         if let Api::Include(include) = api {
@@ -432,6 +464,15 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         }
     }
 
+    if derive::contains(&strct.derives, Trait::Hash) {
+        let link_name = mangle::operator(&strct.name, "hash");
+        writeln!(
+            out,
+            "size_t {}(const {} &) noexcept;",
+            link_name, strct.name.cxx,
+        );
+    }
+
     out.end_block(Block::ExternC);
 }
 
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index be8ad82..a015ed0 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -16,6 +16,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
             Trait::PartialOrd => expanded.extend(struct_partial_ord(strct, span)),
@@ -56,6 +57,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
+            Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
                 traits.push(quote_spanned!(span=> ::std::cmp::PartialEq));
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e065a55..c218267 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -230,6 +230,19 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                     });
                 }
             }
+            Trait::Hash => {
+                let link_name = mangle::operator(&strct.name, "hash");
+                let local_name = format_ident!("__operator_hash_{}", strct.name.rust);
+                operators.extend(quote_spanned! {span=>
+                    #[doc(hidden)]
+                    #[export_name = #link_name]
+                    extern "C" fn #local_name(this: &#ident) -> usize {
+                        let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
+                        ::std::hash::Hash::hash(this, &mut hasher);
+                        ::std::hash::Hasher::finish(&hasher) as usize
+                    }
+                });
+            }
             _ => {}
         }
     }
diff --git a/syntax/derive.rs b/syntax/derive.rs
index a8b6bde..1121211 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -13,6 +13,7 @@ pub enum Trait {
     Debug,
     Default,
     Eq,
+    Hash,
     Ord,
     PartialEq,
     PartialOrd,
@@ -26,6 +27,7 @@ impl Derive {
             "Debug" => Trait::Debug,
             "Default" => Trait::Default,
             "Eq" => Trait::Eq,
+            "Hash" => Trait::Hash,
             "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
             "PartialOrd" => Trait::PartialOrd,
@@ -50,6 +52,7 @@ impl AsRef<str> for Trait {
             Trait::Debug => "Debug",
             Trait::Default => "Default",
             Trait::Eq => "Eq",
+            Trait::Hash => "Hash",
             Trait::Ord => "Ord",
             Trait::PartialEq => "PartialEq",
             Trait::PartialOrd => "PartialOrd",
diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 26cd3c0..0d395e3 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -26,7 +26,13 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
 }
 
 pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
-    join!(receiver.namespace, CXXBRIDGE, receiver.cxx, "operator", operator)
+    join!(
+        receiver.namespace,
+        CXXBRIDGE,
+        receiver.cxx,
+        "operator",
+        operator,
+    )
 }
 
 // The C half of a function pointer trampoline.
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cb0f916..5427b89 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -25,7 +25,7 @@ pub mod ffi {
         msg: String,
     }
 
-    #[derive(Debug)]
+    #[derive(Debug, Hash)]
     enum Enum {
         AVal,
         BVal = 2020,
@@ -64,6 +64,7 @@ pub mod ffi {
     }
 
     #[namespace = "second"]
+    #[derive(Hash)]
     struct Second {
         i: i32,
         e: COwnedEnum,
@@ -184,6 +185,7 @@ pub mod ffi {
     }
 
     #[repr(u32)]
+    #[derive(Hash)]
     enum COwnedEnum {
         CVal1,
         CVal2,

From 2ab0574476af84bb03e67ca32750270196431543 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 02:30:07 +0000
Subject: [PATCH 1612/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 6cc37e8..4414319 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.51/src/**"]),
+    srcs = glob(["vendor/syn-1.0.52/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index ef9dba1..bbfa648 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.51/src/**"]),
+    srcs = glob(["vendor/syn-1.0.52/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 94bbb0f..b633f59 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.51"
+version = "1.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b4f34193997d92804d359ed09953e25d5138df6bcc055a71bf68ee89fdf9223"
+checksum = "6c1e438504729046a5cfae47f97c30d6d083c7d91d94603efdae3477fc070d4c"
 dependencies = [
  "proc-macro2",
  "quote",

From ecce017e140ed3b9cf7ed045b55e0fb847d5b949 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 02:31:15 +0000
Subject: [PATCH 1613/2232] Release 1.0.6


---

diff --git a/Cargo.toml b/Cargo.toml
index 63ad1e2..4d442ea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.5" # remember to update html_root_url
+version = "1.0.6" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.5", path = "macro" }
+cxxbridge-macro = { version = "=1.0.6", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.5", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.6", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.5", path = "gen/build" }
+cxx-build = { version = "=1.0.6", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index a3fba7f..87f6a5f 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.5"
+version = "1.0.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 618b41a..80adb6d 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.5"
+version = "1.0.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 1af6ae3..c7f54cc 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.5"
+version = "1.0.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 67aee37..5397af6 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.5"
+version = "0.7.6"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index b843879..e570f8b 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.5"
+version = "1.0.6"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 09a5259..e251a23 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.5")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.6")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b633f59..6754d53 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.5"
+version = "1.0.6"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.5"
+version = "1.0.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.5"
+version = "0.7.6"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.5"
+version = "1.0.6"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.5"
+version = "1.0.6"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.5"
+version = "1.0.6"
 dependencies = [
  "cxx",
  "proc-macro2",

From 16e2620fe51032d789770b489e27a9c6c27719ef Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 03:45:21 +0000
Subject: [PATCH 1614/2232] Add ExternType derive for opaque Rust types


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 22b0c9f..fe1664b 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -52,7 +52,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
 mod tests {
     use super::NamespaceEntries;
     use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Pair};
+    use crate::syntax::{Api, Doc, ExternType, Lang, Pair};
     use proc_macro2::{Ident, Span};
     use std::iter::FromIterator;
     use syn::Token;
@@ -126,7 +126,9 @@ mod tests {
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
         let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
         Api::CxxType(ExternType {
+            lang: Lang::Rust,
             doc: Doc::new(),
+            derives: Vec::new(),
             type_token: Token![type](Span::call_site()),
             name: Pair::new(ns, Ident::new(ident, Span::call_site())),
             semi_token: Token![;](Span::call_site()),
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index a015ed0..3379c9c 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -16,6 +16,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
             Trait::Debug => expanded.extend(struct_debug(strct, span)),
             Trait::Default => expanded.extend(struct_default(strct, span)),
             Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
+            Trait::ExternType => unreachable!(),
             Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(struct_ord(strct, span)),
             Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
@@ -57,6 +58,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
                 traits.push(quote_spanned!(span=> ::std::cmp::Eq));
                 has_eq = true;
             }
+            Trait::ExternType => unreachable!(),
             Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
             Trait::Ord => expanded.extend(enum_ord(enm, span)),
             Trait::PartialEq => {
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c218267..ae13beb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -617,9 +617,24 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
     let span = ident.span();
     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
 
-    quote_spanned! {span=>
+    let mut impls = quote_spanned! {span=>
         #unsafe_impl ::cxx::private::RustType for #ident {}
+    };
+
+    for derive in &ety.derives {
+        if derive.what == Trait::ExternType {
+            let type_id = type_id(&ety.name);
+            let span = derive.span;
+            impls.extend(quote_spanned! {span=>
+                unsafe impl ::cxx::ExternType for #ident {
+                    type Id = #type_id;
+                    type Kind = ::cxx::kind::Opaque;
+                }
+            });
+        }
     }
+
+    impls
 }
 
 fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
diff --git a/syntax/check.rs b/syntax/check.rs
index 725105d..a60332d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -232,6 +232,13 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
         }
     }
 
+    for derive in &strct.derives {
+        if derive.what == Trait::ExternType {
+            let msg = format!("derive({}) on shared struct is not supported", derive);
+            cx.error(derive, msg);
+        }
+    }
+
     for field in &strct.fields {
         if let Type::Fn(_) = field.ty {
             cx.error(
@@ -258,11 +265,9 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
     }
 
     for derive in &enm.derives {
-        if derive.what == Trait::Default {
-            cx.error(
-                derive,
-                "derive(Default) on shared enums is not supported yet",
-            );
+        if derive.what == Trait::Default || derive.what == Trait::ExternType {
+            let msg = format!("derive({}) on shared enum is not supported", derive);
+            cx.error(derive, msg);
         }
     }
 }
@@ -270,6 +275,21 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
 fn check_api_type(cx: &mut Check, ety: &ExternType) {
     check_reserved_name(cx, &ety.name.rust);
 
+    for derive in &ety.derives {
+        if derive.what == Trait::ExternType && ety.lang == Lang::Rust {
+            continue;
+        }
+        let lang = match ety.lang {
+            Lang::Rust => "Rust",
+            Lang::Cxx => "C++",
+        };
+        let msg = format!(
+            "derive({}) on opaque {} type is not supported yet",
+            derive, lang,
+        );
+        cx.error(derive, msg);
+    }
+
     if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 1121211..96b3eea 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -1,4 +1,5 @@
 use proc_macro2::{Ident, Span};
+use std::fmt::{self, Display};
 
 #[derive(Copy, Clone)]
 pub struct Derive {
@@ -13,6 +14,7 @@ pub enum Trait {
     Debug,
     Default,
     Eq,
+    ExternType,
     Hash,
     Ord,
     PartialEq,
@@ -27,6 +29,7 @@ impl Derive {
             "Debug" => Trait::Debug,
             "Default" => Trait::Default,
             "Eq" => Trait::Eq,
+            "ExternType" => Trait::ExternType,
             "Hash" => Trait::Hash,
             "Ord" => Trait::Ord,
             "PartialEq" => Trait::PartialEq,
@@ -52,6 +55,7 @@ impl AsRef<str> for Trait {
             Trait::Debug => "Debug",
             Trait::Default => "Default",
             Trait::Eq => "Eq",
+            Trait::ExternType => "ExternType",
             Trait::Hash => "Hash",
             Trait::Ord => "Ord",
             Trait::PartialEq => "PartialEq",
@@ -60,6 +64,12 @@ impl AsRef<str> for Trait {
     }
 }
 
+impl Display for Derive {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(self.what.as_ref())
+    }
+}
+
 pub fn contains(derives: &[Derive], query: Trait) -> bool {
     derives.iter().any(|derive| derive.what == query)
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index bd7efc0..e8288a9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -67,7 +67,9 @@ pub enum IncludeKind {
 }
 
 pub struct ExternType {
+    pub lang: Lang,
     pub doc: Doc,
+    pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
     pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a009e19..e46cdb4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -327,12 +327,14 @@ fn parse_extern_type(
     namespace: &Namespace,
 ) -> Api {
     let mut doc = Doc::new();
+    let mut derives = Vec::new();
     let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_type.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
+            derives: Some(&mut derives),
             namespace: Some(&mut namespace),
             ..Default::default()
         },
@@ -345,7 +347,9 @@ fn parse_extern_type(
         Lang::Rust => Api::RustType,
     };
     api_type(ExternType {
+        lang,
         doc,
+        derives,
         type_token,
         name: Pair::new(namespace, ident),
         semi_token,

From edff9c0d502ba7fe583666fb2fed2c94a7585ce6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 04:54:08 +0000
Subject: [PATCH 1615/2232] Suppress clippy too_many_arguments lint


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index b290058..6d44e5d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -52,6 +52,7 @@
     clippy::new_without_default,
     clippy::nonminimal_bool,
     clippy::or_fun_call,
+    clippy::too_many_arguments,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index e607030..2372c2c 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -5,6 +5,7 @@
     clippy::new_without_default,
     clippy::nonminimal_bool,
     clippy::or_fun_call,
+    clippy::too_many_arguments,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 506b007..dd7d515 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -13,6 +13,7 @@
     clippy::new_without_default,
     clippy::nonminimal_bool,
     clippy::or_fun_call,
+    clippy::too_many_arguments,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 89f2549..1498bbb 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -5,6 +5,7 @@
     clippy::nonminimal_bool,
     clippy::or_fun_call,
     clippy::single_match,
+    clippy::too_many_arguments,
     clippy::toplevel_ref_arg,
     clippy::useless_let_if_seq
 )]

From b7eb65e4280997adb27b5c1788c6953303aa13ac Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 04:54:22 +0000
Subject: [PATCH 1616/2232] Parse trait bounded extern types


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index fe1664b..1f4fc5d 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -131,6 +131,8 @@ mod tests {
             derives: Vec::new(),
             type_token: Token![type](Span::call_site()),
             name: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            colon_token: None,
+            bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
             trusted: false,
         })
diff --git a/syntax/check.rs b/syntax/check.rs
index a60332d..15e19b8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Trait, Ty1, Type, Types,
+    SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -43,12 +43,13 @@ fn do_typecheck(cx: &mut Check) {
 
     for api in cx.apis {
         match api {
+            Api::Include(_) => {}
             Api::Struct(strct) => check_api_struct(cx, strct),
             Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
+            Api::TypeAlias(alias) => check_api_type_alias(cx, alias),
             Api::Impl(imp) => check_api_impl(cx, imp),
-            Api::Include(_) | Api::TypeAlias(_) => {}
         }
     }
 }
@@ -290,6 +291,12 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
+    if !ety.bounds.is_empty() {
+        let bounds = &ety.bounds;
+        let span = quote!(#(#bounds)*);
+        cx.error(span, "extern type bounds are not implemented yet");
+    }
+
     if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
@@ -387,6 +394,13 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     check_multiple_arg_lifetimes(cx, efn);
 }
 
+fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
+    for derive in &alias.derives {
+        let msg = format!("derive({}) on extern type alias is not supported", derive);
+        cx.error(derive, msg);
+    }
+}
+
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
     if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
         if let Type::Ident(inner) = &ty.inner {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e8288a9..c688f55 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -72,6 +72,8 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub colon_token: Option<Token![:]>,
+    pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
     pub trusted: bool,
 }
@@ -108,6 +110,7 @@ pub struct ExternFn {
 
 pub struct TypeAlias {
     pub doc: Doc,
+    pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
     pub eq_token: Token![=],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e46cdb4..aa86a9f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,8 +3,8 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
-    Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
+    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
+    Lang, Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
     TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
@@ -14,8 +14,8 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
-    TypePath, TypeReference,
+    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
 };
 
 pub mod kw {
@@ -257,7 +257,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, &namespace) {
+                match parse_extern_verbatim(cx, tokens, lang, trusted, &namespace) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }
@@ -352,6 +352,8 @@ fn parse_extern_type(
         derives,
         type_token,
         name: Pair::new(namespace, ident),
+        colon_token: None,
+        bounds: Vec::new(),
         semi_token,
         trusted,
     })
@@ -518,10 +520,10 @@ fn parse_extern_verbatim(
     cx: &mut Errors,
     tokens: &TokenStream,
     lang: Lang,
+    trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    // type Alias = crate::path::to::Type;
-    let parse = |input: ParseStream| -> Result<TypeAlias> {
+    |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
@@ -531,41 +533,137 @@ fn parse_extern_verbatim(
             }
         };
         let ident: Ident = input.parse()?;
-        let eq_token: Token![=] = input.parse()?;
-        let ty: RustType = input.parse()?;
-        let semi_token: Token![;] = input.parse()?;
-        let mut doc = Doc::new();
-        let mut namespace = namespace.clone();
-        attrs::parse(
-            cx,
-            &attrs,
-            attrs::Parser {
-                doc: Some(&mut doc),
-                namespace: Some(&mut namespace),
-                ..Default::default()
-            },
-        );
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Token![=]) {
+            // type Alias = crate::path::to::Type;
+            parse_type_alias(cx, attrs, type_token, ident, input, lang, namespace)
+        } else if lookahead.peek(Token![:]) {
+            // type Opaque: Bound2 + Bound2;
+            parse_extern_type_bounded(
+                cx, attrs, type_token, ident, input, lang, trusted, namespace,
+            )
+        } else {
+            Err(lookahead.error())
+        }
+    }
+    .parse2(tokens.clone())
+}
 
-        Ok(TypeAlias {
-            doc,
-            type_token,
-            name: Pair::new(namespace, ident),
-            eq_token,
-            ty,
-            semi_token,
-        })
-    };
+fn parse_type_alias(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    type_token: Token![type],
+    ident: Ident,
+    input: ParseStream,
+    lang: Lang,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let eq_token: Token![=] = input.parse()?;
+    let ty: RustType = input.parse()?;
+    let semi_token: Token![;] = input.parse()?;
 
-    let type_alias = parse.parse2(tokens.clone())?;
-    match lang {
-        Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
-        Lang::Rust => {
-            let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
-            let span = quote!(#type_token #semi_token);
-            let msg = "type alias in extern \"Rust\" block is not supported";
-            Err(Error::new_spanned(span, msg))
+    let mut doc = Doc::new();
+    let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            derives: Some(&mut derives),
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
+    if lang == Lang::Rust {
+        let span = quote!(#type_token #semi_token);
+        let msg = "type alias in extern \"Rust\" block is not supported";
+        return Err(Error::new_spanned(span, msg));
+    }
+
+    Ok(Api::TypeAlias(TypeAlias {
+        doc,
+        derives,
+        type_token,
+        name: Pair::new(namespace, ident),
+        eq_token,
+        ty,
+        semi_token,
+    }))
+}
+
+fn parse_extern_type_bounded(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    type_token: Token![type],
+    ident: Ident,
+    input: ParseStream,
+    lang: Lang,
+    trusted: bool,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let colon_token: Token![:] = input.parse()?;
+    let mut bounds = Vec::new();
+    loop {
+        match input.parse()? {
+            TypeParamBound::Trait(TraitBound {
+                paren_token: None,
+                modifier: TraitBoundModifier::None,
+                lifetimes: None,
+                path,
+            }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
+                bounds.push(derive);
+                true
+            } else {
+                false
+            } => {}
+            bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
+                cx.error(bound, "unsupported trait");
+            }
+        }
+
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Token![+]) {
+            input.parse::<Token![+]>()?;
+        } else if lookahead.peek(Token![;]) {
+            break;
+        } else {
+            return Err(lookahead.error());
         }
     }
+    let semi_token: Token![;] = input.parse()?;
+
+    let mut doc = Doc::new();
+    let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            derives: Some(&mut derives),
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
+    let api_type = match lang {
+        Lang::Cxx => Api::CxxType,
+        Lang::Rust => Api::RustType,
+    };
+
+    Ok(api_type(ExternType {
+        lang,
+        doc,
+        derives,
+        type_token,
+        name: Pair::new(namespace, ident),
+        colon_token: Some(colon_token),
+        bounds,
+        semi_token,
+        trusted,
+    }))
 }
 
 fn parse_impl(imp: ItemImpl) -> Result<Api> {
diff --git a/tests/ui/extern_type_bound.rs b/tests/ui/extern_type_bound.rs
new file mode 100644
index 0000000..958accd
--- /dev/null
+++ b/tests/ui/extern_type_bound.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque: PartialEq + PartialOrd;
+    }
+}
+
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque: for<'de> Deserialize<'de>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_bound.stderr b/tests/ui/extern_type_bound.stderr
new file mode 100644
index 0000000..ca07ef7
--- /dev/null
+++ b/tests/ui/extern_type_bound.stderr
@@ -0,0 +1,11 @@
+error: extern type bounds are not implemented yet
+ --> $DIR/extern_type_bound.rs:4:22
+  |
+4 |         type Opaque: PartialEq + PartialOrd;
+  |                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unsupported trait
+  --> $DIR/extern_type_bound.rs:11:22
+   |
+11 |         type Opaque: for<'de> Deserialize<'de>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^

From ded2962f41aa2fb8b3e8aedd4d4242f56c49b131 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 28 2020 05:00:06 +0000
Subject: [PATCH 1617/2232] Merge pull request #523 from dtolnay/bound


Parse trait bounded extern types
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index fe1664b..1f4fc5d 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -131,6 +131,8 @@ mod tests {
             derives: Vec::new(),
             type_token: Token![type](Span::call_site()),
             name: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            colon_token: None,
+            bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
             trusted: false,
         })
diff --git a/syntax/check.rs b/syntax/check.rs
index a60332d..15e19b8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -3,7 +3,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Trait, Ty1, Type, Types,
+    SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -43,12 +43,13 @@ fn do_typecheck(cx: &mut Check) {
 
     for api in cx.apis {
         match api {
+            Api::Include(_) => {}
             Api::Struct(strct) => check_api_struct(cx, strct),
             Api::Enum(enm) => check_api_enum(cx, enm),
             Api::CxxType(ety) | Api::RustType(ety) => check_api_type(cx, ety),
             Api::CxxFunction(efn) | Api::RustFunction(efn) => check_api_fn(cx, efn),
+            Api::TypeAlias(alias) => check_api_type_alias(cx, alias),
             Api::Impl(imp) => check_api_impl(cx, imp),
-            Api::Include(_) | Api::TypeAlias(_) => {}
         }
     }
 }
@@ -290,6 +291,12 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
+    if !ety.bounds.is_empty() {
+        let bounds = &ety.bounds;
+        let span = quote!(#(#bounds)*);
+        cx.error(span, "extern type bounds are not implemented yet");
+    }
+
     if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
         let what = match reason {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
@@ -387,6 +394,13 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     check_multiple_arg_lifetimes(cx, efn);
 }
 
+fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
+    for derive in &alias.derives {
+        let msg = format!("derive({}) on extern type alias is not supported", derive);
+        cx.error(derive, msg);
+    }
+}
+
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
     if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
         if let Type::Ident(inner) = &ty.inner {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e8288a9..c688f55 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -72,6 +72,8 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub colon_token: Option<Token![:]>,
+    pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
     pub trusted: bool,
 }
@@ -108,6 +110,7 @@ pub struct ExternFn {
 
 pub struct TypeAlias {
     pub doc: Doc,
+    pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
     pub eq_token: Token![=],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e46cdb4..aa86a9f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -3,8 +3,8 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Array, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind, Lang,
-    Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
+    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
+    Lang, Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
     TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
@@ -14,8 +14,8 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, Type as RustType, TypeArray, TypeBareFn,
-    TypePath, TypeReference,
+    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
 };
 
 pub mod kw {
@@ -257,7 +257,7 @@ fn parse_foreign_mod(
                 }
             }
             ForeignItem::Verbatim(tokens) => {
-                match parse_extern_verbatim(cx, tokens, lang, &namespace) {
+                match parse_extern_verbatim(cx, tokens, lang, trusted, &namespace) {
                     Ok(api) => items.push(api),
                     Err(err) => cx.push(err),
                 }
@@ -352,6 +352,8 @@ fn parse_extern_type(
         derives,
         type_token,
         name: Pair::new(namespace, ident),
+        colon_token: None,
+        bounds: Vec::new(),
         semi_token,
         trusted,
     })
@@ -518,10 +520,10 @@ fn parse_extern_verbatim(
     cx: &mut Errors,
     tokens: &TokenStream,
     lang: Lang,
+    trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    // type Alias = crate::path::to::Type;
-    let parse = |input: ParseStream| -> Result<TypeAlias> {
+    |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
@@ -531,41 +533,137 @@ fn parse_extern_verbatim(
             }
         };
         let ident: Ident = input.parse()?;
-        let eq_token: Token![=] = input.parse()?;
-        let ty: RustType = input.parse()?;
-        let semi_token: Token![;] = input.parse()?;
-        let mut doc = Doc::new();
-        let mut namespace = namespace.clone();
-        attrs::parse(
-            cx,
-            &attrs,
-            attrs::Parser {
-                doc: Some(&mut doc),
-                namespace: Some(&mut namespace),
-                ..Default::default()
-            },
-        );
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Token![=]) {
+            // type Alias = crate::path::to::Type;
+            parse_type_alias(cx, attrs, type_token, ident, input, lang, namespace)
+        } else if lookahead.peek(Token![:]) {
+            // type Opaque: Bound2 + Bound2;
+            parse_extern_type_bounded(
+                cx, attrs, type_token, ident, input, lang, trusted, namespace,
+            )
+        } else {
+            Err(lookahead.error())
+        }
+    }
+    .parse2(tokens.clone())
+}
 
-        Ok(TypeAlias {
-            doc,
-            type_token,
-            name: Pair::new(namespace, ident),
-            eq_token,
-            ty,
-            semi_token,
-        })
-    };
+fn parse_type_alias(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    type_token: Token![type],
+    ident: Ident,
+    input: ParseStream,
+    lang: Lang,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let eq_token: Token![=] = input.parse()?;
+    let ty: RustType = input.parse()?;
+    let semi_token: Token![;] = input.parse()?;
 
-    let type_alias = parse.parse2(tokens.clone())?;
-    match lang {
-        Lang::Cxx => Ok(Api::TypeAlias(type_alias)),
-        Lang::Rust => {
-            let (type_token, semi_token) = (type_alias.type_token, type_alias.semi_token);
-            let span = quote!(#type_token #semi_token);
-            let msg = "type alias in extern \"Rust\" block is not supported";
-            Err(Error::new_spanned(span, msg))
+    let mut doc = Doc::new();
+    let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            derives: Some(&mut derives),
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
+    if lang == Lang::Rust {
+        let span = quote!(#type_token #semi_token);
+        let msg = "type alias in extern \"Rust\" block is not supported";
+        return Err(Error::new_spanned(span, msg));
+    }
+
+    Ok(Api::TypeAlias(TypeAlias {
+        doc,
+        derives,
+        type_token,
+        name: Pair::new(namespace, ident),
+        eq_token,
+        ty,
+        semi_token,
+    }))
+}
+
+fn parse_extern_type_bounded(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    type_token: Token![type],
+    ident: Ident,
+    input: ParseStream,
+    lang: Lang,
+    trusted: bool,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let colon_token: Token![:] = input.parse()?;
+    let mut bounds = Vec::new();
+    loop {
+        match input.parse()? {
+            TypeParamBound::Trait(TraitBound {
+                paren_token: None,
+                modifier: TraitBoundModifier::None,
+                lifetimes: None,
+                path,
+            }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
+                bounds.push(derive);
+                true
+            } else {
+                false
+            } => {}
+            bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
+                cx.error(bound, "unsupported trait");
+            }
+        }
+
+        let lookahead = input.lookahead1();
+        if lookahead.peek(Token![+]) {
+            input.parse::<Token![+]>()?;
+        } else if lookahead.peek(Token![;]) {
+            break;
+        } else {
+            return Err(lookahead.error());
         }
     }
+    let semi_token: Token![;] = input.parse()?;
+
+    let mut doc = Doc::new();
+    let mut derives = Vec::new();
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            derives: Some(&mut derives),
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
+    let api_type = match lang {
+        Lang::Cxx => Api::CxxType,
+        Lang::Rust => Api::RustType,
+    };
+
+    Ok(api_type(ExternType {
+        lang,
+        doc,
+        derives,
+        type_token,
+        name: Pair::new(namespace, ident),
+        colon_token: Some(colon_token),
+        bounds,
+        semi_token,
+        trusted,
+    }))
 }
 
 fn parse_impl(imp: ItemImpl) -> Result<Api> {
diff --git a/tests/ui/extern_type_bound.rs b/tests/ui/extern_type_bound.rs
new file mode 100644
index 0000000..958accd
--- /dev/null
+++ b/tests/ui/extern_type_bound.rs
@@ -0,0 +1,15 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque: PartialEq + PartialOrd;
+    }
+}
+
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Opaque: for<'de> Deserialize<'de>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_bound.stderr b/tests/ui/extern_type_bound.stderr
new file mode 100644
index 0000000..ca07ef7
--- /dev/null
+++ b/tests/ui/extern_type_bound.stderr
@@ -0,0 +1,11 @@
+error: extern type bounds are not implemented yet
+ --> $DIR/extern_type_bound.rs:4:22
+  |
+4 |         type Opaque: PartialEq + PartialOrd;
+  |                      ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unsupported trait
+  --> $DIR/extern_type_bound.rs:11:22
+   |
+11 |         type Opaque: for<'de> Deserialize<'de>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^

From 1dcd53e4a743afbc19ad34122782051f83bee8b8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 29 2020 22:46:55 +0000
Subject: [PATCH 1618/2232] Allow instance methods with same name on different types in same bridge


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ae13beb..63fe888 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -665,8 +665,14 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
-    let local_name = format_ident!("__{}", efn.name.rust);
-    let catch_unwind_label = format!("::{}", efn.name.rust);
+    let local_name = match &efn.receiver {
+        None => format_ident!("__{}", efn.name.rust),
+        Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust),
+    };
+    let catch_unwind_label = match &efn.receiver {
+        None => format!("::{}", efn.name.rust),
+        Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust),
+    };
     let invoke = Some(&efn.name.rust);
     expand_rust_function_shim_impl(
         efn,

From 65be3eb9ee50d6fe831d7353a952cbf2b9e5e7b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 29 2020 22:56:04 +0000
Subject: [PATCH 1619/2232] Merge pull request #528 from dtolnay/samemethod


Allow instance methods with same name on different types in same bridge
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index ae13beb..63fe888 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -665,8 +665,14 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
-    let local_name = format_ident!("__{}", efn.name.rust);
-    let catch_unwind_label = format!("::{}", efn.name.rust);
+    let local_name = match &efn.receiver {
+        None => format_ident!("__{}", efn.name.rust),
+        Some(receiver) => format_ident!("__{}__{}", receiver.ty.rust, efn.name.rust),
+    };
+    let catch_unwind_label = match &efn.receiver {
+        None => format!("::{}", efn.name.rust),
+        Some(receiver) => format!("::{}::{}", receiver.ty.rust, efn.name.rust),
+    };
     let invoke = Some(&efn.name.rust);
     expand_rust_function_shim_impl(
         efn,

From 45e4a80875afa5beda807126e471c7ad56fb67e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 29 2020 22:57:08 +0000
Subject: [PATCH 1620/2232] Release 1.0.7


---

diff --git a/Cargo.toml b/Cargo.toml
index 4d442ea..899a481 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.6" # remember to update html_root_url
+version = "1.0.7" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.6", path = "macro" }
+cxxbridge-macro = { version = "=1.0.7", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.6", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.7", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.6", path = "gen/build" }
+cxx-build = { version = "=1.0.7", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 87f6a5f..c50ca37 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.6"
+version = "1.0.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 80adb6d..ebcb93e 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.6"
+version = "1.0.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index c7f54cc..5eb5b13 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.6"
+version = "1.0.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 5397af6..ff05489 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.6"
+version = "0.7.7"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e570f8b..1e16728 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.6"
+version = "1.0.7"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index e251a23..fd38c27 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.6")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.7")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6754d53..55c3ba0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.6"
+version = "1.0.7"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.6"
+version = "1.0.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.6"
+version = "0.7.7"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.6"
+version = "1.0.7"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.6"
+version = "1.0.7"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.6"
+version = "1.0.7"
 dependencies = [
  "cxx",
  "proc-macro2",

From 902b76f9a6fd8dfbd5dcbc0892b4538921978d6d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 01:43:35 +0000
Subject: [PATCH 1621/2232] Fill in some ExternType impls for builtin types


---

diff --git a/src/extern_type.rs b/src/extern_type.rs
index d7634c4..99e0cb1 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,4 +1,6 @@
 use self::kind::{Kind, Opaque, Trivial};
+use crate::CxxString;
+use alloc::string::String;
 
 /// A type for which the layout is determined by its C++ definition.
 ///
@@ -181,3 +183,35 @@ pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
 
 #[doc(hidden)]
 pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
+
+macro_rules! impl_extern_type {
+    ($([$kind:ident] $($ty:path = $cxxpath:literal)*)*) => {
+        $($(
+            unsafe impl ExternType for $ty {
+                type Id = crate::type_id!($cxxpath);
+                type Kind = $kind;
+            }
+        )*)*
+    };
+}
+
+impl_extern_type! {
+    [Trivial]
+    bool = "bool"
+    u8 = "std::uint8_t"
+    u16 = "std::uint16_t"
+    u32 = "std::uint32_t"
+    u64 = "std::uint64_t"
+    usize = "size_t"
+    i8 = "std::int8_t"
+    i16 = "std::int16_t"
+    i32 = "std::int32_t"
+    i64 = "std::int64_t"
+    isize = "rust::isize"
+    f32 = "float"
+    f64 = "double"
+    String = "rust::String"
+
+    [Opaque]
+    CxxString = "std::string"
+}
diff --git a/src/lib.rs b/src/lib.rs
index fd38c27..dd4cbd4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -386,6 +386,7 @@
 extern crate link_cplusplus;
 
 extern crate alloc;
+extern crate self as cxx;
 extern crate std;
 
 #[macro_use]

From e468f05d8fbe71db56384211aafced25f0321571 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 03:39:35 +0000
Subject: [PATCH 1622/2232] Link to bindings documentation on website from header


---

diff --git a/include/cxx.h b/include/cxx.h
index 8624233..507b466 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -27,6 +27,7 @@ class impl;
 
 #ifndef CXXBRIDGE1_RUST_STRING
 #define CXXBRIDGE1_RUST_STRING
+// https://cxx.rs/binding/string.html
 class String final {
 public:
   String() noexcept;
@@ -68,6 +69,7 @@ private:
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR
+// https://cxx.rs/binding/str.html
 class Str final {
 public:
   Str() noexcept;
@@ -118,6 +120,7 @@ struct copy_assignable_if<false> {
 };
 } // namespace detail
 
+// https://cxx.rs/binding/slice.html
 template <typename T>
 class Slice final
     : private detail::copy_assignable_if<std::is_const<T>::value> {
@@ -171,6 +174,7 @@ private:
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
+// https://cxx.rs/binding/box.html
 template <typename T>
 class Box final {
 public:
@@ -212,6 +216,7 @@ private:
 #endif // CXXBRIDGE1_RUST_BOX
 
 #ifndef CXXBRIDGE1_RUST_VEC
+// https://cxx.rs/binding/vec.html
 template <typename T>
 class Vec final {
 public:
@@ -288,6 +293,7 @@ private:
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN
+// https://cxx.rs/binding/fn.html
 template <typename Signature, bool Throws = false>
 class Fn;
 
@@ -308,6 +314,7 @@ using TryFn = Fn<Signature, true>;
 
 #ifndef CXXBRIDGE1_RUST_ERROR
 #define CXXBRIDGE1_RUST_ERROR
+// https://cxx.rs/binding/result.html
 class Error final : public std::exception {
 public:
   Error(const Error &);

From f031c32dca5b1554dc96b18c79a069541d95159d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 03:41:33 +0000
Subject: [PATCH 1623/2232] Remove TryFn since throwing fn ptr are not implemented yet


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 873904d..5413b68 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1128,7 +1128,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Fn(f) => {
-            write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
+            write!(out, "::rust::Fn<");
             match &f.ret {
                 Some(ret) => write_type(out, ret),
                 None => write!(out, "void"),
diff --git a/include/cxx.h b/include/cxx.h
index 507b466..fe45121 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -294,22 +294,19 @@ private:
 
 #ifndef CXXBRIDGE1_RUST_FN
 // https://cxx.rs/binding/fn.html
-template <typename Signature, bool Throws = false>
+template <typename Signature>
 class Fn;
 
-template <typename Ret, typename... Args, bool Throws>
-class Fn<Ret(Args...), Throws> final {
+template <typename Ret, typename... Args>
+class Fn<Ret(Args...)> final {
 public:
-  Ret operator()(Args... args) const noexcept(!Throws);
+  Ret operator()(Args... args) const noexcept;
   Fn operator*() const noexcept;
 
 private:
-  Ret (*trampoline)(Args..., void *fn) noexcept(!Throws);
+  Ret (*trampoline)(Args..., void *fn) noexcept;
   void *fn;
 };
-
-template <typename Signature>
-using TryFn = Fn<Signature, true>;
 #endif // CXXBRIDGE1_RUST_FN
 
 #ifndef CXXBRIDGE1_RUST_ERROR
@@ -388,10 +385,8 @@ using box = Box<T>;
 template <typename T>
 using vec = Vec<T>;
 using error = Error;
-template <typename Signature, bool Throws = false>
-using fn = Fn<Signature, Throws>;
 template <typename Signature>
-using try_fn = TryFn<Signature>;
+using fn = Fn<Signature>;
 template <typename T>
 using is_relocatable = IsRelocatable<T>;
 
@@ -408,13 +403,13 @@ void panic [[noreturn]] (const char *msg);
 
 #ifndef CXXBRIDGE1_RUST_FN
 #define CXXBRIDGE1_RUST_FN
-template <typename Ret, typename... Args, bool Throws>
-Ret Fn<Ret(Args...), Throws>::operator()(Args... args) const noexcept(!Throws) {
+template <typename Ret, typename... Args>
+Ret Fn<Ret(Args...)>::operator()(Args... args) const noexcept {
   return (*this->trampoline)(std::move(args)..., this->fn);
 }
 
-template <typename Ret, typename... Args, bool Throws>
-Fn<Ret(Args...), Throws> Fn<Ret(Args...), Throws>::operator*() const noexcept {
+template <typename Ret, typename... Args>
+Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept {
   return *this;
 }
 #endif // CXXBRIDGE1_RUST_FN

From 828e513a9466f9b3a9cd4f8a8979143830d6f6af Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 04:41:26 +0000
Subject: [PATCH 1624/2232] Add Str(const String &) noexcept constructor


---

diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index b0a99b4..93e9750 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -15,6 +15,7 @@ class Str final {
 public:
   Str() noexcept;
   Str(const Str &) noexcept;
+  Str(const String &) noexcept;
 
   // Throws std::invalid_argument if not utf-8.
   Str(const std::string &);
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8741e2d..5182e01 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -115,6 +115,11 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::AnonymousNamespace);
     }
 
+    if builtin.rust_str && !builtin.rust_string {
+        out.next_section();
+        writeln!(out, "class String;");
+    }
+
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
     ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
diff --git a/include/cxx.h b/include/cxx.h
index fe45121..e40876d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -73,6 +73,7 @@ private:
 class Str final {
 public:
   Str() noexcept;
+  Str(const String &) noexcept;
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
diff --git a/src/cxx.cc b/src/cxx.cc
index ef5db8f..c9e2151 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -150,6 +150,8 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 
 Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
+Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
+
 static void initStr(const char *ptr, size_t len) {
   if (!cxxbridge1$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");

From c316a598439d2cfabdd7f4d86745fbbe5a17848c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 04:52:45 +0000
Subject: [PATCH 1625/2232] Merge pull request #530 from dtolnay/str-string


Add Str(const String &) noexcept constructor
---

diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index b0a99b4..93e9750 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -15,6 +15,7 @@ class Str final {
 public:
   Str() noexcept;
   Str(const Str &) noexcept;
+  Str(const String &) noexcept;
 
   // Throws std::invalid_argument if not utf-8.
   Str(const std::string &);
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8741e2d..5182e01 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -115,6 +115,11 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::AnonymousNamespace);
     }
 
+    if builtin.rust_str && !builtin.rust_string {
+        out.next_section();
+        writeln!(out, "class String;");
+    }
+
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
     ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
diff --git a/include/cxx.h b/include/cxx.h
index fe45121..e40876d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -73,6 +73,7 @@ private:
 class Str final {
 public:
   Str() noexcept;
+  Str(const String &) noexcept;
   Str(const std::string &);
   Str(const char *);
   Str(const char *, size_t);
diff --git a/src/cxx.cc b/src/cxx.cc
index ef5db8f..c9e2151 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -150,6 +150,8 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
 
 Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
+Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
+
 static void initStr(const char *ptr, size_t len) {
   if (!cxxbridge1$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");

From 76dfe624d0b61b3c4cbfd7a73e702d5d2842665b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 05:50:54 +0000
Subject: [PATCH 1626/2232] Pull in syn 1.0.53 for negative impl support


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ebcb93e..d525407 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -18,7 +18,7 @@ lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 scratch = "1.0"
-syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
 cxx-gen = { version = "0.7", path = "../lib" }
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 5eb5b13..efe30fa 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -20,7 +20,7 @@ clap = "2.33"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index ff05489..71eabfa 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -15,7 +15,7 @@ cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-syn = { version = "1.0.20", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 1e16728..e10d8c2 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -17,7 +17,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0.4"
-syn = { version = "1.0.20", features = ["full"] }
+syn = { version = "1.0.53", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "1.0", path = ".." }
diff --git a/third-party/BUCK b/third-party/BUCK
index 4414319..0a2a665 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.52/src/**"]),
+    srcs = glob(["vendor/syn-1.0.53/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index bbfa648..79999d3 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.52/src/**"]),
+    srcs = glob(["vendor/syn-1.0.53/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 55c3ba0..16970b8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.52"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c1e438504729046a5cfae47f97c30d6d083c7d91d94603efdae3477fc070d4c"
+checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
 dependencies = [
  "proc-macro2",
  "quote",

From 028d3d23f9c11be9c8d0a791dba36f905698f294 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 05:50:54 +0000
Subject: [PATCH 1627/2232] Parse negative impls


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 15e19b8..2ebbf05 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -402,7 +402,15 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
-    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = &imp.ty {
+    let ty = &imp.ty;
+
+    if let Some(negative) = imp.negative_token {
+        let span = quote!(#negative #ty);
+        cx.error(span, "negative impl is not supported yet");
+        return;
+    }
+
+    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = ty {
         if let Type::Ident(inner) = &ty.inner {
             if Atom::from(&inner.rust).is_none() {
                 return;
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4de3c29..73cb1d9 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -342,9 +342,14 @@ impl Hash for Impl {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Impl {
             impl_token: _,
+            negative,
             ty,
             brace_token: _,
+            negative_token: _,
         } = self;
+        if *negative {
+            negative.hash(state);
+        }
         ty.hash(state);
     }
 }
@@ -355,15 +360,19 @@ impl PartialEq for Impl {
     fn eq(&self, other: &Impl) -> bool {
         let Impl {
             impl_token: _,
+            negative,
             ty,
             brace_token: _,
+            negative_token: _,
         } = self;
         let Impl {
             impl_token: _,
+            negative: negative2,
             ty: ty2,
             brace_token: _,
+            negative_token: _,
         } = other;
-        ty == ty2
+        negative == negative2 && ty == ty2
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c688f55..e8bd290 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -120,8 +120,10 @@ pub struct TypeAlias {
 
 pub struct Impl {
     pub impl_token: Token![impl],
+    pub negative: bool,
     pub ty: Type,
     pub brace_token: Brace,
+    pub negative_token: Option<Token![!]>,
 }
 
 pub struct Signature {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index aa86a9f..a3f50ec 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -673,8 +673,8 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         return Err(Error::new_spanned(span, "expected an empty impl block"));
     }
 
-    let self_ty = &imp.self_ty;
     if let Some((bang, path, for_token)) = &imp.trait_ {
+        let self_ty = &imp.self_ty;
         let span = quote!(#bang #path #for_token #self_ty);
         return Err(Error::new_spanned(
             span,
@@ -690,10 +690,27 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         ));
     }
 
+    let mut negative_token = None;
+    let mut self_ty = *imp.self_ty;
+    if let RustType::Verbatim(ty) = &self_ty {
+        let mut iter = ty.clone().into_iter();
+        if let Some(TokenTree::Punct(punct)) = iter.next() {
+            if punct.as_char() == '!' {
+                let ty = iter.collect::<TokenStream>();
+                if !ty.is_empty() {
+                    negative_token = Some(Token![!](punct.span()));
+                    self_ty = syn::parse2(ty)?;
+                }
+            }
+        }
+    }
+
     Ok(Api::Impl(Impl {
         impl_token: imp.impl_token,
+        negative: negative_token.is_some(),
         ty: parse_type(&self_ty)?,
         brace_token: imp.brace_token,
+        negative_token,
     }))
 }
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 377fd4c..edbf818 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -148,6 +148,7 @@ impl ToTokens for ExternFn {
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.impl_token.to_tokens(tokens);
+        self.negative_token.to_tokens(tokens);
         self.ty.to_tokens(tokens);
         self.brace_token.surround(tokens, |_tokens| {});
     }

From ff86dce34263641b096ae9df8f3b696981283500 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 06:37:49 +0000
Subject: [PATCH 1628/2232] Add comparison operators for Str and String


---

diff --git a/include/cxx.h b/include/cxx.h
index e40876d..31b34fc 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -59,6 +59,13 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 
+  bool operator==(const String &) const noexcept;
+  bool operator!=(const String &) const noexcept;
+  bool operator<(const String &) const noexcept;
+  bool operator<=(const String &) const noexcept;
+  bool operator>(const String &) const noexcept;
+  bool operator>=(const String &) const noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   String(unsafe_bitcopy_t, const String &) noexcept;
 
@@ -98,6 +105,13 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 
+  bool operator==(const Str &) const noexcept;
+  bool operator!=(const Str &) const noexcept;
+  bool operator<(const Str &) const noexcept;
+  bool operator<=(const Str &) const noexcept;
+  bool operator>(const Str &) const noexcept;
+  bool operator>=(const Str &) const noexcept;
+
 private:
   friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
diff --git a/src/cxx.cc b/src/cxx.cc
index c9e2151..ac10df1 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,4 +1,5 @@
 #include "../include/cxx.h"
+#include <algorithm>
 #include <cassert>
 #include <cstring>
 #include <exception>
@@ -140,6 +141,30 @@ String::const_iterator String::cend() const noexcept {
   return this->data() + this->size();
 }
 
+bool String::operator==(const String &rhs) const noexcept {
+  return rust::Str(*this) == rust::Str(rhs);
+}
+
+bool String::operator!=(const String &rhs) const noexcept {
+  return rust::Str(*this) != rust::Str(rhs);
+}
+
+bool String::operator<(const String &rhs) const noexcept {
+  return rust::Str(*this) < rust::Str(rhs);
+}
+
+bool String::operator<=(const String &rhs) const noexcept {
+  return rust::Str(*this) <= rust::Str(rhs);
+}
+
+bool String::operator>(const String &rhs) const noexcept {
+  return rust::Str(*this) > rust::Str(rhs);
+}
+
+bool String::operator>=(const String &rhs) const noexcept {
+  return rust::Str(*this) >= rust::Str(rhs);
+}
+
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
 
@@ -186,6 +211,39 @@ Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
 
 Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
 
+bool Str::operator==(const Str &rhs) const noexcept {
+  return this->len == rhs.len &&
+         std::equal(this->begin(), this->end(), rhs.begin());
+}
+
+bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
+
+bool Str::operator<(const Str &rhs) const noexcept {
+  return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
+                                      rhs.end());
+}
+
+bool Str::operator<=(const Str &rhs) const noexcept {
+  // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
+  // without Undefined Behavior on C++11 if rhs is shorter than *this.
+  const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
+                 rend = rhs.end();
+  while (liter != lend && riter != rend && *liter == *riter) {
+    ++liter, ++riter;
+  }
+  if (liter == lend) {
+    return true; // equal or *this is a prefix of rhs
+  } else if (riter == rend) {
+    return false; // rhs is a prefix of *this
+  } else {
+    return *liter <= *riter;
+  }
+}
+
+bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
+
+bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From c0674ccbabb55c44d799a201f4e62ea0efd973e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 06:47:17 +0000
Subject: [PATCH 1629/2232] Add string comparison tests


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 340dc9c..934e58e 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -6,6 +6,7 @@
 #include <numeric>
 #include <stdexcept>
 #include <string>
+#include <tuple>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -656,6 +657,24 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(Shared{1} == Shared{1});
   ASSERT(Shared{1} != Shared{2});
 
+  rust::String first = "first", second = "second", sec = "sec";
+  bool (rust::String::*cmp)(const rust::String &) const;
+  bool first_first, first_second, sec_second, second_sec;
+  for (auto test : (std::tuple<decltype(cmp), bool, bool, bool, bool>[]) {
+    {&rust::String::operator==, true, false, false, false},
+    {&rust::String::operator!=, false, true, true, true},
+    {&rust::String::operator<, false, true, true, false},
+    {&rust::String::operator<=, true, true, true, false},
+    {&rust::String::operator>, false, false, false, true},
+    {&rust::String::operator>=, true, false, false, true},
+  }) {
+    std::tie(cmp, first_first, first_second, sec_second, second_sec) = test;
+    ASSERT((first.*cmp)(first) == first_first);
+    ASSERT((first.*cmp)(second) == first_second);
+    ASSERT((sec.*cmp)(second) == sec_second);
+    ASSERT((second.*cmp)(sec) == second_sec);
+  }
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From b9dd936be9a8033ef3d05b9a2069d42bedfeb3e8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 06:47:18 +0000
Subject: [PATCH 1630/2232] Add string comparison operators to website


---

diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 93e9750..999727c 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -37,6 +37,13 @@ public:
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
+
+  bool operator==(const Str &) const noexcept;
+  bool operator!=(const Str &) const noexcept;
+  bool operator<(const Str &) const noexcept;
+  bool operator<=(const Str &) const noexcept;
+  bool operator>(const Str &) const noexcept;
+  bool operator>=(const Str &) const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 47a2b96..c4a1b6a 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -42,6 +42,13 @@ public:
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
+
+  bool operator==(const String &) const noexcept;
+  bool operator!=(const String &) const noexcept;
+  bool operator<(const String &) const noexcept;
+  bool operator<=(const String &) const noexcept;
+  bool operator>(const String &) const noexcept;
+  bool operator>=(const String &) const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const String &);

From 2ecd4fd921b17c2b39747e02c521dece74ffbde6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 06:56:05 +0000
Subject: [PATCH 1631/2232] Change string comparison test to compile on MSVC


Error from MSVC:

> a parenthesized type followed by an initializer list is a non-standard
> explicit type conversion syntax

---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 934e58e..244c6c0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -660,7 +660,8 @@ extern "C" const char *cxx_run_test() noexcept {
   rust::String first = "first", second = "second", sec = "sec";
   bool (rust::String::*cmp)(const rust::String &) const;
   bool first_first, first_second, sec_second, second_sec;
-  for (auto test : (std::tuple<decltype(cmp), bool, bool, bool, bool>[]) {
+  for (auto test : {
+    std::tuple<decltype(cmp), bool, bool, bool, bool>
     {&rust::String::operator==, true, false, false, false},
     {&rust::String::operator!=, false, true, true, true},
     {&rust::String::operator<, false, true, true, false},

From 861e476a66586241de2839e60e71bae8fc7061df Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 07:10:01 +0000
Subject: [PATCH 1632/2232] Merge pull request #531 from dtolnay/cmp


Add comparison operators for Str and String
---

diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 93e9750..999727c 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -37,6 +37,13 @@ public:
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
+
+  bool operator==(const Str &) const noexcept;
+  bool operator!=(const Str &) const noexcept;
+  bool operator<(const Str &) const noexcept;
+  bool operator<=(const Str &) const noexcept;
+  bool operator>(const Str &) const noexcept;
+  bool operator>=(const Str &) const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 47a2b96..c4a1b6a 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -42,6 +42,13 @@ public:
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
+
+  bool operator==(const String &) const noexcept;
+  bool operator!=(const String &) const noexcept;
+  bool operator<(const String &) const noexcept;
+  bool operator<=(const String &) const noexcept;
+  bool operator>(const String &) const noexcept;
+  bool operator>=(const String &) const noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const String &);
diff --git a/include/cxx.h b/include/cxx.h
index e40876d..31b34fc 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -59,6 +59,13 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 
+  bool operator==(const String &) const noexcept;
+  bool operator!=(const String &) const noexcept;
+  bool operator<(const String &) const noexcept;
+  bool operator<=(const String &) const noexcept;
+  bool operator>(const String &) const noexcept;
+  bool operator>=(const String &) const noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   String(unsafe_bitcopy_t, const String &) noexcept;
 
@@ -98,6 +105,13 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 
+  bool operator==(const Str &) const noexcept;
+  bool operator!=(const Str &) const noexcept;
+  bool operator<(const Str &) const noexcept;
+  bool operator<=(const Str &) const noexcept;
+  bool operator>(const Str &) const noexcept;
+  bool operator>=(const Str &) const noexcept;
+
 private:
   friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
diff --git a/src/cxx.cc b/src/cxx.cc
index c9e2151..ac10df1 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,4 +1,5 @@
 #include "../include/cxx.h"
+#include <algorithm>
 #include <cassert>
 #include <cstring>
 #include <exception>
@@ -140,6 +141,30 @@ String::const_iterator String::cend() const noexcept {
   return this->data() + this->size();
 }
 
+bool String::operator==(const String &rhs) const noexcept {
+  return rust::Str(*this) == rust::Str(rhs);
+}
+
+bool String::operator!=(const String &rhs) const noexcept {
+  return rust::Str(*this) != rust::Str(rhs);
+}
+
+bool String::operator<(const String &rhs) const noexcept {
+  return rust::Str(*this) < rust::Str(rhs);
+}
+
+bool String::operator<=(const String &rhs) const noexcept {
+  return rust::Str(*this) <= rust::Str(rhs);
+}
+
+bool String::operator>(const String &rhs) const noexcept {
+  return rust::Str(*this) > rust::Str(rhs);
+}
+
+bool String::operator>=(const String &rhs) const noexcept {
+  return rust::Str(*this) >= rust::Str(rhs);
+}
+
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
 
@@ -186,6 +211,39 @@ Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
 
 Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
 
+bool Str::operator==(const Str &rhs) const noexcept {
+  return this->len == rhs.len &&
+         std::equal(this->begin(), this->end(), rhs.begin());
+}
+
+bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); }
+
+bool Str::operator<(const Str &rhs) const noexcept {
+  return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(),
+                                      rhs.end());
+}
+
+bool Str::operator<=(const Str &rhs) const noexcept {
+  // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except
+  // without Undefined Behavior on C++11 if rhs is shorter than *this.
+  const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(),
+                 rend = rhs.end();
+  while (liter != lend && riter != rend && *liter == *riter) {
+    ++liter, ++riter;
+  }
+  if (liter == lend) {
+    return true; // equal or *this is a prefix of rhs
+  } else if (riter == rend) {
+    return false; // rhs is a prefix of *this
+  } else {
+    return *liter <= *riter;
+  }
+}
+
+bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
+
+bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 340dc9c..244c6c0 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -6,6 +6,7 @@
 #include <numeric>
 #include <stdexcept>
 #include <string>
+#include <tuple>
 
 extern "C" void cxx_test_suite_set_correct() noexcept;
 extern "C" tests::R *cxx_test_suite_get_box() noexcept;
@@ -656,6 +657,25 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(Shared{1} == Shared{1});
   ASSERT(Shared{1} != Shared{2});
 
+  rust::String first = "first", second = "second", sec = "sec";
+  bool (rust::String::*cmp)(const rust::String &) const;
+  bool first_first, first_second, sec_second, second_sec;
+  for (auto test : {
+    std::tuple<decltype(cmp), bool, bool, bool, bool>
+    {&rust::String::operator==, true, false, false, false},
+    {&rust::String::operator!=, false, true, true, true},
+    {&rust::String::operator<, false, true, true, false},
+    {&rust::String::operator<=, true, true, true, false},
+    {&rust::String::operator>, false, false, false, true},
+    {&rust::String::operator>=, true, false, false, true},
+  }) {
+    std::tie(cmp, first_first, first_second, sec_second, second_sec) = test;
+    ASSERT((first.*cmp)(first) == first_first);
+    ASSERT((first.*cmp)(second) == first_second);
+    ASSERT((sec.*cmp)(second) == sec_second);
+    ASSERT((second.*cmp)(sec) == second_sec);
+  }
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From f799b3781cb7405928614547ceab8a8330241961 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 08:11:30 +0000
Subject: [PATCH 1633/2232] Add std::initializer_list constructor for rust::Vec


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 5820001..aef9527 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -6,6 +6,7 @@
 ```cpp,hidelines
 // rust/cxx.h
 #
+# #include <initializer_list>
 # #include <iterator>
 # #include <type_traits>
 #
@@ -17,6 +18,7 @@ public:
   using value_type = T;
 
   Vec() noexcept;
+  Vec(std::initializer_list<T>);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 5182e01..837761d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -71,7 +71,9 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_vec {
+        include.algorithm = true;
         include.array = true;
+        include.initializer_list = true;
         include.iterator = true;
         include.new = true;
         include.type_traits = true;
diff --git a/gen/src/include.rs b/gen/src/include.rs
index accaaee..9db95be 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -21,11 +21,13 @@ pub struct Include {
 #[derive(Default, PartialEq)]
 pub struct Includes<'a> {
     pub custom: Vec<Include>,
+    pub algorithm: bool,
     pub array: bool,
     pub cstddef: bool,
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
+    pub initializer_list: bool,
     pub iterator: bool,
     pub memory: bool,
     pub new: bool,
@@ -69,11 +71,13 @@ pub(super) fn write(out: &mut OutFile) {
 
     let Includes {
         custom: _,
+        algorithm,
         array,
         cstddef,
         cstdint,
         cstring,
         exception,
+        initializer_list,
         iterator,
         memory,
         new,
@@ -85,6 +89,9 @@ pub(super) fn write(out: &mut OutFile) {
         content: _,
     } = *include;
 
+    if algorithm {
+        writeln!(out, "#include <algorithm>");
+    }
     if array {
         writeln!(out, "#include <array>");
     }
@@ -100,6 +107,9 @@ pub(super) fn write(out: &mut OutFile) {
     if exception {
         writeln!(out, "#include <exception>");
     }
+    if initializer_list {
+        writeln!(out, "#include <initializer_list>");
+    }
     if iterator {
         writeln!(out, "#include <iterator>");
     }
diff --git a/include/cxx.h b/include/cxx.h
index 31b34fc..792d57d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -1,8 +1,10 @@
 #pragma once
+#include <algorithm>
 #include <array>
 #include <cstddef>
 #include <cstdint>
 #include <exception>
+#include <initializer_list>
 #include <iosfwd>
 #include <iterator>
 #include <new>
@@ -238,6 +240,7 @@ public:
   using value_type = T;
 
   Vec() noexcept;
+  Vec(std::initializer_list<T>);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
@@ -620,6 +623,12 @@ Box<T>::Box() noexcept = default;
 #ifndef CXXBRIDGE1_RUST_VEC
 #define CXXBRIDGE1_RUST_VEC
 template <typename T>
+Vec<T>::Vec(std::initializer_list<T> init) : Vec{} {
+  this->reserve_total(init.size());
+  std::move(init.begin(), init.end(), std::back_inserter(*this));
+}
+
+template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 244c6c0..6fd43ae 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -132,7 +132,8 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
 std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); }
 
 rust::Vec<uint8_t> c_return_rust_vec() {
-  throw std::runtime_error("unimplemented");
+  rust::Vec<uint8_t> vec{2, 0, 2, 0};
+  return vec;
 }
 
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
@@ -146,7 +147,7 @@ rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
 }
 
 rust::Vec<rust::String> c_return_rust_vec_string() {
-  throw std::runtime_error("unimplemented");
+  return {"2", "0", "2", "0"};
 }
 
 size_t c_return_identity(size_t n) { return n; }

From d537a2eb36584871e7c392cfe701500d2cae9b15 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 08:18:46 +0000
Subject: [PATCH 1634/2232] Merge pull request #533 from dtolnay/vecinit


Add std::initializer_list constructor for rust::Vec
---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 5820001..aef9527 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -6,6 +6,7 @@
 ```cpp,hidelines
 // rust/cxx.h
 #
+# #include <initializer_list>
 # #include <iterator>
 # #include <type_traits>
 #
@@ -17,6 +18,7 @@ public:
   using value_type = T;
 
   Vec() noexcept;
+  Vec(std::initializer_list<T>);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 5182e01..837761d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -71,7 +71,9 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_vec {
+        include.algorithm = true;
         include.array = true;
+        include.initializer_list = true;
         include.iterator = true;
         include.new = true;
         include.type_traits = true;
diff --git a/gen/src/include.rs b/gen/src/include.rs
index accaaee..9db95be 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -21,11 +21,13 @@ pub struct Include {
 #[derive(Default, PartialEq)]
 pub struct Includes<'a> {
     pub custom: Vec<Include>,
+    pub algorithm: bool,
     pub array: bool,
     pub cstddef: bool,
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
+    pub initializer_list: bool,
     pub iterator: bool,
     pub memory: bool,
     pub new: bool,
@@ -69,11 +71,13 @@ pub(super) fn write(out: &mut OutFile) {
 
     let Includes {
         custom: _,
+        algorithm,
         array,
         cstddef,
         cstdint,
         cstring,
         exception,
+        initializer_list,
         iterator,
         memory,
         new,
@@ -85,6 +89,9 @@ pub(super) fn write(out: &mut OutFile) {
         content: _,
     } = *include;
 
+    if algorithm {
+        writeln!(out, "#include <algorithm>");
+    }
     if array {
         writeln!(out, "#include <array>");
     }
@@ -100,6 +107,9 @@ pub(super) fn write(out: &mut OutFile) {
     if exception {
         writeln!(out, "#include <exception>");
     }
+    if initializer_list {
+        writeln!(out, "#include <initializer_list>");
+    }
     if iterator {
         writeln!(out, "#include <iterator>");
     }
diff --git a/include/cxx.h b/include/cxx.h
index 31b34fc..792d57d 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -1,8 +1,10 @@
 #pragma once
+#include <algorithm>
 #include <array>
 #include <cstddef>
 #include <cstdint>
 #include <exception>
+#include <initializer_list>
 #include <iosfwd>
 #include <iterator>
 #include <new>
@@ -238,6 +240,7 @@ public:
   using value_type = T;
 
   Vec() noexcept;
+  Vec(std::initializer_list<T>);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
@@ -620,6 +623,12 @@ Box<T>::Box() noexcept = default;
 #ifndef CXXBRIDGE1_RUST_VEC
 #define CXXBRIDGE1_RUST_VEC
 template <typename T>
+Vec<T>::Vec(std::initializer_list<T> init) : Vec{} {
+  this->reserve_total(init.size());
+  std::move(init.begin(), init.end(), std::back_inserter(*this));
+}
+
+template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 244c6c0..6fd43ae 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -132,7 +132,8 @@ const std::vector<uint8_t> &c_return_ref_vector(const C &c) {
 std::vector<uint8_t> &c_return_mut_vector(C &c) { return c.get_v(); }
 
 rust::Vec<uint8_t> c_return_rust_vec() {
-  throw std::runtime_error("unimplemented");
+  rust::Vec<uint8_t> vec{2, 0, 2, 0};
+  return vec;
 }
 
 const rust::Vec<uint8_t> &c_return_ref_rust_vec(const C &c) {
@@ -146,7 +147,7 @@ rust::Vec<uint8_t> &c_return_mut_rust_vec(C &c) {
 }
 
 rust::Vec<rust::String> c_return_rust_vec_string() {
-  throw std::runtime_error("unimplemented");
+  return {"2", "0", "2", "0"};
 }
 
 size_t c_return_identity(size_t n) { return n; }

From 0b933debac0fb7b20e70e075257d6555de0e57ec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 08:21:02 +0000
Subject: [PATCH 1635/2232] Release 1.0.8


---

diff --git a/Cargo.toml b/Cargo.toml
index 899a481..1f3617c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.7" # remember to update html_root_url
+version = "1.0.8" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.7", path = "macro" }
+cxxbridge-macro = { version = "=1.0.8", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.7", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.8", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.7", path = "gen/build" }
+cxx-build = { version = "=1.0.8", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index c50ca37..ec44610 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.7"
+version = "1.0.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index d525407..e46c0a3 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.7"
+version = "1.0.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index efe30fa..1348998 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.7"
+version = "1.0.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 71eabfa..9ac3fa0 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.7"
+version = "0.7.8"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e10d8c2..cc489c6 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.7"
+version = "1.0.8"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index dd4cbd4..f98bde7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.7")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.8")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 16970b8..04bd7ba 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.7"
+version = "1.0.8"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.7"
+version = "1.0.8"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.7"
+version = "0.7.8"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.7"
+version = "1.0.8"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.7"
+version = "1.0.8"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.7"
+version = "1.0.8"
 dependencies = [
  "cxx",
  "proc-macro2",

From 908d5e5dc5ca3062aab09fc36eb26e66e2b69124 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 08:37:22 +0000
Subject: [PATCH 1636/2232] Add non-const indexing for rust::Vec


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index aef9527..e2eaecb 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -31,10 +31,14 @@ public:
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
-
   const T &front() const;
   const T &back() const;
 
+  T &operator[](size_t n) noexcept;
+  T &at(size_t n);
+  T &front();
+  T &back();
+
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
diff --git a/include/cxx.h b/include/cxx.h
index 792d57d..8c3f241 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -253,10 +253,14 @@ public:
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
-
   const T &front() const;
   const T &back() const;
 
+  T &operator[](size_t n) noexcept;
+  T &at(size_t n);
+  T &front();
+  T &back();
+
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
@@ -683,6 +687,30 @@ const T &Vec<T>::back() const {
 }
 
 template <typename T>
+T &Vec<T>::operator[](size_t n) noexcept {
+  auto data = reinterpret_cast<char *>(this->data());
+  return *reinterpret_cast<T *>(data + n * this->stride());
+}
+
+template <typename T>
+T &Vec<T>::at(size_t n) {
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Vec index out of range");
+  }
+  return (*this)[n];
+}
+
+template <typename T>
+T &Vec<T>::front() {
+  return (*this)[0];
+}
+
+template <typename T>
+T &Vec<T>::back() {
+  return (*this)[this->size() - 1];
+}
+
+template <typename T>
 void Vec<T>::reserve(size_t new_cap) {
   this->reserve_total(new_cap);
 }

From b4d6ce67cc6eb6fcc10f2cc539621038da7f1e68 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Nov 30 2020 08:42:21 +0000
Subject: [PATCH 1637/2232] Merge pull request #534 from dtolnay/vecindex


Add non-const indexing for rust::Vec
---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index aef9527..e2eaecb 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -31,10 +31,14 @@ public:
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
-
   const T &front() const;
   const T &back() const;
 
+  T &operator[](size_t n) noexcept;
+  T &at(size_t n);
+  T &front();
+  T &back();
+
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
diff --git a/include/cxx.h b/include/cxx.h
index 792d57d..8c3f241 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -253,10 +253,14 @@ public:
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
-
   const T &front() const;
   const T &back() const;
 
+  T &operator[](size_t n) noexcept;
+  T &at(size_t n);
+  T &front();
+  T &back();
+
   void reserve(size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
@@ -683,6 +687,30 @@ const T &Vec<T>::back() const {
 }
 
 template <typename T>
+T &Vec<T>::operator[](size_t n) noexcept {
+  auto data = reinterpret_cast<char *>(this->data());
+  return *reinterpret_cast<T *>(data + n * this->stride());
+}
+
+template <typename T>
+T &Vec<T>::at(size_t n) {
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Vec index out of range");
+  }
+  return (*this)[n];
+}
+
+template <typename T>
+T &Vec<T>::front() {
+  return (*this)[0];
+}
+
+template <typename T>
+T &Vec<T>::back() {
+  return (*this)[this->size() - 1];
+}
+
+template <typename T>
 void Vec<T>::reserve(size_t new_cap) {
   this->reserve_total(new_cap);
 }

From 22af60d23768dcbd5325449e0f2ebe80b3216c0f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 01 2020 22:49:47 +0000
Subject: [PATCH 1638/2232] Fix enum PartialOrd and Ord derives


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 3379c9c..5e9b8a9 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -255,7 +255,7 @@ fn enum_ord(enm: &Enum, span: Span) -> TokenStream {
 
     quote_spanned! {span=>
         impl ::std::cmp::Ord for #ident {
-            pub fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
+            fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                 ::std::cmp::Ord::cmp(&self.repr, &other.repr)
             }
         }
@@ -267,8 +267,8 @@ fn enum_partial_ord(enm: &Enum, span: Span) -> TokenStream {
 
     quote_spanned! {span=>
         impl ::std::cmp::PartialOrd for #ident {
-            pub fn cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
-                ::std::cmp::PartialOrd::cmp(&self.repr, &other.repr)
+            fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
+                ::std::cmp::PartialOrd::partial_cmp(&self.repr, &other.repr)
             }
         }
     }

From 852d05f717279ee6a74602a6c0efec4c08ab2733 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 01 2020 22:49:47 +0000
Subject: [PATCH 1639/2232] Test more derives


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5427b89..fc69581 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -25,7 +25,7 @@ pub mod ffi {
         msg: String,
     }
 
-    #[derive(Debug, Hash)]
+    #[derive(Debug, Hash, PartialOrd, Ord)]
     enum Enum {
         AVal,
         BVal = 2020,
@@ -33,7 +33,7 @@ pub mod ffi {
     }
 
     #[namespace = "A"]
-    #[derive(Clone)]
+    #[derive(Copy, Clone, Default)]
     struct AShared {
         z: usize,
     }

From 9bbbe5fa89ef4753bdc36deee6465a3ffffe7eb7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 01 2020 22:50:36 +0000
Subject: [PATCH 1640/2232] Release 1.0.9


---

diff --git a/Cargo.toml b/Cargo.toml
index 1f3617c..2c01d1e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.8" # remember to update html_root_url
+version = "1.0.9" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.8", path = "macro" }
+cxxbridge-macro = { version = "=1.0.9", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.8", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.9", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.8", path = "gen/build" }
+cxx-build = { version = "=1.0.9", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index ec44610..3afb072 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.8"
+version = "1.0.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index e46c0a3..63bff45 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.8"
+version = "1.0.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 1348998..0b62654 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.8"
+version = "1.0.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 9ac3fa0..dee56bd 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.8"
+version = "0.7.9"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index cc489c6..0041254 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.8"
+version = "1.0.9"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index f98bde7..917dd3b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.8")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.9")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 04bd7ba..92896d8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.8"
+version = "1.0.9"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.8"
+version = "1.0.9"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.8"
+version = "0.7.9"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.8"
+version = "1.0.9"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.8"
+version = "1.0.9"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.8"
+version = "1.0.9"
 dependencies = [
  "cxx",
  "proc-macro2",

From b3b24a1fe00d31c7e10e052fa47d6856cfc7340e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 04:49:04 +0000
Subject: [PATCH 1641/2232] Add Rust std::shared_ptr binding


---

diff --git a/README.md b/README.md
index 746e466..f6a18eb 100644
--- a/README.md
+++ b/README.md
@@ -327,6 +327,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
@@ -350,7 +351,6 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index e10c2cc..4987694 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -29,6 +29,7 @@
     - [CxxString &mdash; std::string](binding/cxxstring.md)
     - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
     - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
+    - [SharedPtr\<T\> &mdash; std::shared\_ptr\<T\>](binding/sharedptr.md)
     - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
     - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
     - [Function pointers](binding/fn.md)
diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 8bcae58..7456ada 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -49,8 +49,8 @@ public:
 ### Restrictions:
 
 Box\<T\> does not support T being an opaque C++ type. You should use
-[UniquePtr\<T\>](uniqueptr.md) instead for transferring ownership of opaque C++
-types on the language boundary.
+[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for
+transferring ownership of opaque C++ types on the language boundary.
 
 If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
 known at compile time. In the future we may introduce support for dynamically
diff --git a/book/src/binding/sharedptr.md b/book/src/binding/sharedptr.md
new file mode 100644
index 0000000..8f494ae
--- /dev/null
+++ b/book/src/binding/sharedptr.md
@@ -0,0 +1,80 @@
+{{#title std::shared_ptr<T> — Rust ♡ C++}}
+# std::shared\_ptr\<T\>
+
+The Rust binding of std::shared\_ptr\<T\> is called **[`SharedPtr<T>`]**. See
+the link for documentation of the Rust API.
+
+[`SharedPtr<T>`]: https://docs.rs/cxx/*/cxx/struct.SharedPtr.html
+
+### Restrictions:
+
+SharedPtr\<T\> does not support T being an opaque Rust type. You should use a
+Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of
+opaque Rust types on the language boundary.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+use std::ops::Deref;
+use std::ptr;
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        type Object;
+
+        fn create_shared_ptr() -> SharedPtr<Object>;
+    }
+}
+
+fn main() {
+    let ptr1 = ffi::create_shared_ptr();
+
+    {
+        // Create a second shared_ptr holding shared ownership of the same
+        // object. There is still only one Object but two SharedPtr<Object>.
+        // Both pointers point to the same object on the heap. 
+        let ptr2 = ptr1.clone();
+        assert!(ptr::eq(ptr1.deref(), ptr2.deref()));
+
+        // ptr2 goes out of scope, but Object is not destroyed yet.
+    }
+
+    println!("say goodbye to Object");
+
+    // ptr1 goes out of scope and Object is destroyed.
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include <memory>
+
+class Object {
+public:
+  Object();
+  ~Object();
+};
+
+std::shared_ptr<Object> create_shared_ptr();
+```
+
+```cpp
+// src/example.cc
+
+#include "example/include/example.h"
+#include <iostream>
+
+Object::Object() { std::cout << "construct Object" << std::endl; }
+Object::~Object() { std::cout << "~Object" << std::endl; }
+
+std::shared_ptr<Object> create_shared_ptr() {
+  return std::make_shared<Object>();
+}
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index c2a525c..b2069b8 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -16,6 +16,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/sharedptr.md">SharedPtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::shared_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5413b68..26da9e4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -201,6 +201,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
             Type::UniquePtr(_) => out.include.memory = true,
+            Type::SharedPtr(_) => out.include.memory = true,
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
@@ -1104,6 +1105,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::SharedPtr(ptr) => {
+            write!(out, "::std::shared_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
@@ -1182,6 +1188,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         Type::Ident(_)
         | Type::RustBox(_)
         | Type::UniquePtr(_)
+        | Type::SharedPtr(_)
         | Type::Str(_)
         | Type::CxxVector(_)
         | Type::RustVec(_)
@@ -1270,6 +1277,16 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_unique_ptr(out, inner);
                 }
             }
+        } else if let Type::SharedPtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && !(out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_shared_ptr(out, inner);
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
@@ -1554,6 +1571,87 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
+fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
+    let resolved = out.types.resolve(ident);
+    let inner = resolved.to_fully_qualified();
+    let instance = ident.to_symbol(out.types);
+
+    writeln!(out, "#ifndef CXXBRIDGE1_SHARED_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_SHARED_PTR_{}", instance);
+    out.include.new = true;
+    out.include.utility = true;
+
+    // Some aliases are to opaque types; some are to trivial types. We can't
+    // know at code generation time, so we generate both C++ and Rust side
+    // bindings for a "new" method anyway. But the Rust code can't be called for
+    // Opaque types because the 'new' method is not implemented.
+    let can_construct_from_value = out.types.structs.contains_key(&ident.rust)
+        || out.types.enums.contains_key(&ident.rust)
+        || out.types.aliases.contains_key(&ident.rust);
+
+    if !out.types.structs.contains_key(&ident.rust) && !out.types.enums.contains_key(&ident.rust) {
+        out.builtin.is_complete = true;
+        writeln!(
+            out,
+            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+            inner, resolved.cxx,
+        );
+    }
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::shared_ptr<{}>) == 2 * sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::shared_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    if can_construct_from_value {
+        writeln!(
+            out,
+            "void cxxbridge1$shared_ptr${}$new(::std::shared_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::shared_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$clone(const ::std::shared_ptr<{}>& self, ::std::shared_ptr<{}> *ptr) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(self);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} *cxxbridge1$shared_ptr${}$get(const ::std::shared_ptr<{}>& self) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return self.get();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  self->~shared_ptr();");
+    writeln!(out, "}}");
+
+    writeln!(out, "#endif // CXXBRIDGE1_SHARED_PTR_{}", instance);
+}
+
 fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 63fe888..82b79aa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -86,6 +86,14 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                     expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
             }
+        } else if let Type::SharedPtr(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
+                    expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1110,6 +1118,77 @@ fn expand_unique_ptr(
     }
 }
 
+fn expand_shared_ptr(
+    ident: &ResolvableName,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge1$shared_ptr${}$", ident.to_symbol(types));
+    let link_null = format!("{}null", prefix);
+    let link_new = format!("{}new", prefix);
+    let link_clone = format!("{}clone", prefix);
+    let link_get = format!("{}get", prefix);
+    let link_drop = format!("{}drop", prefix);
+
+    let can_construct_from_value = types.structs.contains_key(&ident.rust)
+        || types.enums.contains_key(&ident.rust)
+        || types.aliases.contains_key(&ident.rust);
+    let new_method = if can_construct_from_value {
+        Some(quote! {
+            unsafe fn __new(mut value: Self, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_new]
+                    fn __new(new: *mut ::std::ffi::c_void, value: *mut #ident);
+                }
+                __new(new, &mut value);
+            }
+        })
+    } else {
+        None
+    };
+
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::SharedPtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            unsafe fn __null(new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_null]
+                    fn __null(new: *mut ::std::ffi::c_void);
+                }
+                __null(new);
+            }
+            #new_method
+            unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_clone]
+                    fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void);
+                }
+                __clone(this, new);
+            }
+            unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self {
+                extern "C" {
+                    #[link_name = #link_get]
+                    fn __get(this: *const ::std::ffi::c_void) -> *const #ident;
+                }
+                __get(this)
+            }
+            unsafe fn __drop(this: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_drop]
+                    fn __drop(this: *mut ::std::ffi::c_void);
+                }
+                __drop(this);
+            }
+        }
+    }
+}
+
 fn expand_cxx_vector(
     elem: &ResolvableName,
     explicit_impl: Option<&Impl>,
diff --git a/src/lib.rs b/src/lib.rs
index 917dd3b..bfd7a51 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -336,6 +336,7 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
@@ -359,7 +360,6 @@
 //! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 //! </table>
 
 #![no_std]
@@ -404,6 +404,7 @@ mod rust_str;
 mod rust_string;
 mod rust_type;
 mod rust_vec;
+mod shared_ptr;
 mod symbols;
 mod unique_ptr;
 mod unwind;
@@ -412,6 +413,7 @@ pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
+pub use crate::shared_ptr::SharedPtr;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 
@@ -448,6 +450,7 @@ pub mod private {
     pub use crate::rust_string::RustString;
     pub use crate::rust_type::RustType;
     pub use crate::rust_vec::RustVec;
+    pub use crate::shared_ptr::SharedPtrTarget;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
new file mode 100644
index 0000000..7fdb356
--- /dev/null
+++ b/src/shared_ptr.rs
@@ -0,0 +1,191 @@
+use crate::kind::Trivial;
+use crate::ExternType;
+use core::ffi::c_void;
+use core::fmt::{self, Debug, Display};
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+use core::ops::{Deref, DerefMut};
+use core::pin::Pin;
+
+/// BInding to C++ `std::shared_ptr<T>`.
+#[repr(C)]
+pub struct SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    repr: [*mut c_void; 2],
+    ty: PhantomData<T>,
+}
+
+impl<T> SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    /// Makes a new SharedPtr wrapping a null pointer.
+    ///
+    /// Matches the behavior of default-constructing a std::shared\_ptr.
+    pub fn null() -> Self {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__null(new);
+            shared_ptr.assume_init()
+        }
+    }
+
+    /// Allocates memory on the heap and makes a SharedPtr owner for it.
+    pub fn new(value: T) -> Self
+    where
+        T: ExternType<Kind = Trivial>,
+    {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__new(value, new);
+            shared_ptr.assume_init()
+        }
+    }
+
+    /// Chacks whether the SharedPtr does not own an object.
+    ///
+    /// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
+    pub fn is_null(&self) -> bool {
+        let this = self as *const Self as *const c_void;
+        let ptr = unsafe { T::__get(this) };
+        ptr.is_null()
+    }
+
+    /// Returns a reference to the object owned by this SharedPtr if any,
+    /// otherwise None.
+    pub fn as_ref(&self) -> Option<&T> {
+        let this = self as *const Self as *const c_void;
+        unsafe { T::__get(this).as_ref() }
+    }
+
+    /// Returns a mutable pinned reference to the object owned by this SharedPtr
+    /// if any, otherwise None.
+    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
+        let this = self as *mut Self as *mut c_void;
+        unsafe {
+            let mut_reference = (T::__get(this) as *mut T).as_mut()?;
+            Some(Pin::new_unchecked(mut_reference))
+        }
+    }
+
+    /// Returns a mutable pinned reference to the object owned by this
+    /// SharedPtr.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the SharedPtr holds a null pointer.
+    pub fn pin_mut(&mut self) -> Pin<&mut T> {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called pin_mut on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
+unsafe impl<T> Sync for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
+
+impl<T> Clone for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    fn clone(&self) -> Self {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        let this = self as *const Self as *mut c_void;
+        unsafe {
+            T::__clone(this, new);
+            shared_ptr.assume_init()
+        }
+    }
+}
+
+impl<T> Drop for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    fn drop(&mut self) {
+        let this = self as *mut Self as *mut c_void;
+        unsafe { T::__drop(this) }
+    }
+}
+
+impl<T> Deref for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        match self.as_ref() {
+            Some(target) => target,
+            None => panic!("called deref on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+impl<T> DerefMut for SharedPtr<T>
+where
+    T: SharedPtrTarget + Unpin,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => Pin::into_inner(target),
+            None => panic!("called deref_mut on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+impl<T> Debug for SharedPtr<T>
+where
+    T: Debug + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        match self.as_ref() {
+            None => formatter.write_str("nullptr"),
+            Some(value) => Debug::fmt(value, formatter),
+        }
+    }
+}
+
+impl<T> Display for SharedPtr<T>
+where
+    T: Display + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        match self.as_ref() {
+            None => formatter.write_str("nullptr"),
+            Some(value) => Display::fmt(value, formatter),
+        }
+    }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+pub unsafe trait SharedPtrTarget {
+    #[doc(hidden)]
+    const __NAME: &'static dyn Display;
+    #[doc(hidden)]
+    unsafe fn __null(new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __new(value: Self, new: *mut c_void)
+    where
+        Self: Sized,
+    {
+        // Opoaque C types do not get this method because they can never exist
+        // by value on the Rust side of the bridge.
+        let _ = value;
+        let _ = new;
+        unreachable!()
+    }
+    #[doc(hidden)]
+    unsafe fn __clone(this: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __get(this: *const c_void) -> *const Self;
+    #[doc(hidden)]
+    unsafe fn __drop(this: *mut c_void);
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index 2ebbf05..6dce563 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -32,6 +32,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
@@ -115,6 +116,7 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
             cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
+            return;
         }
 
         match Atom::from(&ident.rust) {
@@ -128,6 +130,29 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
+fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(&ident.rust) {
+            cx.error(ptr, "shared_ptr of a Rust type is not supported yet");
+            return;
+        }
+
+        match Atom::from(&ident.rust) {
+            None => return,
+            Some(CxxString) => {
+                cx.error(ptr, "std::shared_ptr<std::string> is not supported yet");
+                return;
+            }
+            _ => {}
+        }
+    } else if let Type::CxxVector(_) = &ptr.inner {
+        cx.error(ptr, "std::shared_ptr<std::vector> is not supported yet");
+        return;
+    }
+
+    cx.error(ptr, "unsupported shared_ptr target type");
+}
+
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
@@ -135,6 +160,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
                 ptr,
                 "C++ vector containing a Rust type is not supported yet",
             );
+            return;
         }
 
         match Atom::from(&ident.rust) {
@@ -410,7 +436,7 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         return;
     }
 
-    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = ty {
+    if let Type::UniquePtr(ty) | Type::SharedPtr(ty) | Type::CxxVector(ty) = ty {
         if let Type::Ident(inner) = &ty.inner {
             if Atom::from(&inner.rust).is_none() {
                 return;
@@ -473,6 +499,7 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"
+        || ident == "SharedPtr"
         || ident == "Vec"
         || ident == "CxxVector"
         || ident == "str"
@@ -493,6 +520,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         Type::RustBox(_)
         | Type::RustVec(_)
         | Type::UniquePtr(_)
+        | Type::SharedPtr(_)
         | Type::Ref(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
@@ -564,6 +592,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::RustBox(_) => "Box".to_owned(),
         Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
+        Type::SharedPtr(_) => "shared_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
diff --git a/syntax/error.rs b/syntax/error.rs
index d0ae021..a672329 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -29,7 +29,7 @@ pub static ERRORS: &[Error] = &[
 pub static BOX_CXX_TYPE: Error = Error {
     msg: "Box of a C++ type is not supported yet",
     label: None,
-    note: Some("hint: use UniquePtr<>"),
+    note: Some("hint: use UniquePtr<> or SharedPtr<>"),
 };
 
 pub static CXXBRIDGE_RESERVED: Error = Error {
@@ -47,7 +47,7 @@ pub static CXX_STRING_BY_VALUE: Error = Error {
 pub static CXX_TYPE_BY_VALUE: Error = Error {
     msg: "C++ type by value is not supported",
     label: None,
-    note: Some("hint: wrap it in a UniquePtr<>"),
+    note: Some("hint: wrap it in a UniquePtr<> or SharedPtr<>"),
 };
 
 pub static DISCRIMINANT_OVERFLOW: Error = Error {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 73cb1d9..9b154f6 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -45,6 +45,7 @@ impl Hash for Type {
             Type::Ident(t) => t.hash(state),
             Type::RustBox(t) => t.hash(state),
             Type::UniquePtr(t) => t.hash(state),
+            Type::SharedPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
@@ -65,6 +66,7 @@ impl PartialEq for Type {
             (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
             (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
+            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
diff --git a/syntax/improper.rs b/syntax/improper.rs
index e0e5154..c0f6983 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -28,7 +28,7 @@ impl<'a> Types<'a> {
             | Type::Fn(_)
             | Type::Void(_)
             | Type::SliceRef(_) => Definite(true),
-            Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e8bd290..12b269e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -167,6 +167,7 @@ pub enum Type {
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
+    SharedPtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a3f50ec..e4f0512 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -822,6 +822,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "SharedPtr" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::SharedPtr(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index edbf818..07738d8 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -20,9 +20,11 @@ impl ToTokens for Type {
                 }
                 ident.rust.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
-                ty.to_tokens(tokens)
-            }
+            Type::RustBox(ty)
+            | Type::UniquePtr(ty)
+            | Type::SharedPtr(ty)
+            | Type::CxxVector(ty)
+            | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
@@ -44,7 +46,7 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
-        if let "UniquePtr" | "CxxVector" = name.as_str() {
+        if let "UniquePtr" | "SharedPtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
             tokens.extend(quote_spanned!(span=> ::std::vec::));
diff --git a/syntax/types.rs b/syntax/types.rs
index c98fe85..70b381f 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -45,6 +45,7 @@ impl<'a> Types<'a> {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
+                | Type::SharedPtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
@@ -254,7 +255,7 @@ impl<'a> Types<'a> {
                     Atom::from(&ident.rust) == Some(RustString)
                 }
             }
-            Type::RustVec(_) | Type::Array(_) => true,
+            Type::SharedPtr(_) | Type::RustVec(_) | Type::Array(_) => true,
             _ => false,
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fc69581..0c2b8b6 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -9,8 +9,9 @@
 pub mod cast;
 pub mod module;
 
-use cxx::{CxxString, CxxVector, UniquePtr};
+use cxx::{CxxString, CxxVector, SharedPtr, UniquePtr};
 use std::fmt::{self, Display};
+use std::mem::MaybeUninit;
 use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
@@ -83,6 +84,7 @@ pub mod ffi {
         fn c_return_shared() -> Shared;
         fn c_return_box() -> Box<R>;
         fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_shared_ptr() -> SharedPtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
@@ -198,6 +200,7 @@ pub mod ffi {
         fn r_return_shared() -> Shared;
         fn r_return_box() -> Box<R>;
         fn r_return_unique_ptr() -> UniquePtr<C>;
+        fn r_return_shared_ptr() -> SharedPtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
@@ -217,6 +220,7 @@ pub mod ffi {
         fn r_take_shared(shared: Shared);
         fn r_take_box(r: Box<R>);
         fn r_take_unique_ptr(c: UniquePtr<C>);
+        fn r_take_shared_ptr(c: SharedPtr<C>);
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
@@ -377,6 +381,18 @@ fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
     unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
 }
 
+fn r_return_shared_ptr() -> SharedPtr<ffi::C> {
+    extern "C" {
+        fn cxx_test_suite_get_shared_ptr(repr: *mut SharedPtr<ffi::C>);
+    }
+    let mut shared_ptr = MaybeUninit::<SharedPtr<ffi::C>>::uninit();
+    let repr = shared_ptr.as_mut_ptr();
+    unsafe {
+        cxx_test_suite_get_shared_ptr(repr);
+        shared_ptr.assume_init()
+    }
+}
+
 fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
@@ -462,6 +478,10 @@ fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
     let _ = c;
 }
 
+fn r_take_shared_ptr(c: SharedPtr<ffi::C>) {
+    let _ = c;
+}
+
 fn r_take_ref_r(r: &R) {
     let _ = r;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6fd43ae..47d447c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -57,6 +57,10 @@ std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
 
+std::shared_ptr<C> c_return_shared_ptr() {
+  return std::shared_ptr<C>(new C{2020});
+}
+
 std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
   return std::unique_ptr<::H::H>(new ::H::H{"hello"});
 }
@@ -479,6 +483,11 @@ extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
 
+extern "C" void
+cxx_test_suite_get_shared_ptr(std::shared_ptr<C> *repr) noexcept {
+  new (repr) std::shared_ptr<C>(new C{2020});
+}
+
 extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
   return std::unique_ptr<std::string>(new std::string("2020")).release();
 }
@@ -611,6 +620,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r_return_shared().z == 2020);
   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));
   ASSERT(r_return_unique_ptr()->get() == 2020);
+  ASSERT(r_return_shared_ptr()->get() == 2020);
   ASSERT(r_return_ref(Shared{2020}) == 2020);
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");
@@ -624,6 +634,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
+  r_take_shared_ptr(std::shared_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
   r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 5791983..0e16ab7 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -77,6 +77,7 @@ Shared c_return_shared();
 ::A::B::ABShared c_return_nested_ns_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
+std::shared_ptr<C> c_return_shared_ptr();
 std::unique_ptr<::H::H> c_return_ns_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 const size_t &c_return_ns_ref(const ::A::AShared &shared);
diff --git a/tests/test.rs b/tests/test.rs
index 1b9a88e..d339152 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -36,6 +36,7 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, ffi::c_return_box().0);
     ffi::c_return_unique_ptr();
+    ffi::c_return_shared_ptr();
     ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));

From 71f1f75c7ae069dc6a077778efd4880876f279c3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 04:55:01 +0000
Subject: [PATCH 1642/2232] Merge pull request #536 from dtolnay/shared_ptr


Add Rust std::shared_ptr binding
---

diff --git a/README.md b/README.md
index 746e466..f6a18eb 100644
--- a/README.md
+++ b/README.md
@@ -327,6 +327,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
@@ -350,7 +351,6 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index e10c2cc..4987694 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -29,6 +29,7 @@
     - [CxxString &mdash; std::string](binding/cxxstring.md)
     - [Box\<T\> &mdash; rust::Box\<T\>](binding/box.md)
     - [UniquePtr\<T\> &mdash; std::unique\_ptr\<T\>](binding/uniqueptr.md)
+    - [SharedPtr\<T\> &mdash; std::shared\_ptr\<T\>](binding/sharedptr.md)
     - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
     - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
     - [Function pointers](binding/fn.md)
diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 8bcae58..7456ada 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -49,8 +49,8 @@ public:
 ### Restrictions:
 
 Box\<T\> does not support T being an opaque C++ type. You should use
-[UniquePtr\<T\>](uniqueptr.md) instead for transferring ownership of opaque C++
-types on the language boundary.
+[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for
+transferring ownership of opaque C++ types on the language boundary.
 
 If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size
 known at compile time. In the future we may introduce support for dynamically
diff --git a/book/src/binding/sharedptr.md b/book/src/binding/sharedptr.md
new file mode 100644
index 0000000..8f494ae
--- /dev/null
+++ b/book/src/binding/sharedptr.md
@@ -0,0 +1,80 @@
+{{#title std::shared_ptr<T> — Rust ♡ C++}}
+# std::shared\_ptr\<T\>
+
+The Rust binding of std::shared\_ptr\<T\> is called **[`SharedPtr<T>`]**. See
+the link for documentation of the Rust API.
+
+[`SharedPtr<T>`]: https://docs.rs/cxx/*/cxx/struct.SharedPtr.html
+
+### Restrictions:
+
+SharedPtr\<T\> does not support T being an opaque Rust type. You should use a
+Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of
+opaque Rust types on the language boundary.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+use std::ops::Deref;
+use std::ptr;
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        include!("example/include/example.h");
+
+        type Object;
+
+        fn create_shared_ptr() -> SharedPtr<Object>;
+    }
+}
+
+fn main() {
+    let ptr1 = ffi::create_shared_ptr();
+
+    {
+        // Create a second shared_ptr holding shared ownership of the same
+        // object. There is still only one Object but two SharedPtr<Object>.
+        // Both pointers point to the same object on the heap. 
+        let ptr2 = ptr1.clone();
+        assert!(ptr::eq(ptr1.deref(), ptr2.deref()));
+
+        // ptr2 goes out of scope, but Object is not destroyed yet.
+    }
+
+    println!("say goodbye to Object");
+
+    // ptr1 goes out of scope and Object is destroyed.
+}
+```
+
+```cpp
+// include/example.h
+
+#pragma once
+#include <memory>
+
+class Object {
+public:
+  Object();
+  ~Object();
+};
+
+std::shared_ptr<Object> create_shared_ptr();
+```
+
+```cpp
+// src/example.cc
+
+#include "example/include/example.h"
+#include <iostream>
+
+Object::Object() { std::cout << "construct Object" << std::endl; }
+Object::~Object() { std::cout << "~Object" << std::endl; }
+
+std::shared_ptr<Object> create_shared_ptr() {
+  return std::make_shared<Object>();
+}
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index c2a525c..b2069b8 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -16,6 +16,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/sharedptr.md">SharedPtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::shared_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5413b68..26da9e4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -201,6 +201,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
             Type::UniquePtr(_) => out.include.memory = true,
+            Type::SharedPtr(_) => out.include.memory = true,
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
@@ -1104,6 +1105,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::SharedPtr(ptr) => {
+            write!(out, "::std::shared_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
@@ -1182,6 +1188,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         Type::Ident(_)
         | Type::RustBox(_)
         | Type::UniquePtr(_)
+        | Type::SharedPtr(_)
         | Type::Str(_)
         | Type::CxxVector(_)
         | Type::RustVec(_)
@@ -1270,6 +1277,16 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_unique_ptr(out, inner);
                 }
             }
+        } else if let Type::SharedPtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && !(out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_shared_ptr(out, inner);
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
@@ -1554,6 +1571,87 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
+fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
+    let resolved = out.types.resolve(ident);
+    let inner = resolved.to_fully_qualified();
+    let instance = ident.to_symbol(out.types);
+
+    writeln!(out, "#ifndef CXXBRIDGE1_SHARED_PTR_{}", instance);
+    writeln!(out, "#define CXXBRIDGE1_SHARED_PTR_{}", instance);
+    out.include.new = true;
+    out.include.utility = true;
+
+    // Some aliases are to opaque types; some are to trivial types. We can't
+    // know at code generation time, so we generate both C++ and Rust side
+    // bindings for a "new" method anyway. But the Rust code can't be called for
+    // Opaque types because the 'new' method is not implemented.
+    let can_construct_from_value = out.types.structs.contains_key(&ident.rust)
+        || out.types.enums.contains_key(&ident.rust)
+        || out.types.aliases.contains_key(&ident.rust);
+
+    if !out.types.structs.contains_key(&ident.rust) && !out.types.enums.contains_key(&ident.rust) {
+        out.builtin.is_complete = true;
+        writeln!(
+            out,
+            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+            inner, resolved.cxx,
+        );
+    }
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::shared_ptr<{}>) == 2 * sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::shared_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    if can_construct_from_value {
+        writeln!(
+            out,
+            "void cxxbridge1$shared_ptr${}$new(::std::shared_ptr<{}> *ptr, {} *value) noexcept {{",
+            instance, inner, inner,
+        );
+        writeln!(
+            out,
+            "  new (ptr) ::std::shared_ptr<{}>(new {}(::std::move(*value)));",
+            inner, inner,
+        );
+        writeln!(out, "}}");
+    }
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$clone(const ::std::shared_ptr<{}>& self, ::std::shared_ptr<{}> *ptr) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(self);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "const {} *cxxbridge1$shared_ptr${}$get(const ::std::shared_ptr<{}>& self) noexcept {{",
+        inner, instance, inner,
+    );
+    writeln!(out, "  return self.get();");
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$shared_ptr${}$drop(::std::shared_ptr<{}> *self) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  self->~shared_ptr();");
+    writeln!(out, "}}");
+
+    writeln!(out, "#endif // CXXBRIDGE1_SHARED_PTR_{}", instance);
+}
+
 fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 63fe888..82b79aa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -86,6 +86,14 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                     expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
                 }
             }
+        } else if let Type::SharedPtr(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
+                    expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1110,6 +1118,77 @@ fn expand_unique_ptr(
     }
 }
 
+fn expand_shared_ptr(
+    ident: &ResolvableName,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge1$shared_ptr${}$", ident.to_symbol(types));
+    let link_null = format!("{}null", prefix);
+    let link_new = format!("{}new", prefix);
+    let link_clone = format!("{}clone", prefix);
+    let link_get = format!("{}get", prefix);
+    let link_drop = format!("{}drop", prefix);
+
+    let can_construct_from_value = types.structs.contains_key(&ident.rust)
+        || types.enums.contains_key(&ident.rust)
+        || types.aliases.contains_key(&ident.rust);
+    let new_method = if can_construct_from_value {
+        Some(quote! {
+            unsafe fn __new(mut value: Self, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_new]
+                    fn __new(new: *mut ::std::ffi::c_void, value: *mut #ident);
+                }
+                __new(new, &mut value);
+            }
+        })
+    } else {
+        None
+    };
+
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::SharedPtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            unsafe fn __null(new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_null]
+                    fn __null(new: *mut ::std::ffi::c_void);
+                }
+                __null(new);
+            }
+            #new_method
+            unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_clone]
+                    fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void);
+                }
+                __clone(this, new);
+            }
+            unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self {
+                extern "C" {
+                    #[link_name = #link_get]
+                    fn __get(this: *const ::std::ffi::c_void) -> *const #ident;
+                }
+                __get(this)
+            }
+            unsafe fn __drop(this: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_drop]
+                    fn __drop(this: *mut ::std::ffi::c_void);
+                }
+                __drop(this);
+            }
+        }
+    }
+}
+
 fn expand_cxx_vector(
     elem: &ResolvableName,
     explicit_impl: Option<&Impl>,
diff --git a/src/lib.rs b/src/lib.rs
index 917dd3b..bfd7a51 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -336,6 +336,7 @@
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td><a href="struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
@@ -359,7 +360,6 @@
 //! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 //! </table>
 
 #![no_std]
@@ -404,6 +404,7 @@ mod rust_str;
 mod rust_string;
 mod rust_type;
 mod rust_vec;
+mod shared_ptr;
 mod symbols;
 mod unique_ptr;
 mod unwind;
@@ -412,6 +413,7 @@ pub use crate::cxx_string::CxxString;
 pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
+pub use crate::shared_ptr::SharedPtr;
 pub use crate::unique_ptr::UniquePtr;
 pub use cxxbridge_macro::bridge;
 
@@ -448,6 +450,7 @@ pub mod private {
     pub use crate::rust_string::RustString;
     pub use crate::rust_type::RustType;
     pub use crate::rust_vec::RustVec;
+    pub use crate::shared_ptr::SharedPtrTarget;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
 }
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
new file mode 100644
index 0000000..7fdb356
--- /dev/null
+++ b/src/shared_ptr.rs
@@ -0,0 +1,191 @@
+use crate::kind::Trivial;
+use crate::ExternType;
+use core::ffi::c_void;
+use core::fmt::{self, Debug, Display};
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+use core::ops::{Deref, DerefMut};
+use core::pin::Pin;
+
+/// BInding to C++ `std::shared_ptr<T>`.
+#[repr(C)]
+pub struct SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    repr: [*mut c_void; 2],
+    ty: PhantomData<T>,
+}
+
+impl<T> SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    /// Makes a new SharedPtr wrapping a null pointer.
+    ///
+    /// Matches the behavior of default-constructing a std::shared\_ptr.
+    pub fn null() -> Self {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__null(new);
+            shared_ptr.assume_init()
+        }
+    }
+
+    /// Allocates memory on the heap and makes a SharedPtr owner for it.
+    pub fn new(value: T) -> Self
+    where
+        T: ExternType<Kind = Trivial>,
+    {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__new(value, new);
+            shared_ptr.assume_init()
+        }
+    }
+
+    /// Chacks whether the SharedPtr does not own an object.
+    ///
+    /// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
+    pub fn is_null(&self) -> bool {
+        let this = self as *const Self as *const c_void;
+        let ptr = unsafe { T::__get(this) };
+        ptr.is_null()
+    }
+
+    /// Returns a reference to the object owned by this SharedPtr if any,
+    /// otherwise None.
+    pub fn as_ref(&self) -> Option<&T> {
+        let this = self as *const Self as *const c_void;
+        unsafe { T::__get(this).as_ref() }
+    }
+
+    /// Returns a mutable pinned reference to the object owned by this SharedPtr
+    /// if any, otherwise None.
+    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
+        let this = self as *mut Self as *mut c_void;
+        unsafe {
+            let mut_reference = (T::__get(this) as *mut T).as_mut()?;
+            Some(Pin::new_unchecked(mut_reference))
+        }
+    }
+
+    /// Returns a mutable pinned reference to the object owned by this
+    /// SharedPtr.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the SharedPtr holds a null pointer.
+    pub fn pin_mut(&mut self) -> Pin<&mut T> {
+        match self.as_mut() {
+            Some(target) => target,
+            None => panic!("called pin_mut on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
+unsafe impl<T> Sync for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
+
+impl<T> Clone for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    fn clone(&self) -> Self {
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        let this = self as *const Self as *mut c_void;
+        unsafe {
+            T::__clone(this, new);
+            shared_ptr.assume_init()
+        }
+    }
+}
+
+impl<T> Drop for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    fn drop(&mut self) {
+        let this = self as *mut Self as *mut c_void;
+        unsafe { T::__drop(this) }
+    }
+}
+
+impl<T> Deref for SharedPtr<T>
+where
+    T: SharedPtrTarget,
+{
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        match self.as_ref() {
+            Some(target) => target,
+            None => panic!("called deref on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+impl<T> DerefMut for SharedPtr<T>
+where
+    T: SharedPtrTarget + Unpin,
+{
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        match self.as_mut() {
+            Some(target) => Pin::into_inner(target),
+            None => panic!("called deref_mut on a null SharedPtr<{}>", T::__NAME),
+        }
+    }
+}
+
+impl<T> Debug for SharedPtr<T>
+where
+    T: Debug + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        match self.as_ref() {
+            None => formatter.write_str("nullptr"),
+            Some(value) => Debug::fmt(value, formatter),
+        }
+    }
+}
+
+impl<T> Display for SharedPtr<T>
+where
+    T: Display + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        match self.as_ref() {
+            None => formatter.write_str("nullptr"),
+            Some(value) => Display::fmt(value, formatter),
+        }
+    }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+pub unsafe trait SharedPtrTarget {
+    #[doc(hidden)]
+    const __NAME: &'static dyn Display;
+    #[doc(hidden)]
+    unsafe fn __null(new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __new(value: Self, new: *mut c_void)
+    where
+        Self: Sized,
+    {
+        // Opoaque C types do not get this method because they can never exist
+        // by value on the Rust side of the bridge.
+        let _ = value;
+        let _ = new;
+        unreachable!()
+    }
+    #[doc(hidden)]
+    unsafe fn __clone(this: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __get(this: *const c_void) -> *const Self;
+    #[doc(hidden)]
+    unsafe fn __drop(this: *mut c_void);
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index 2ebbf05..6dce563 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -32,6 +32,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
+            Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
@@ -115,6 +116,7 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
             cx.error(ptr, "unique_ptr of a Rust type is not supported yet");
+            return;
         }
 
         match Atom::from(&ident.rust) {
@@ -128,6 +130,29 @@ fn check_type_unique_ptr(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported unique_ptr target type");
 }
 
+fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(&ident.rust) {
+            cx.error(ptr, "shared_ptr of a Rust type is not supported yet");
+            return;
+        }
+
+        match Atom::from(&ident.rust) {
+            None => return,
+            Some(CxxString) => {
+                cx.error(ptr, "std::shared_ptr<std::string> is not supported yet");
+                return;
+            }
+            _ => {}
+        }
+    } else if let Type::CxxVector(_) = &ptr.inner {
+        cx.error(ptr, "std::shared_ptr<std::vector> is not supported yet");
+        return;
+    }
+
+    cx.error(ptr, "unsupported shared_ptr target type");
+}
+
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
@@ -135,6 +160,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
                 ptr,
                 "C++ vector containing a Rust type is not supported yet",
             );
+            return;
         }
 
         match Atom::from(&ident.rust) {
@@ -410,7 +436,7 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         return;
     }
 
-    if let Type::UniquePtr(ty) | Type::CxxVector(ty) = ty {
+    if let Type::UniquePtr(ty) | Type::SharedPtr(ty) | Type::CxxVector(ty) = ty {
         if let Type::Ident(inner) = &ty.inner {
             if Atom::from(&inner.rust).is_none() {
                 return;
@@ -473,6 +499,7 @@ fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"
+        || ident == "SharedPtr"
         || ident == "Vec"
         || ident == "CxxVector"
         || ident == "str"
@@ -493,6 +520,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         Type::RustBox(_)
         | Type::RustVec(_)
         | Type::UniquePtr(_)
+        | Type::SharedPtr(_)
         | Type::Ref(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
@@ -564,6 +592,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::RustBox(_) => "Box".to_owned(),
         Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
+        Type::SharedPtr(_) => "shared_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
diff --git a/syntax/error.rs b/syntax/error.rs
index d0ae021..a672329 100644
--- a/syntax/error.rs
+++ b/syntax/error.rs
@@ -29,7 +29,7 @@ pub static ERRORS: &[Error] = &[
 pub static BOX_CXX_TYPE: Error = Error {
     msg: "Box of a C++ type is not supported yet",
     label: None,
-    note: Some("hint: use UniquePtr<>"),
+    note: Some("hint: use UniquePtr<> or SharedPtr<>"),
 };
 
 pub static CXXBRIDGE_RESERVED: Error = Error {
@@ -47,7 +47,7 @@ pub static CXX_STRING_BY_VALUE: Error = Error {
 pub static CXX_TYPE_BY_VALUE: Error = Error {
     msg: "C++ type by value is not supported",
     label: None,
-    note: Some("hint: wrap it in a UniquePtr<>"),
+    note: Some("hint: wrap it in a UniquePtr<> or SharedPtr<>"),
 };
 
 pub static DISCRIMINANT_OVERFLOW: Error = Error {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 73cb1d9..9b154f6 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -45,6 +45,7 @@ impl Hash for Type {
             Type::Ident(t) => t.hash(state),
             Type::RustBox(t) => t.hash(state),
             Type::UniquePtr(t) => t.hash(state),
+            Type::SharedPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
@@ -65,6 +66,7 @@ impl PartialEq for Type {
             (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
             (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
+            (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
diff --git a/syntax/improper.rs b/syntax/improper.rs
index e0e5154..c0f6983 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -28,7 +28,7 @@ impl<'a> Types<'a> {
             | Type::Fn(_)
             | Type::Void(_)
             | Type::SliceRef(_) => Definite(true),
-            Type::UniquePtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::CxxVector(_) => Definite(false),
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index e8bd290..12b269e 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -167,6 +167,7 @@ pub enum Type {
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
+    SharedPtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a3f50ec..e4f0512 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -822,6 +822,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "SharedPtr" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::SharedPtr(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index edbf818..07738d8 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -20,9 +20,11 @@ impl ToTokens for Type {
                 }
                 ident.rust.to_tokens(tokens);
             }
-            Type::RustBox(ty) | Type::UniquePtr(ty) | Type::CxxVector(ty) | Type::RustVec(ty) => {
-                ty.to_tokens(tokens)
-            }
+            Type::RustBox(ty)
+            | Type::UniquePtr(ty)
+            | Type::SharedPtr(ty)
+            | Type::CxxVector(ty)
+            | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
@@ -44,7 +46,7 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
-        if let "UniquePtr" | "CxxVector" = name.as_str() {
+        if let "UniquePtr" | "SharedPtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
             tokens.extend(quote_spanned!(span=> ::std::vec::));
diff --git a/syntax/types.rs b/syntax/types.rs
index c98fe85..70b381f 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -45,6 +45,7 @@ impl<'a> Types<'a> {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
+                | Type::SharedPtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
@@ -254,7 +255,7 @@ impl<'a> Types<'a> {
                     Atom::from(&ident.rust) == Some(RustString)
                 }
             }
-            Type::RustVec(_) | Type::Array(_) => true,
+            Type::SharedPtr(_) | Type::RustVec(_) | Type::Array(_) => true,
             _ => false,
         }
     }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index fc69581..0c2b8b6 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -9,8 +9,9 @@
 pub mod cast;
 pub mod module;
 
-use cxx::{CxxString, CxxVector, UniquePtr};
+use cxx::{CxxString, CxxVector, SharedPtr, UniquePtr};
 use std::fmt::{self, Display};
+use std::mem::MaybeUninit;
 use std::os::raw::c_char;
 
 #[cxx::bridge(namespace = "tests")]
@@ -83,6 +84,7 @@ pub mod ffi {
         fn c_return_shared() -> Shared;
         fn c_return_box() -> Box<R>;
         fn c_return_unique_ptr() -> UniquePtr<C>;
+        fn c_return_shared_ptr() -> SharedPtr<C>;
         fn c_return_ref(shared: &Shared) -> &usize;
         fn c_return_mut(shared: &mut Shared) -> &mut usize;
         fn c_return_str(shared: &Shared) -> &str;
@@ -198,6 +200,7 @@ pub mod ffi {
         fn r_return_shared() -> Shared;
         fn r_return_box() -> Box<R>;
         fn r_return_unique_ptr() -> UniquePtr<C>;
+        fn r_return_shared_ptr() -> SharedPtr<C>;
         fn r_return_ref(shared: &Shared) -> &usize;
         fn r_return_mut(shared: &mut Shared) -> &mut usize;
         fn r_return_str(shared: &Shared) -> &str;
@@ -217,6 +220,7 @@ pub mod ffi {
         fn r_take_shared(shared: Shared);
         fn r_take_box(r: Box<R>);
         fn r_take_unique_ptr(c: UniquePtr<C>);
+        fn r_take_shared_ptr(c: SharedPtr<C>);
         fn r_take_ref_r(r: &R);
         fn r_take_ref_c(c: &C);
         fn r_take_str(s: &str);
@@ -377,6 +381,18 @@ fn r_return_unique_ptr() -> UniquePtr<ffi::C> {
     unsafe { UniquePtr::from_raw(cxx_test_suite_get_unique_ptr()) }
 }
 
+fn r_return_shared_ptr() -> SharedPtr<ffi::C> {
+    extern "C" {
+        fn cxx_test_suite_get_shared_ptr(repr: *mut SharedPtr<ffi::C>);
+    }
+    let mut shared_ptr = MaybeUninit::<SharedPtr<ffi::C>>::uninit();
+    let repr = shared_ptr.as_mut_ptr();
+    unsafe {
+        cxx_test_suite_get_shared_ptr(repr);
+        shared_ptr.assume_init()
+    }
+}
+
 fn r_return_ref(shared: &ffi::Shared) -> &usize {
     &shared.z
 }
@@ -462,6 +478,10 @@ fn r_take_unique_ptr(c: UniquePtr<ffi::C>) {
     let _ = c;
 }
 
+fn r_take_shared_ptr(c: SharedPtr<ffi::C>) {
+    let _ = c;
+}
+
 fn r_take_ref_r(r: &R) {
     let _ = r;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 6fd43ae..47d447c 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -57,6 +57,10 @@ std::unique_ptr<C> c_return_unique_ptr() {
   return std::unique_ptr<C>(new C{2020});
 }
 
+std::shared_ptr<C> c_return_shared_ptr() {
+  return std::shared_ptr<C>(new C{2020});
+}
+
 std::unique_ptr<::H::H> c_return_ns_unique_ptr() {
   return std::unique_ptr<::H::H>(new ::H::H{"hello"});
 }
@@ -479,6 +483,11 @@ extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
 
+extern "C" void
+cxx_test_suite_get_shared_ptr(std::shared_ptr<C> *repr) noexcept {
+  new (repr) std::shared_ptr<C>(new C{2020});
+}
+
 extern "C" std::string *cxx_test_suite_get_unique_ptr_string() noexcept {
   return std::unique_ptr<std::string>(new std::string("2020")).release();
 }
@@ -611,6 +620,7 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r_return_shared().z == 2020);
   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));
   ASSERT(r_return_unique_ptr()->get() == 2020);
+  ASSERT(r_return_shared_ptr()->get() == 2020);
   ASSERT(r_return_ref(Shared{2020}) == 2020);
   ASSERT(std::string(r_return_str(Shared{2020})) == "2020");
   ASSERT(std::string(r_return_rust_string()) == "2020");
@@ -624,6 +634,7 @@ extern "C" const char *cxx_run_test() noexcept {
   r_take_primitive(2020);
   r_take_shared(Shared{2020});
   r_take_unique_ptr(std::unique_ptr<C>(new C{2020}));
+  r_take_shared_ptr(std::shared_ptr<C>(new C{2020}));
   r_take_ref_c(C{2020});
   r_take_str(rust::Str("2020"));
   r_take_slice_char(rust::Slice<const char>(SLICE_DATA, sizeof(SLICE_DATA)));
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 5791983..0e16ab7 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -77,6 +77,7 @@ Shared c_return_shared();
 ::A::B::ABShared c_return_nested_ns_shared();
 rust::Box<R> c_return_box();
 std::unique_ptr<C> c_return_unique_ptr();
+std::shared_ptr<C> c_return_shared_ptr();
 std::unique_ptr<::H::H> c_return_ns_unique_ptr();
 const size_t &c_return_ref(const Shared &shared);
 const size_t &c_return_ns_ref(const ::A::AShared &shared);
diff --git a/tests/test.rs b/tests/test.rs
index 1b9a88e..d339152 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -36,6 +36,7 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, ffi::c_return_box().0);
     ffi::c_return_unique_ptr();
+    ffi::c_return_shared_ptr();
     ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));

From 23a0e9d1bc42718bbf22a9789e92eb376f4ee664 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 05:00:02 +0000
Subject: [PATCH 1643/2232] Insert some pointer casts to hide type of ptr target from improper_ctypes


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 82b79aa..a94625a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1087,25 +1087,25 @@ fn expand_unique_ptr(
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
-                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut #ident);
+                    fn __raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::std::ffi::c_void);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                __raw(&mut repr, raw);
+                __raw(&mut repr, raw.cast());
                 repr
             }
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const #ident;
+                    fn __get(this: *const *mut ::std::ffi::c_void) -> *const ::std::ffi::c_void;
                 }
-                __get(&repr)
+                __get(&repr).cast()
             }
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
-                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut #ident;
+                    fn __release(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
-                __release(&mut repr)
+                __release(&mut repr).cast()
             }
             unsafe fn __drop(mut repr: *mut ::std::ffi::c_void) {
                 extern "C" {
@@ -1139,9 +1139,9 @@ fn expand_shared_ptr(
             unsafe fn __new(mut value: Self, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_new]
-                    fn __new(new: *mut ::std::ffi::c_void, value: *mut #ident);
+                    fn __new(new: *mut ::std::ffi::c_void, value: *mut ::std::ffi::c_void);
                 }
-                __new(new, &mut value);
+                __new(new, &mut value as *mut Self as *mut ::std::ffi::c_void);
             }
         })
     } else {
@@ -1174,9 +1174,9 @@ fn expand_shared_ptr(
             unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
-                    fn __get(this: *const ::std::ffi::c_void) -> *const #ident;
+                    fn __get(this: *const ::std::ffi::c_void) -> *const ::std::ffi::c_void;
                 }
-                __get(this)
+                __get(this).cast()
             }
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {

From 0b8814062bab1258396745a37f06bc953feb1441 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 05:40:52 +0000
Subject: [PATCH 1644/2232] Skip a move construction on Unique/SharedPtr::new


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 26da9e4..77bff8d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1520,16 +1520,19 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
+        out.builtin.maybe_uninit = true;
         writeln!(
             out,
-            "void cxxbridge1$unique_ptr${}$new(::std::unique_ptr<{}> *ptr, {} *value) noexcept {{",
-            instance, inner, inner,
+            "{} *cxxbridge1$unique_ptr${}$uninit(::std::unique_ptr<{}> *ptr) noexcept {{",
+            inner, instance, inner,
         );
         writeln!(
             out,
-            "  new (ptr) ::std::unique_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
+            "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
+            inner, inner, inner,
         );
+        writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
+        writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
     writeln!(
@@ -1615,16 +1618,19 @@ fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
     writeln!(out, "  new (ptr) ::std::shared_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
+        out.builtin.maybe_uninit = true;
         writeln!(
             out,
-            "void cxxbridge1$shared_ptr${}$new(::std::shared_ptr<{}> *ptr, {} *value) noexcept {{",
-            instance, inner, inner,
+            "{} *cxxbridge1$shared_ptr${}$uninit(::std::shared_ptr<{}> *ptr) noexcept {{",
+            inner, instance, inner,
         );
         writeln!(
             out,
-            "  new (ptr) ::std::shared_ptr<{}>(new {}(::std::move(*value)));",
-            inner, inner,
+            "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
+            inner, inner, inner,
         );
+        writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
+        writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
     writeln!(
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index a94625a..9f16e5e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1041,7 +1041,7 @@ fn expand_unique_ptr(
     let name = ident.rust.to_string();
     let prefix = format!("cxxbridge1$unique_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
-    let link_new = format!("{}new", prefix);
+    let link_uninit = format!("{}uninit", prefix);
     let link_raw = format!("{}raw", prefix);
     let link_get = format!("{}get", prefix);
     let link_release = format!("{}release", prefix);
@@ -1054,11 +1054,11 @@ fn expand_unique_ptr(
         Some(quote! {
             fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
+                    #[link_name = #link_uninit]
+                    fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __new(&mut repr, &mut value) }
+                unsafe { __uninit(&mut repr).cast::<#ident>().write(value) }
                 repr
             }
         })
@@ -1126,7 +1126,7 @@ fn expand_shared_ptr(
     let name = ident.rust.to_string();
     let prefix = format!("cxxbridge1$shared_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
-    let link_new = format!("{}new", prefix);
+    let link_uninit = format!("{}uninit", prefix);
     let link_clone = format!("{}clone", prefix);
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
@@ -1138,10 +1138,10 @@ fn expand_shared_ptr(
         Some(quote! {
             unsafe fn __new(mut value: Self, new: *mut ::std::ffi::c_void) {
                 extern "C" {
-                    #[link_name = #link_new]
-                    fn __new(new: *mut ::std::ffi::c_void, value: *mut ::std::ffi::c_void);
+                    #[link_name = #link_uninit]
+                    fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
-                __new(new, &mut value as *mut Self as *mut ::std::ffi::c_void);
+                __uninit(new).cast::<#ident>().write(value);
             }
         })
     } else {

From b745381af449c1574198f338705f611d183e2163 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 05:46:55 +0000
Subject: [PATCH 1645/2232] Fix shared_ptr explicit impl C++ codegen condition


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 77bff8d..1fb45d9 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1280,7 +1280,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
         } else if let Type::SharedPtr(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
-                    && !(out.types.aliases.contains_key(&inner.rust)
+                    && (!out.types.aliases.contains_key(&inner.rust)
                         || out.types.explicit_impls.contains(ty))
                 {
                     out.next_section();

From 42c0ea7058789aa8cc6c27c433a3e0e043f2cf0c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 05:49:36 +0000
Subject: [PATCH 1646/2232] Remove requirement that shared_ptr T be incomplete type


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 1fb45d9..419e46c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1592,14 +1592,6 @@ fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
         || out.types.enums.contains_key(&ident.rust)
         || out.types.aliases.contains_key(&ident.rust);
 
-    if !out.types.structs.contains_key(&ident.rust) && !out.types.enums.contains_key(&ident.rust) {
-        out.builtin.is_complete = true;
-        writeln!(
-            out,
-            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
-            inner, resolved.cxx,
-        );
-    }
     writeln!(
         out,
         "static_assert(sizeof(::std::shared_ptr<{}>) == 2 * sizeof(void *), \"\");",

From e58f3a0ce002f3f72fd48cb910ae21e3ff6547d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 02 2020 18:36:49 +0000
Subject: [PATCH 1647/2232] Release 1.0.10


---

diff --git a/Cargo.toml b/Cargo.toml
index 2c01d1e..451759c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.9" # remember to update html_root_url
+version = "1.0.10" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.9", path = "macro" }
+cxxbridge-macro = { version = "=1.0.10", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.9", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.10", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.9", path = "gen/build" }
+cxx-build = { version = "=1.0.10", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 3afb072..c925131 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.9"
+version = "1.0.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 63bff45..d294226 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.9"
+version = "1.0.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 0b62654..95b3e3c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.9"
+version = "1.0.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index dee56bd..05a57d8 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.9"
+version = "0.7.10"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 0041254..2927300 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.9"
+version = "1.0.10"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index bfd7a51..fb52ce1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.9")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.10")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 92896d8..30c360c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.9"
+version = "1.0.10"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.9"
+version = "1.0.10"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.9"
+version = "0.7.10"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.9"
+version = "1.0.10"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.9"
+version = "1.0.10"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.9"
+version = "1.0.10"
 dependencies = [
  "cxx",
  "proc-macro2",

From efd5cd443cfe0ece7504f7bc858a29b936e8b77d Mon Sep 17 00:00:00 2001
From: Yan Zaretskiy <yzaretskiy@stoneridgetechnology.com>
Date: Dec 03 2020 14:22:22 +0000
Subject: [PATCH 1648/2232] Implement the random access iterator for rust::Vec


---

diff --git a/include/cxx.h b/include/cxx.h
index 8c3f241..cbaf129 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -293,18 +293,33 @@ private:
 template <typename T>
 class Vec<T>::iterator final {
 public:
-  using difference_type = ptrdiff_t;
+  using iterator_category = std::random_access_iterator_tag;
   using value_type = T;
+  using difference_type = ptrdiff_t;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
-  using iterator_category = std::forward_iterator_tag;
 
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
+  reference operator*() const noexcept;
+  pointer operator->() const noexcept;
+  reference operator[](difference_type) const noexcept;
+
   iterator &operator++() noexcept;
   iterator operator++(int) noexcept;
+  iterator &operator--() noexcept;
+  iterator operator--(int) noexcept;
+
+  iterator &operator+=(difference_type) noexcept;
+  iterator &operator-=(difference_type) noexcept;
+  iterator operator+(difference_type) const noexcept;
+  iterator operator-(difference_type) const noexcept;
+  difference_type operator-(const iterator &) const noexcept;
+
   bool operator==(const iterator &) const noexcept;
   bool operator!=(const iterator &) const noexcept;
+  bool operator<(const iterator &) const noexcept;
+  bool operator>(const iterator &) const noexcept;
+  bool operator<=(const iterator &) const noexcept;
+  bool operator>=(const iterator &) const noexcept;
 
 private:
   friend class Vec;
@@ -737,16 +752,23 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
-T &Vec<T>::iterator::operator*() const noexcept {
+typename Vec<T>::iterator::reference Vec<T>::iterator::operator*() const noexcept {
   return *static_cast<T *>(this->pos);
 }
 
 template <typename T>
-T *Vec<T>::iterator::operator->() const noexcept {
+typename Vec<T>::iterator::pointer Vec<T>::iterator::operator->() const noexcept {
   return static_cast<T *>(this->pos);
 }
 
 template <typename T>
+typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *static_cast<T *>(pos);
+}
+
+template <typename T>
 typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
   this->pos = static_cast<char *>(this->pos) + this->stride;
   return *this;
@@ -760,6 +782,57 @@ typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
 }
 
 template <typename T>
+typename Vec<T>::iterator &Vec<T>::iterator::operator--() noexcept {
+  this->pos = static_cast<char *>(this->pos) - this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
+  auto ret = iterator(*this);
+  this->pos = static_cast<char *>(this->pos) - this->stride;
+  return ret;
+}
+
+template <typename T>
+typename Vec<T>::iterator &
+Vec<T>::iterator::operator+=(Vec<T>::iterator::difference_type n) noexcept {
+  this->pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator &
+Vec<T>::iterator::operator-=(Vec<T>::iterator::difference_type n) noexcept {
+  this->pos = static_cast<char *>(this->pos) - this->stride * n;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator+(
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto temp = iterator(*this);
+  temp.pos = static_cast<char *>(this->pos) + this->stride * n;
+  return temp;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator-(
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto temp = iterator(*this);
+  temp.pos = static_cast<char *>(this->pos) - this->stride * n;
+  return temp;
+}
+
+template <typename T>
+typename Vec<T>::iterator::difference_type
+Vec<T>::iterator::operator-(const iterator &other) const noexcept {
+  auto diff = std::distance(static_cast<char *>(other.pos),
+                            static_cast<char *>(this->pos));
+  return diff / stride;
+}
+
+template <typename T>
 bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
   return this->pos == other.pos;
 }
@@ -770,6 +843,26 @@ bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
+bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
+  return this->pos > other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
+  return this->pos < other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
+  return this->pos >= other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
+  return this->pos <= other.pos;
+}
+
+template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0c2b8b6..ec77594 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -133,6 +133,7 @@ pub mod ffi {
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_push(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
+        fn c_take_rust_vec_shared_sort(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 47d447c..485346f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -365,6 +365,16 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_sort(rust::Vec<Shared> v) {
+  // Exercise requirements of RandomAccessIterator.
+  // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
+  std::sort(v.begin(), v.end());
+  if (v[0].z == 0 && v[1].z == 2 && v[2].z == 4 && v[3].z == 7)
+  {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
   if (v[0].z == 1010 && v.at(0).z == 1010 && v.front().z == 1010 &&
       v[1].z == 1011 && v.at(1).z == 1011 && v.back().z == 1011) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0e16ab7..024ecea 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -134,6 +134,7 @@ void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_push(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_sort(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
diff --git a/tests/test.rs b/tests/test.rs
index d339152..a272335 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,6 +149,10 @@ fn test_c_take() {
     check!(ffi::c_take_rust_vec_shared_forward_iterator(
         shared_test_vec,
     ));
+    let shared_sort_vec = vec![ffi::Shared { z: 2 }, ffi::Shared { z: 0 }, ffi::Shared { z: 7 }, ffi::Shared { z: 4 }];
+    check!(ffi::c_take_rust_vec_shared_sort(
+        shared_sort_vec,
+    ));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));

From ff01bbc1f7cb9ab8efd6b1cd4f3ff324dbaf1808 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 03 2020 20:25:56 +0000
Subject: [PATCH 1649/2232] Merge pull request #538 from mindv0rtex/vec_iterator


Implement the random access iterator for rust::Vec
---

diff --git a/include/cxx.h b/include/cxx.h
index 8c3f241..cbaf129 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -293,18 +293,33 @@ private:
 template <typename T>
 class Vec<T>::iterator final {
 public:
-  using difference_type = ptrdiff_t;
+  using iterator_category = std::random_access_iterator_tag;
   using value_type = T;
+  using difference_type = ptrdiff_t;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
-  using iterator_category = std::forward_iterator_tag;
 
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
+  reference operator*() const noexcept;
+  pointer operator->() const noexcept;
+  reference operator[](difference_type) const noexcept;
+
   iterator &operator++() noexcept;
   iterator operator++(int) noexcept;
+  iterator &operator--() noexcept;
+  iterator operator--(int) noexcept;
+
+  iterator &operator+=(difference_type) noexcept;
+  iterator &operator-=(difference_type) noexcept;
+  iterator operator+(difference_type) const noexcept;
+  iterator operator-(difference_type) const noexcept;
+  difference_type operator-(const iterator &) const noexcept;
+
   bool operator==(const iterator &) const noexcept;
   bool operator!=(const iterator &) const noexcept;
+  bool operator<(const iterator &) const noexcept;
+  bool operator>(const iterator &) const noexcept;
+  bool operator<=(const iterator &) const noexcept;
+  bool operator>=(const iterator &) const noexcept;
 
 private:
   friend class Vec;
@@ -737,16 +752,23 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
-T &Vec<T>::iterator::operator*() const noexcept {
+typename Vec<T>::iterator::reference Vec<T>::iterator::operator*() const noexcept {
   return *static_cast<T *>(this->pos);
 }
 
 template <typename T>
-T *Vec<T>::iterator::operator->() const noexcept {
+typename Vec<T>::iterator::pointer Vec<T>::iterator::operator->() const noexcept {
   return static_cast<T *>(this->pos);
 }
 
 template <typename T>
+typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *static_cast<T *>(pos);
+}
+
+template <typename T>
 typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
   this->pos = static_cast<char *>(this->pos) + this->stride;
   return *this;
@@ -760,6 +782,57 @@ typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
 }
 
 template <typename T>
+typename Vec<T>::iterator &Vec<T>::iterator::operator--() noexcept {
+  this->pos = static_cast<char *>(this->pos) - this->stride;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
+  auto ret = iterator(*this);
+  this->pos = static_cast<char *>(this->pos) - this->stride;
+  return ret;
+}
+
+template <typename T>
+typename Vec<T>::iterator &
+Vec<T>::iterator::operator+=(Vec<T>::iterator::difference_type n) noexcept {
+  this->pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator &
+Vec<T>::iterator::operator-=(Vec<T>::iterator::difference_type n) noexcept {
+  this->pos = static_cast<char *>(this->pos) - this->stride * n;
+  return *this;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator+(
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto temp = iterator(*this);
+  temp.pos = static_cast<char *>(this->pos) + this->stride * n;
+  return temp;
+}
+
+template <typename T>
+typename Vec<T>::iterator Vec<T>::iterator::operator-(
+    Vec<T>::iterator::difference_type n) const noexcept {
+  auto temp = iterator(*this);
+  temp.pos = static_cast<char *>(this->pos) - this->stride * n;
+  return temp;
+}
+
+template <typename T>
+typename Vec<T>::iterator::difference_type
+Vec<T>::iterator::operator-(const iterator &other) const noexcept {
+  auto diff = std::distance(static_cast<char *>(other.pos),
+                            static_cast<char *>(this->pos));
+  return diff / stride;
+}
+
+template <typename T>
 bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
   return this->pos == other.pos;
 }
@@ -770,6 +843,26 @@ bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
+bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
+  return this->pos > other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
+  return this->pos < other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
+  return this->pos >= other.pos;
+}
+
+template <typename T>
+bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
+  return this->pos <= other.pos;
+}
+
+template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 0c2b8b6..ec77594 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -133,6 +133,7 @@ pub mod ffi {
         fn c_take_rust_vec_shared_index(v: Vec<Shared>);
         fn c_take_rust_vec_shared_push(v: Vec<Shared>);
         fn c_take_rust_vec_shared_forward_iterator(v: Vec<Shared>);
+        fn c_take_rust_vec_shared_sort(v: Vec<Shared>);
         fn c_take_ref_rust_vec(v: &Vec<u8>);
         fn c_take_ref_rust_vec_string(v: &Vec<String>);
         fn c_take_ref_rust_vec_index(v: &Vec<u8>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 47d447c..485346f 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -365,6 +365,16 @@ void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v) {
   }
 }
 
+void c_take_rust_vec_shared_sort(rust::Vec<Shared> v) {
+  // Exercise requirements of RandomAccessIterator.
+  // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
+  std::sort(v.begin(), v.end());
+  if (v[0].z == 0 && v[1].z == 2 && v[2].z == 4 && v[3].z == 7)
+  {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v) {
   if (v[0].z == 1010 && v.at(0).z == 1010 && v.front().z == 1010 &&
       v[1].z == 1011 && v.at(1).z == 1011 && v.back().z == 1011) {
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0e16ab7..024ecea 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -134,6 +134,7 @@ void c_take_rust_vec_string(rust::Vec<rust::String> v);
 void c_take_rust_vec_shared_index(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_push(rust::Vec<Shared> v);
 void c_take_rust_vec_shared_forward_iterator(rust::Vec<Shared> v);
+void c_take_rust_vec_shared_sort(rust::Vec<Shared> v);
 void c_take_ref_rust_vec(const rust::Vec<uint8_t> &v);
 void c_take_ref_rust_vec_string(const rust::Vec<rust::String> &v);
 void c_take_ref_rust_vec_index(const rust::Vec<uint8_t> &v);
diff --git a/tests/test.rs b/tests/test.rs
index d339152..a272335 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,6 +149,10 @@ fn test_c_take() {
     check!(ffi::c_take_rust_vec_shared_forward_iterator(
         shared_test_vec,
     ));
+    let shared_sort_vec = vec![ffi::Shared { z: 2 }, ffi::Shared { z: 0 }, ffi::Shared { z: 7 }, ffi::Shared { z: 4 }];
+    check!(ffi::c_take_rust_vec_shared_sort(
+        shared_sort_vec,
+    ));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));

From 300072b5f36f68d0fda51a53427ee97e7147c85b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 03 2020 20:27:27 +0000
Subject: [PATCH 1650/2232] Touch up PR 538


---

diff --git a/include/cxx.h b/include/cxx.h
index cbaf129..da0194a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -752,12 +752,14 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
-typename Vec<T>::iterator::reference Vec<T>::iterator::operator*() const noexcept {
+typename Vec<T>::iterator::reference
+Vec<T>::iterator::operator*() const noexcept {
   return *static_cast<T *>(this->pos);
 }
 
 template <typename T>
-typename Vec<T>::iterator::pointer Vec<T>::iterator::operator->() const noexcept {
+typename Vec<T>::iterator::pointer
+Vec<T>::iterator::operator->() const noexcept {
   return static_cast<T *>(this->pos);
 }
 
@@ -811,17 +813,17 @@ Vec<T>::iterator::operator-=(Vec<T>::iterator::difference_type n) noexcept {
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator+(
     Vec<T>::iterator::difference_type n) const noexcept {
-  auto temp = iterator(*this);
-  temp.pos = static_cast<char *>(this->pos) + this->stride * n;
-  return temp;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) + this->stride * n;
+  return ret;
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator-(
     Vec<T>::iterator::difference_type n) const noexcept {
-  auto temp = iterator(*this);
-  temp.pos = static_cast<char *>(this->pos) - this->stride * n;
-  return temp;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) - this->stride * n;
+  return ret;
 }
 
 template <typename T>
@@ -829,7 +831,7 @@ typename Vec<T>::iterator::difference_type
 Vec<T>::iterator::operator-(const iterator &other) const noexcept {
   auto diff = std::distance(static_cast<char *>(other.pos),
                             static_cast<char *>(this->pos));
-  return diff / stride;
+  return diff / this->stride;
 }
 
 template <typename T>
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 485346f..2be1e06 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -369,8 +369,7 @@ void c_take_rust_vec_shared_sort(rust::Vec<Shared> v) {
   // Exercise requirements of RandomAccessIterator.
   // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
   std::sort(v.begin(), v.end());
-  if (v[0].z == 0 && v[1].z == 2 && v[2].z == 4 && v[3].z == 7)
-  {
+  if (v[0].z == 0 && v[1].z == 2 && v[2].z == 4 && v[3].z == 7) {
     cxx_test_suite_set_correct();
   }
 }
diff --git a/tests/test.rs b/tests/test.rs
index a272335..00a7228 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -149,10 +149,13 @@ fn test_c_take() {
     check!(ffi::c_take_rust_vec_shared_forward_iterator(
         shared_test_vec,
     ));
-    let shared_sort_vec = vec![ffi::Shared { z: 2 }, ffi::Shared { z: 0 }, ffi::Shared { z: 7 }, ffi::Shared { z: 4 }];
-    check!(ffi::c_take_rust_vec_shared_sort(
-        shared_sort_vec,
-    ));
+    let shared_sort_vec = vec![
+        ffi::Shared { z: 2 },
+        ffi::Shared { z: 0 },
+        ffi::Shared { z: 7 },
+        ffi::Shared { z: 4 },
+    ];
+    check!(ffi::c_take_rust_vec_shared_sort(shared_sort_vec));
     check!(ffi::c_take_ref_rust_vec(&test_vec));
     check!(ffi::c_take_ref_rust_vec_index(&test_vec));
     check!(ffi::c_take_ref_rust_vec_copy(&test_vec));
@@ -207,7 +210,7 @@ fn test_c_method_calls() {
     assert_eq!(2021, unique_ptr.pin_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
-    assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap(),);
+    assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap());
     assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
 

From 130fc4e00f7cfe340e5092aa4de9fdcb98604a9b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 03 2020 20:27:27 +0000
Subject: [PATCH 1651/2232] Add Vec iterator random access APIs to book


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index e2eaecb..75f502b 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -59,31 +59,63 @@ public:
 # template <typename T>
 # class Vec<T>::iterator final {
 # public:
+#   using iterator_category = std::random_access_iterator_tag;
 #   using value_type = T;
 #   using pointer = T *;
 #   using reference = T &;
 #
 #   T &operator*() const noexcept;
 #   T *operator->() const noexcept;
+#   T &operator[](ptrdiff_t) const noexcept;
+#
 #   iterator &operator++() noexcept;
 #   iterator operator++(int) noexcept;
+#   iterator &operator--() noexcept;
+#   iterator operator--(int) noexcept;
+#
+#   iterator &operator+=(ptrdiff_t) noexcept;
+#   iterator &operator-=(ptrdiff_t) noexcept;
+#   iterator operator+(ptrdiff_t) const noexcept;
+#   iterator operator-(ptrdiff_t) const noexcept;
+#   ptrdiff_t operator-(const iterator &) const noexcept;
+#
 #   bool operator==(const iterator &) const noexcept;
 #   bool operator!=(const iterator &) const noexcept;
+#   bool operator<(const iterator &) const noexcept;
+#   bool operator>(const iterator &) const noexcept;
+#   bool operator<=(const iterator &) const noexcept;
+#   bool operator>=(const iterator &) const noexcept;
 # };
 #
 # template <typename T>
 # class Vec<T>::const_iterator final {
 # public:
+#   using iterator_category = std::random_access_iterator_tag;
 #   using value_type = const T;
 #   using pointer = const T *;
 #   using reference = const T &;
 #
 #   const T &operator*() const noexcept;
 #   const T *operator->() const noexcept;
+#   const T &operator[](ptrdiff_t) const noexcept;
+#
 #   const_iterator &operator++() noexcept;
 #   const_iterator operator++(int) noexcept;
+#   const_iterator &operator--() noexcept;
+#   const_iterator operator--(int) noexcept;
+#
+#   const_iterator &operator+=(ptrdiff_t) noexcept;
+#   const_iterator &operator-=(ptrdiff_t) noexcept;
+#   const_iterator operator+(ptrdiff_t) const noexcept;
+#   const_iterator operator-(ptrdiff_t) const noexcept;
+#   ptrdiff_t operator-(const const_iterator &) const noexcept;
+#
 #   bool operator==(const const_iterator &) const noexcept;
 #   bool operator!=(const const_iterator &) const noexcept;
+#   bool operator<(const const_iterator &) const noexcept;
+#   bool operator>(const const_iterator &) const noexcept;
+#   bool operator<=(const const_iterator &) const noexcept;
+#   bool operator>=(const const_iterator &) const noexcept;
 # };
 #
 # } // namespace rust

From 764dda27cfa220fb9a68661a77ed4b84f9d1c489 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 03 2020 20:29:48 +0000
Subject: [PATCH 1652/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 0a2a665..afb1520 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.65/src/**"]),
+    srcs = glob(["vendor/cc-1.0.66/src/**"]),
     visibility = ["PUBLIC"],
 )
 
diff --git a/third-party/BUILD b/third-party/BUILD
index 79999d3..b9d71a3 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -13,7 +13,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.65/src/**"]),
+    srcs = glob(["vendor/cc-1.0.66/src/**"]),
     visibility = ["//visibility:public"],
 )
 
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 30c360c..f02d255 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -28,9 +28,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.65"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
+checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
 
 [[package]]
 name = "clap"
@@ -252,9 +252,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
+checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
 dependencies = [
  "itoa",
  "ryu",

From 7297d74fd0bc61dab74d76226ba43a2e64c72212 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 03 2020 20:30:29 +0000
Subject: [PATCH 1653/2232] Release 1.0.11


---

diff --git a/Cargo.toml b/Cargo.toml
index 451759c..d377e6a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.10" # remember to update html_root_url
+version = "1.0.11" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.10", path = "macro" }
+cxxbridge-macro = { version = "=1.0.11", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.10", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.11", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.10", path = "gen/build" }
+cxx-build = { version = "=1.0.11", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index c925131..dbfd484 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.10"
+version = "1.0.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index d294226..3f6b73d 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.10"
+version = "1.0.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 95b3e3c..eda9092 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.10"
+version = "1.0.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 05a57d8..5317db8 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.10"
+version = "0.7.11"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 2927300..e754edf 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.10"
+version = "1.0.11"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index fb52ce1..8f56ed6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.10")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.11")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f02d255..6ec111d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.10"
+version = "1.0.11"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.10"
+version = "1.0.11"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.10"
+version = "0.7.11"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.10"
+version = "1.0.11"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.10"
+version = "1.0.11"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.10"
+version = "1.0.11"
 dependencies = [
  "cxx",
  "proc-macro2",

From 181ee912ac24a8ce6a85d7754b7197977fdd7237 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 04 2020 20:17:10 +0000
Subject: [PATCH 1654/2232] Restrict CxxVector::as_slice to types where size is definite


&[T] where T is an opaque C++ type isn't meaningful because Rust
wouldn't know the size of the type and therefore how big of a stride to
take between slice elements. Opaque C++ types are implemented as Rust
ZSTs so the observed effect would be seeing N copies of just the first
vector element, which is memory safe but misleading.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d1611db..b8de942 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,4 +1,6 @@
 use crate::cxx_string::CxxString;
+use crate::extern_type::ExternType;
+use crate::kind::Trivial;
 use core::ffi::c_void;
 use core::fmt::{self, Display};
 use core::marker::{PhantomData, PhantomPinned};
@@ -67,7 +69,10 @@ where
     }
 
     /// Returns a slice to the underlying contiguous array of elements.
-    pub fn as_slice(&self) -> &[T] {
+    pub fn as_slice(&self) -> &[T]
+    where
+        T: ExternType<Kind = Trivial>,
+    {
         let len = self.len();
         if len == 0 {
             // The slice::from_raw_parts in the other branch requires a nonnull

From a23d7fd9efbc551d57977edeaf7fe770321072db Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 04 2020 20:27:25 +0000
Subject: [PATCH 1655/2232] Support root namespace in namespace attribute


---

diff --git a/syntax/qualified.rs b/syntax/qualified.rs
index 5eefb8d..96f07c1 100644
--- a/syntax/qualified.rs
+++ b/syntax/qualified.rs
@@ -10,14 +10,14 @@ impl QualifiedName {
     pub fn parse_unquoted(input: ParseStream) -> Result<Self> {
         let mut segments = Vec::new();
         let mut trailing_punct = true;
-        input.parse::<Option<Token![::]>>()?;
+        let leading_colons: Option<Token![::]> = input.parse()?;
         while trailing_punct && input.peek(Ident::peek_any) {
             let ident = Ident::parse_any(input)?;
             segments.push(ident);
             let colons: Option<Token![::]> = input.parse()?;
             trailing_punct = colons.is_some();
         }
-        if segments.is_empty() {
+        if segments.is_empty() && leading_colons.is_none() {
             return Err(input.error("expected path"));
         } else if trailing_punct {
             return Err(input.error("expected path segment"));
@@ -28,7 +28,12 @@ impl QualifiedName {
     pub fn parse_quoted_or_unquoted(input: ParseStream) -> Result<Self> {
         if input.peek(LitStr) {
             let lit: LitStr = input.parse()?;
-            lit.parse_with(Self::parse_unquoted)
+            if lit.value().is_empty() {
+                let segments = Vec::new();
+                Ok(QualifiedName { segments })
+            } else {
+                lit.parse_with(Self::parse_unquoted)
+            }
         } else {
             Self::parse_unquoted(input)
         }
diff --git a/tests/ui/root_namespace.rs b/tests/ui/root_namespace.rs
new file mode 100644
index 0000000..886fbd9
--- /dev/null
+++ b/tests/ui/root_namespace.rs
@@ -0,0 +1,13 @@
+#[cxx::bridge]
+mod ffi {
+    #[namespace = "::"]
+    extern "Rust" {}
+
+    #[namespace = ""]
+    extern "Rust" {}
+
+    #[namespace = ]
+    extern "Rust" {}
+}
+
+fn main() {}
diff --git a/tests/ui/root_namespace.stderr b/tests/ui/root_namespace.stderr
new file mode 100644
index 0000000..ed07e66
--- /dev/null
+++ b/tests/ui/root_namespace.stderr
@@ -0,0 +1,5 @@
+error: unexpected token: `]`
+ --> $DIR/root_namespace.rs:9:19
+  |
+9 |     #[namespace = ]
+  |                   ^

From a8100ed5dca2f2fa8b4f385220e2ff504cf89709 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 04 2020 20:41:24 +0000
Subject: [PATCH 1656/2232] Add Debug impl for CxxVector<T>


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index b8de942..037fe6a 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -2,7 +2,7 @@ use crate::cxx_string::CxxString;
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use core::ffi::c_void;
-use core::fmt::{self, Display};
+use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
@@ -124,6 +124,15 @@ where
     }
 }
 
+impl<T> Debug for CxxVector<T>
+where
+    T: VectorElement + Debug,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.debug_list().entries(self).finish()
+    }
+}
+
 pub struct TypeName<T> {
     element: PhantomData<T>,
 }

From 15a9b0766c09f4081ea34968bf6d1b80441632e2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 04 2020 20:50:25 +0000
Subject: [PATCH 1657/2232] Merge pull request #540 from dtolnay/debug-cxxvector


Add Debug impl for CxxVector<T>
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index b8de942..037fe6a 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -2,7 +2,7 @@ use crate::cxx_string::CxxString;
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use core::ffi::c_void;
-use core::fmt::{self, Display};
+use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
@@ -124,6 +124,15 @@ where
     }
 }
 
+impl<T> Debug for CxxVector<T>
+where
+    T: VectorElement + Debug,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.debug_list().entries(self).finish()
+    }
+}
+
 pub struct TypeName<T> {
     element: PhantomData<T>,
 }

From 56f78f34339a64e57b67689d73013dedd2867464 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 04 2020 20:51:08 +0000
Subject: [PATCH 1658/2232] Release 1.0.12


---

diff --git a/Cargo.toml b/Cargo.toml
index d377e6a..1d2723f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.11" # remember to update html_root_url
+version = "1.0.12" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.11", path = "macro" }
+cxxbridge-macro = { version = "=1.0.12", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.11", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.12", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.11", path = "gen/build" }
+cxx-build = { version = "=1.0.12", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index dbfd484..73502d6 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.11"
+version = "1.0.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 3f6b73d..12c888a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.11"
+version = "1.0.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index eda9092..92badcc 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.11"
+version = "1.0.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 5317db8..d3ce393 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.11"
+version = "0.7.12"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index e754edf..15cdf24 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.11"
+version = "1.0.12"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 8f56ed6..75716a9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.11")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.12")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6ec111d..f6f6900 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.11"
+version = "1.0.12"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.11"
+version = "1.0.12"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.11"
+version = "0.7.12"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.11"
+version = "1.0.12"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.11"
+version = "1.0.12"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.11"
+version = "1.0.12"
 dependencies = [
  "cxx",
  "proc-macro2",

From fccf4e5b34453ed7421339b98d080154289c4a7b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 01:22:41 +0000
Subject: [PATCH 1659/2232] Fix Vec containing shared type from other module


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6dce563..21a8515 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -93,6 +93,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
         if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.aliases.contains_key(&ident.rust)
             && !cx.types.structs.contains_key(&ident.rust)
             && !cx.types.enums.contains_key(&ident.rust)
         {
@@ -328,6 +329,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
+            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
diff --git a/syntax/types.rs b/syntax/types.rs
index 70b381f..e2f5bf8 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -201,6 +201,12 @@ impl<'a> Types<'a> {
                 _ => {}
             }
         }
+        for ty in &all {
+            if let Type::RustVec(ty) = ty {
+                let reason = TrivialReason::VecElement;
+                insist_alias_types_are_trivial(&ty.inner, reason);
+            }
+        }
 
         let mut types = Types {
             all,
@@ -297,6 +303,7 @@ pub enum TrivialReason<'a> {
     StructField(&'a Struct),
     FunctionArgument(&'a ExternFn),
     FunctionReturn(&'a ExternFn),
+    VecElement,
 }
 
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {

From cb6562977a1e128eaebfd39c1ecfd003e223d5f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 01:22:41 +0000
Subject: [PATCH 1660/2232] Add Vec opaque type ui test


---

diff --git a/tests/ui/vec_opaque.rs b/tests/ui/vec_opaque.rs
new file mode 100644
index 0000000..d0b279c
--- /dev/null
+++ b/tests/ui/vec_opaque.rs
@@ -0,0 +1,34 @@
+#[cxx::bridge]
+mod handle {
+    extern "C++" {
+        type Job;
+    }
+}
+
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        type Job;
+    }
+
+    extern "Rust" {
+        fn f() -> Vec<Job>;
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    extern "C++" {
+        type Job = crate::handle::Job;
+    }
+
+    extern "Rust" {
+        fn f() -> Vec<Job>;
+    }
+}
+
+fn f() -> Vec<handle::Job> {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/vec_opaque.stderr b/tests/ui/vec_opaque.stderr
new file mode 100644
index 0000000..b8dad91
--- /dev/null
+++ b/tests/ui/vec_opaque.stderr
@@ -0,0 +1,22 @@
+error: Rust Vec containing C++ type is not supported yet
+  --> $DIR/vec_opaque.rs:15:19
+   |
+15 |         fn f() -> Vec<Job>;
+   |                   ^^^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a vector element in Vec<Job>
+  --> $DIR/vec_opaque.rs:11:9
+   |
+11 |         type Job;
+   |         ^^^^^^^^
+
+error[E0271]: type mismatch resolving `<handle::Job as ExternType>::Kind == Trivial`
+   --> $DIR/vec_opaque.rs:22:9
+    |
+22  |         type Job = crate::handle::Job;
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
+    |
+   ::: $WORKSPACE/src/extern_type.rs
+    |
+    | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
+    |                                         ----------- required by this bound in `verify_extern_kind`

From 99b3cb7bc494ffa172e80416c23d3983621df7ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 01:27:40 +0000
Subject: [PATCH 1661/2232] Add test of returning Vec with struct from other bridge


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ec77594..cabcdbc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -184,7 +184,10 @@ pub mod ffi {
     }
 
     extern "C++" {
+        include!("tests/ffi/module.rs.h");
+
         type COwnedEnum;
+        type Job = crate::module::ffi::Job;
     }
 
     #[repr(u32)]
@@ -211,6 +214,7 @@ pub mod ffi {
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_rust_vec_string() -> Vec<String>;
+        fn r_return_rust_vec_extern_struct() -> Vec<Job>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
@@ -435,6 +439,10 @@ fn r_return_rust_vec_string() -> Vec<String> {
     Vec::new()
 }
 
+fn r_return_rust_vec_extern_struct() -> Vec<ffi::Job> {
+    Vec::new()
+}
+
 fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     let _ = shared;
     unimplemented!()
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 5846e11..0dd51e5 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,5 +1,9 @@
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
+    struct Job {
+        raw: u32,
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 

From a7c80074e0e658e74628371b71f032489e451780 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 01:42:34 +0000
Subject: [PATCH 1662/2232] Update starlark targets with lib.rs.h dependency on module.rs.h


---

diff --git a/tests/BUCK b/tests/BUCK
index b6699e2..d131ddb 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -32,6 +32,7 @@ cxx_library(
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
+        "ffi/module.rs.h": ":module/header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
diff --git a/tests/BUILD b/tests/BUILD
index 9194ca4..7886e4f 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -35,6 +35,7 @@ cc_library(
     hdrs = ["ffi/tests.h"],
     deps = [
         ":bridge/include",
+        ":module/include",
         "//:core",
     ],
 )

From b110dfb0d46e661d8c80bef7eaeba065a8cd2d1b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 01:48:57 +0000
Subject: [PATCH 1663/2232] Merge pull request #541 from dtolnay/vec-extern


Fix Vec containing shared type from other module
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6dce563..21a8515 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -93,6 +93,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
     if let Type::Ident(ident) = &ty.inner {
         if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.aliases.contains_key(&ident.rust)
             && !cx.types.structs.contains_key(&ident.rust)
             && !cx.types.enums.contains_key(&ident.rust)
         {
@@ -328,6 +329,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
+            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
diff --git a/syntax/types.rs b/syntax/types.rs
index 70b381f..e2f5bf8 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -201,6 +201,12 @@ impl<'a> Types<'a> {
                 _ => {}
             }
         }
+        for ty in &all {
+            if let Type::RustVec(ty) = ty {
+                let reason = TrivialReason::VecElement;
+                insist_alias_types_are_trivial(&ty.inner, reason);
+            }
+        }
 
         let mut types = Types {
             all,
@@ -297,6 +303,7 @@ pub enum TrivialReason<'a> {
     StructField(&'a Struct),
     FunctionArgument(&'a ExternFn),
     FunctionReturn(&'a ExternFn),
+    VecElement,
 }
 
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
diff --git a/tests/BUCK b/tests/BUCK
index b6699e2..d131ddb 100644
--- a/tests/BUCK
+++ b/tests/BUCK
@@ -32,6 +32,7 @@ cxx_library(
     ],
     headers = {
         "ffi/lib.rs.h": ":bridge/header",
+        "ffi/module.rs.h": ":module/header",
         "ffi/tests.h": "ffi/tests.h",
     },
     deps = ["//:core"],
diff --git a/tests/BUILD b/tests/BUILD
index 9194ca4..7886e4f 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -35,6 +35,7 @@ cc_library(
     hdrs = ["ffi/tests.h"],
     deps = [
         ":bridge/include",
+        ":module/include",
         "//:core",
     ],
 )
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ec77594..cabcdbc 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -184,7 +184,10 @@ pub mod ffi {
     }
 
     extern "C++" {
+        include!("tests/ffi/module.rs.h");
+
         type COwnedEnum;
+        type Job = crate::module::ffi::Job;
     }
 
     #[repr(u32)]
@@ -211,6 +214,7 @@ pub mod ffi {
         fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn r_return_rust_vec() -> Vec<u8>;
         fn r_return_rust_vec_string() -> Vec<String>;
+        fn r_return_rust_vec_extern_struct() -> Vec<Job>;
         fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
         fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
         fn r_return_identity(_: usize) -> usize;
@@ -435,6 +439,10 @@ fn r_return_rust_vec_string() -> Vec<String> {
     Vec::new()
 }
 
+fn r_return_rust_vec_extern_struct() -> Vec<ffi::Job> {
+    Vec::new()
+}
+
 fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
     let _ = shared;
     unimplemented!()
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 5846e11..0dd51e5 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -1,5 +1,9 @@
 #[cxx::bridge(namespace = "tests")]
 pub mod ffi {
+    struct Job {
+        raw: u32,
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
diff --git a/tests/ui/vec_opaque.rs b/tests/ui/vec_opaque.rs
new file mode 100644
index 0000000..d0b279c
--- /dev/null
+++ b/tests/ui/vec_opaque.rs
@@ -0,0 +1,34 @@
+#[cxx::bridge]
+mod handle {
+    extern "C++" {
+        type Job;
+    }
+}
+
+#[cxx::bridge]
+mod ffi1 {
+    extern "C++" {
+        type Job;
+    }
+
+    extern "Rust" {
+        fn f() -> Vec<Job>;
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    extern "C++" {
+        type Job = crate::handle::Job;
+    }
+
+    extern "Rust" {
+        fn f() -> Vec<Job>;
+    }
+}
+
+fn f() -> Vec<handle::Job> {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/vec_opaque.stderr b/tests/ui/vec_opaque.stderr
new file mode 100644
index 0000000..b8dad91
--- /dev/null
+++ b/tests/ui/vec_opaque.stderr
@@ -0,0 +1,22 @@
+error: Rust Vec containing C++ type is not supported yet
+  --> $DIR/vec_opaque.rs:15:19
+   |
+15 |         fn f() -> Vec<Job>;
+   |                   ^^^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a vector element in Vec<Job>
+  --> $DIR/vec_opaque.rs:11:9
+   |
+11 |         type Job;
+   |         ^^^^^^^^
+
+error[E0271]: type mismatch resolving `<handle::Job as ExternType>::Kind == Trivial`
+   --> $DIR/vec_opaque.rs:22:9
+    |
+22  |         type Job = crate::handle::Job;
+    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
+    |
+   ::: $WORKSPACE/src/extern_type.rs
+    |
+    | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
+    |                                         ----------- required by this bound in `verify_extern_kind`

From 25ed783082f0a1a733a033606f03288ed8ee4493 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 02:22:07 +0000
Subject: [PATCH 1664/2232] Allow Box containing shared type from other module


#541, but for Box in addition to Vec.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 21a8515..e9d977b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -76,6 +76,7 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
 fn check_type_box(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.cxx.contains(&ident.rust)
+            && !cx.types.aliases.contains_key(&ident.rust)
             && !cx.types.structs.contains_key(&ident.rust)
             && !cx.types.enums.contains_key(&ident.rust)
         {
@@ -329,6 +330,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
             TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
             TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
+            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
             TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
         };
         let msg = format!(
diff --git a/syntax/types.rs b/syntax/types.rs
index e2f5bf8..1b61cdb 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -202,9 +202,16 @@ impl<'a> Types<'a> {
             }
         }
         for ty in &all {
-            if let Type::RustVec(ty) = ty {
-                let reason = TrivialReason::VecElement;
-                insist_alias_types_are_trivial(&ty.inner, reason);
+            match ty {
+                Type::RustBox(ty) => {
+                    let reason = TrivialReason::BoxTarget;
+                    insist_alias_types_are_trivial(&ty.inner, reason);
+                }
+                Type::RustVec(ty) => {
+                    let reason = TrivialReason::VecElement;
+                    insist_alias_types_are_trivial(&ty.inner, reason);
+                }
+                _ => {}
             }
         }
 
@@ -303,6 +310,7 @@ pub enum TrivialReason<'a> {
     StructField(&'a Struct),
     FunctionArgument(&'a ExternFn),
     FunctionReturn(&'a ExternFn),
+    BoxTarget,
     VecElement,
 }
 

From f33bc24057ae787604f869407865c607dc91ee25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 02:35:37 +0000
Subject: [PATCH 1665/2232] Respect explicit impls on Vec and Box


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 419e46c..6881e4c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1255,14 +1255,22 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                out.next_section();
-                write_rust_box_extern(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_rust_box_extern(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_rust_vec_extern(out, inner);
                 }
@@ -1287,8 +1295,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_shared_ptr(out, inner);
                 }
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
+        } else if let Type::CxxVector(vector) = ty {
+            if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
                         || out.types.explicit_impls.contains(ty))
@@ -1304,13 +1312,21 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    write_rust_box_impl(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     write_rust_vec_impl(out, inner);
                 }
             }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9f16e5e..43f152b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -68,13 +68,17 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_box(ident, types));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_vec(ident, types));
                 }
             }
diff --git a/syntax/check.rs b/syntax/check.rs
index e9d977b..3b7b513 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -440,12 +440,19 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         return;
     }
 
-    if let Type::UniquePtr(ty) | Type::SharedPtr(ty) | Type::CxxVector(ty) = ty {
-        if let Type::Ident(inner) = &ty.inner {
-            if Atom::from(&inner.rust).is_none() {
-                return;
+    match ty {
+        Type::RustBox(ty)
+        | Type::RustVec(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::CxxVector(ty) => {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(&inner.rust).is_none() {
+                    return;
+                }
             }
         }
+        _ => {}
     }
 
     cx.error(imp, "unsupported Self type of explicit impl");
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 0dd51e5..a2c13d3 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -11,6 +11,8 @@ pub mod ffi {
 
         fn c_take_unique_ptr(c: UniquePtr<C>);
     }
+
+    impl Vec<Job> {}
 }
 
 #[cxx::bridge(namespace = "tests")]

From 355dfa5e1a3c3020e2cb178e4071a41eb3f325b3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 05 2020 02:40:57 +0000
Subject: [PATCH 1666/2232] Merge pull request #542 from dtolnay/explicitvec


Respect explicit impls on Vec and Box
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 419e46c..6881e4c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1255,14 +1255,22 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                out.next_section();
-                write_rust_box_extern(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_rust_box_extern(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     out.next_section();
                     write_rust_vec_extern(out, inner);
                 }
@@ -1287,8 +1295,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_shared_ptr(out, inner);
                 }
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
+        } else if let Type::CxxVector(vector) = ty {
+            if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
                         || out.types.explicit_impls.contains(ty))
@@ -1304,13 +1312,21 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                write_rust_box_impl(out, &out.types.resolve(&inner));
+        if let Type::RustBox(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    write_rust_box_impl(out, &out.types.resolve(&inner));
+                }
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(inner) = &ty.inner {
-                if Atom::from(&inner.rust).is_none() {
+        } else if let Type::RustVec(vec) = ty {
+            if let Type::Ident(inner) = &vec.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
                     write_rust_vec_impl(out, inner);
                 }
             }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9f16e5e..43f152b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -68,13 +68,17 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         let explicit_impl = types.explicit_impls.get(ty);
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_box(ident, types));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none() {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
                     hidden.extend(expand_rust_vec(ident, types));
                 }
             }
diff --git a/syntax/check.rs b/syntax/check.rs
index e9d977b..3b7b513 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -440,12 +440,19 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         return;
     }
 
-    if let Type::UniquePtr(ty) | Type::SharedPtr(ty) | Type::CxxVector(ty) = ty {
-        if let Type::Ident(inner) = &ty.inner {
-            if Atom::from(&inner.rust).is_none() {
-                return;
+    match ty {
+        Type::RustBox(ty)
+        | Type::RustVec(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::CxxVector(ty) => {
+            if let Type::Ident(inner) = &ty.inner {
+                if Atom::from(&inner.rust).is_none() {
+                    return;
+                }
             }
         }
+        _ => {}
     }
 
     cx.error(imp, "unsupported Self type of explicit impl");
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index 0dd51e5..a2c13d3 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -11,6 +11,8 @@ pub mod ffi {
 
         fn c_take_unique_ptr(c: UniquePtr<C>);
     }
+
+    impl Vec<Job> {}
 }
 
 #[cxx::bridge(namespace = "tests")]

From 4f705dc799382bac3bfcc03940a8d28df82c1880 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 06 2020 20:15:40 +0000
Subject: [PATCH 1667/2232] Fix arrowheads rendered by Safari


---

diff --git a/book/src/overview.svg b/book/src/overview.svg
index 850e034..6590547 100644
--- a/book/src/overview.svg
+++ b/book/src/overview.svg
@@ -34,43 +34,6 @@
                          font-family: monospace;
                          font-size: 14px;
                         }
-
-                        .end_marked_arrow{
-                            marker-end: url(#arrow);
-                         }
-                        .start_marked_arrow{
-                            marker-start: url(#arrow);
-                         }
-
-                        .end_marked_diamond{
-                            marker-end: url(#diamond);
-                         }
-                        .start_marked_diamond{
-                            marker-start: url(#diamond);
-                         }
-
-                        .end_marked_circle{
-                            marker-end: url(#circle);
-                         }
-                        .start_marked_circle{
-                            marker-start: url(#circle);
-                         }
-
-                        .end_marked_open_circle{
-                            marker-end: url(#open_circle);
-                         }
-                        .start_marked_open_circle{
-                            marker-start: url(#open_circle);
-                         }
-
-                        .end_marked_big_open_circle{
-                            marker-end: url(#big_open_circle);
-                         }
-                        .start_marked_big_open_circle{
-                            marker-start: url(#big_open_circle);
-                         }
-
-                         
                         </style>
     <defs>
         <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
@@ -96,17 +59,22 @@
     <text x="426" y="188" >C++ bindings</text>
     <text x="272" y="28" >#[cxx::bridge] mod</text>
     <text x="250" y="44" >description of boundary</text>
-    <line x1="220" y1="120" x2="220" y2="160" class="solid end_marked_arrow"></line>
-    <line x1="476" y1="120" x2="476" y2="160" class="solid end_marked_arrow"></line>
+    <line x1="220" y1="120" x2="220" y2="160" class="solid"></line>
+    <polygon points="216,156 224,156 220,164" class="filled"></polygon>
+    <line x1="476" y1="120" x2="476" y2="160" class="solid"></line>
+    <polygon points="472,156 480,156 476,164" class="filled"></polygon>
     <text x="74" y="140" >Safe</text>
     <text x="34" y="156" >straightforward</text>
     <text x="530" y="156" >Straightforward</text>
     <polygon points="48,180 40,184 48,188" class="filled"></polygon>
-    <line x1="48" y1="184" x2="144" y2="184" class="solid end_marked_arrow"></line>
+    <line x1="48" y1="184" x2="144" y2="184" class="solid"></line>
+    <polygon points="136,180 144,184 136,188" class="filled"></polygon>
     <polygon points="296,180 288,184 296,188" class="filled"></polygon>
-    <line x1="296" y1="184" x2="408" y2="184" class="broken end_marked_arrow"></line>
+    <line x1="296" y1="184" x2="408" y2="184" class="broken"></line>
+    <polygon points="400,180 408,184 400,188" class="filled"></polygon>
     <polygon points="552,180 544,184 552,188" class="filled"></polygon>
-    <line x1="552" y1="184" x2="648" y2="184" class="solid end_marked_arrow"></line>
+    <line x1="552" y1="184" x2="648" y2="184" class="solid"></line>
+    <polygon points="644,180 652,184 644,188" class="filled"></polygon>
     <text x="2" y="188" >Rust</text>
     <text x="2" y="204" >code</text>
     <text x="658" y="204" >code</text>

From 5804bb726605efa4bc997c82ac31c87c80a0f837 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 05:06:27 +0000
Subject: [PATCH 1668/2232] Use ResolvableName as resolutions map key


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 12b269e..da1dbf8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -228,7 +228,8 @@ pub struct Pair {
 
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(transparent)]
 pub struct ResolvableName {
     pub rust: Ident,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index 25ae9f4..b4d8ef1 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -53,6 +53,10 @@ impl ResolvableName {
         Self { rust: ident }
     }
 
+    pub fn from_ref(ident: &Ident) -> &Self {
+        unsafe { &*(ident as *const Ident as *const Self) }
+    }
+
     pub fn make_self(span: Span) -> Self {
         Self {
             rust: Token![Self](span).into(),
diff --git a/syntax/types.rs b/syntax/types.rs
index 1b61cdb..9fe3562 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -20,7 +20,7 @@ pub struct Types<'a> {
     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 Pair>,
+    pub resolutions: Map<&'a ResolvableName, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -63,7 +63,7 @@ impl<'a> Types<'a> {
         }
 
         let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(&pair.rust, pair);
+            resolutions.insert(ResolvableName::from_ref(&pair.rust), pair);
         };
 
         let mut type_names = UnorderedSet::new();
@@ -291,9 +291,7 @@ impl<'a> Types<'a> {
     }
 
     pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
-        self.resolutions
-            .get(&ident.rust)
-            .expect("Unable to resolve type")
+        self.resolutions.get(ident).expect("Unable to resolve type")
     }
 }
 

From 75ea17ce4e708102e6157b32f684d75f76d84022 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 05:08:47 +0000
Subject: [PATCH 1669/2232] Rename ResolvableName -> RustName


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6881e4c..2770a05 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,8 +5,8 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, ResolvableName, Signature, Struct,
-    Trait, Type, Types, Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
+    Type, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
@@ -1202,15 +1202,15 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 #[derive(Copy, Clone)]
 enum UniquePtr<'a> {
-    Ident(&'a ResolvableName),
-    CxxVector(&'a ResolvableName),
+    Ident(&'a RustName),
+    CxxVector(&'a RustName),
 }
 
 trait ToTypename {
     fn to_typename(&self, types: &Types) -> String;
 }
 
-impl ToTypename for ResolvableName {
+impl ToTypename for RustName {
     fn to_typename(&self, types: &Types) -> String {
         types.resolve(self).to_fully_qualified()
     }
@@ -1231,7 +1231,7 @@ trait ToMangled {
     fn to_mangled(&self, types: &Types) -> Symbol;
 }
 
-impl ToMangled for ResolvableName {
+impl ToMangled for RustName {
     fn to_mangled(&self, types: &Types) -> Symbol {
         self.to_symbol(types)
     }
@@ -1355,7 +1355,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "#endif // CXXBRIDGE1_RUST_BOX_{}", instance);
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &ResolvableName) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1414,7 +1414,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1466,7 +1466,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &ResolvableName) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &ResolvableName) {
+fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
     let ty = UniquePtr::Ident(ident);
     let instance = ty.to_mangled(out.types);
 
@@ -1590,7 +1590,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
+fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     let resolved = out.types.resolve(ident);
     let inner = resolved.to_fully_qualified();
     let instance = ident.to_symbol(out.types);
@@ -1666,7 +1666,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &ResolvableName) {
     writeln!(out, "#endif // CXXBRIDGE1_SHARED_PTR_{}", instance);
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
+fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 43f152b..c5063a2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -4,8 +4,8 @@ use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
-    Struct, Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Signature, Struct,
+    Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -949,7 +949,7 @@ fn type_id(name: &Pair) -> TokenStream {
     }
 }
 
-fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
+fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
     let link_uninit = format!("{}uninit", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
@@ -978,7 +978,7 @@ fn expand_rust_box(ident: &ResolvableName, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
+fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$rust_vec${}$", elem.to_symbol(types));
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
@@ -1037,11 +1037,7 @@ fn expand_rust_vec(elem: &ResolvableName, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(
-    ident: &ResolvableName,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
+fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
     let prefix = format!("cxxbridge1$unique_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
@@ -1122,11 +1118,7 @@ fn expand_unique_ptr(
     }
 }
 
-fn expand_shared_ptr(
-    ident: &ResolvableName,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
+fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
     let prefix = format!("cxxbridge1$shared_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
@@ -1193,11 +1185,7 @@ fn expand_shared_ptr(
     }
 }
 
-fn expand_cxx_vector(
-    elem: &ResolvableName,
-    explicit_impl: Option<&Impl>,
-    types: &Types,
-) -> TokenStream {
+fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let _ = explicit_impl;
     let name = elem.rust.to_string();
     let prefix = format!("cxxbridge1$std$vector${}$", elem.to_symbol(types));
diff --git a/syntax/mod.rs b/syntax/mod.rs
index da1dbf8..3b5b4d7 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -150,7 +150,7 @@ pub struct Receiver {
     pub lifetime: Option<Lifetime>,
     pub mutable: bool,
     pub var: Token![self],
-    pub ty: ResolvableName,
+    pub ty: RustName,
     pub shorthand: bool,
     pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
     pub mutability: Option<Token![mut]>,
@@ -163,7 +163,7 @@ pub struct Variant {
 }
 
 pub enum Type {
-    Ident(ResolvableName),
+    Ident(RustName),
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
@@ -230,6 +230,6 @@ pub struct Pair {
 // C++.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
-pub struct ResolvableName {
+pub struct RustName {
     pub rust: Ident,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index b4d8ef1..2cc91f9 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{Namespace, Pair, ResolvableName, Symbol, Types};
+use crate::syntax::{Namespace, Pair, RustName, Symbol, Types};
 use proc_macro2::{Ident, Span};
 use std::iter;
 use syn::Token;
@@ -48,7 +48,7 @@ impl Pair {
     }
 }
 
-impl ResolvableName {
+impl RustName {
     pub fn new(ident: Ident) -> Self {
         Self { rust: ident }
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e4f0512..c571132 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,7 +4,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Namespace, Pair, Receiver, Ref, ResolvableName, Signature, SliceRef, Struct, Ty1, Type,
+    Lang, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1, Type,
     TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
@@ -186,7 +186,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     }
 
     let ident = Ident::new(repr.as_ref(), Span::call_site());
-    let repr_type = Type::Ident(ResolvableName::new(ident));
+    let repr_type = Type::Ident(RustName::new(ident));
 
     Ok(Api::Enum(Enum {
         doc,
@@ -289,7 +289,7 @@ fn parse_foreign_mod(
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
                     if receiver.ty.is_self() {
-                        receiver.ty = ResolvableName::new(single_type.rust.clone());
+                        receiver.ty = RustName::new(single_type.rust.clone());
                     }
                 }
             }
@@ -432,7 +432,7 @@ fn parse_extern_fn(
                         lifetime: lifetime.clone(),
                         mutable: arg.mutability.is_some(),
                         var: arg.self_token,
-                        ty: ResolvableName::make_self(arg.self_token.span),
+                        ty: RustName::make_self(arg.self_token.span),
                         shorthand: true,
                         pin_tokens: None,
                         mutability: arg.mutability,
@@ -810,7 +810,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
         let segment = &path.segments[0];
         let ident = segment.ident.clone();
         match &segment.arguments {
-            PathArguments::None => return Ok(Type::Ident(ResolvableName::new(ident))),
+            PathArguments::None => return Ok(Type::Ident(RustName::new(ident))),
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 07738d8..ae2d1d9 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
-    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, RustName, Signature,
+    SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -182,7 +182,7 @@ impl ToTokens for Signature {
     }
 }
 
-impl ToTokens for ResolvableName {
+impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.rust.to_tokens(tokens);
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index 9fe3562..72216b3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,8 +3,8 @@ use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
-    derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Trait,
-    Type, TypeAlias,
+    derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Trait, Type,
+    TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -20,7 +20,7 @@ pub struct Types<'a> {
     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 ResolvableName, &'a Pair>,
+    pub resolutions: Map<&'a RustName, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -63,7 +63,7 @@ impl<'a> Types<'a> {
         }
 
         let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(ResolvableName::from_ref(&pair.rust), pair);
+            resolutions.insert(RustName::from_ref(&pair.rust), pair);
         };
 
         let mut type_names = UnorderedSet::new();
@@ -290,7 +290,7 @@ impl<'a> Types<'a> {
         }
     }
 
-    pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
+    pub fn resolve(&self, ident: &RustName) -> &Pair {
         self.resolutions.get(ident).expect("Unable to resolve type")
     }
 }

From 7082067186909fa4bbece010dafbb25a0b9f7e44 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 19:16:15 +0000
Subject: [PATCH 1670/2232] Include <memory> for CxxVector's unique_ptr shims


Fixes #548.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 419e46c..fb1a7f3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1671,6 +1671,7 @@ fn write_cxx_vector(out: &mut OutFile, element: &ResolvableName) {
     writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
+    out.include.memory = true;
     write_unique_ptr_common(out, UniquePtr::CxxVector(element));
 
     writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);

From c7ec958bc00ea6f97d278c259c739fe5421baf7b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 19:17:29 +0000
Subject: [PATCH 1671/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index afb1520..0a9f4bb 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.53/src/**"]),
+    srcs = glob(["vendor/syn-1.0.54/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index b9d71a3..1861ad9 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.53/src/**"]),
+    srcs = glob(["vendor/syn-1.0.54/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f6f6900..b4475ef 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -175,9 +175,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.80"
+version = "0.2.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
 
 [[package]]
 name = "link-cplusplus"
@@ -232,18 +232,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
+checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
+checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.53"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
+checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
 dependencies = [
  "proc-macro2",
  "quote",

From c9e14fb4146c3b099d0f6f49e261fa51ba8169fb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 19:18:51 +0000
Subject: [PATCH 1672/2232] Release 1.0.13


---

diff --git a/Cargo.toml b/Cargo.toml
index 1d2723f..d886fde 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.12" # remember to update html_root_url
+version = "1.0.13" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.12", path = "macro" }
+cxxbridge-macro = { version = "=1.0.13", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.12", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.13", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.12", path = "gen/build" }
+cxx-build = { version = "=1.0.13", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 73502d6..a5f33a8 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 12c888a..59695a2 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 92badcc..00eda7b 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index d3ce393..d9b44dc 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.12"
+version = "0.7.13"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 15cdf24..d533b4f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 75716a9..1f24ca2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.12")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.13")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b4475ef..14d67e8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.12"
+version = "0.7.13"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.12"
+version = "1.0.13"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cxx",
  "proc-macro2",

From 8801e60242b885677aeae900ad2340a99e7d4239 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 07 2020 19:19:53 +0000
Subject: [PATCH 1673/2232] Merge 1.0.13 into master


---

diff --git a/Cargo.toml b/Cargo.toml
index 1d2723f..d886fde 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.12" # remember to update html_root_url
+version = "1.0.13" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.12", path = "macro" }
+cxxbridge-macro = { version = "=1.0.13", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.12", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.13", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.12", path = "gen/build" }
+cxx-build = { version = "=1.0.13", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 73502d6..a5f33a8 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 12c888a..59695a2 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 92badcc..00eda7b 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index d3ce393..d9b44dc 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.12"
+version = "0.7.13"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2770a05..28a3eec 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1687,6 +1687,7 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     writeln!(out, "  return &s[pos];");
     writeln!(out, "}}");
 
+    out.include.memory = true;
     write_unique_ptr_common(out, UniquePtr::CxxVector(element));
 
     writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 15cdf24..d533b4f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.12"
+version = "1.0.13"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 75716a9..1f24ca2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.12")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.13")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/BUCK b/third-party/BUCK
index afb1520..0a9f4bb 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.53/src/**"]),
+    srcs = glob(["vendor/syn-1.0.54/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index b9d71a3..1861ad9 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.53/src/**"]),
+    srcs = glob(["vendor/syn-1.0.54/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f6f6900..14d67e8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.12"
+version = "0.7.13"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.12"
+version = "1.0.13"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.12"
+version = "1.0.13"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -175,9 +175,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.80"
+version = "0.2.81"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
+checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
 
 [[package]]
 name = "link-cplusplus"
@@ -232,18 +232,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
+checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.117"
+version = "1.0.118"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
+checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.53"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
+checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
 dependencies = [
  "proc-macro2",
  "quote",

From 73f2daff89c25f703f129a5364c849a75d077155 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Dec 08 2020 00:25:59 +0000
Subject: [PATCH 1674/2232] Allow &mut calls on Trivial extern types only.


Previously we allowed extern types to be used as un-pinned
reference parameters only if there happened to be some other
use of the type in some way which required it to be Trivial.

With this change,
* Opaque extern types must always be pinned when used as mutable
  reference parameters;
* Trivial extern types need never be pinned when used as mutable
  reference parameters.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 3b7b513..80426f9 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -189,7 +189,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
             cx.error(
                 ty,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}> or declare the type Trivial in a cxx::ExternType impl",
                     requires_pin,
                 ),
             );
@@ -332,6 +332,10 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
             TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
             TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
             TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
+            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => format!(
+                "a non-pinned mutable reference argument of {}",
+                efn.name.rust
+            ),
         };
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
@@ -385,7 +389,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(
                 span,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use `self: Pin<&mut {}>`",
+                    "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>` or declare the type Trivial in a cxx::ExternType impl",
                     receiver.ty.rust,
                 ),
             );
diff --git a/syntax/types.rs b/syntax/types.rs
index 72216b3..ddd3c42 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -170,14 +170,13 @@ impl<'a> Types<'a> {
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
         let mut required_trivial = Map::new();
-        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
-            if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust)
-                    && !structs.contains_key(&ident.rust)
-                    && !enums.contains_key(&ident.rust)
-                {
-                    required_trivial.entry(&ident.rust).or_insert(reason);
-                }
+
+        let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
+            if cxx.contains(&ident.rust)
+                && !structs.contains_key(&ident.rust)
+                && !enums.contains_key(&ident.rust)
+            {
+                required_trivial.entry(&ident.rust).or_insert(reason);
             }
         };
         for api in apis {
@@ -185,17 +184,23 @@ impl<'a> Types<'a> {
                 Api::Struct(strct) => {
                     let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(&field.ty, reason);
+                        if let Type::Ident(ident) = &field.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(&arg.ty, reason);
+                        if let Type::Ident(ident) = &arg.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                     if let Some(ret) = &efn.ret {
                         let reason = TrivialReason::FunctionReturn(efn);
-                        insist_alias_types_are_trivial(&ret, reason);
+                        if let Type::Ident(ident) = &ret {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 _ => {}
@@ -205,11 +210,37 @@ impl<'a> Types<'a> {
             match ty {
                 Type::RustBox(ty) => {
                     let reason = TrivialReason::BoxTarget;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
                 }
                 Type::RustVec(ty) => {
                     let reason = TrivialReason::VecElement;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
+                }
+                _ => {}
+            }
+        }
+        for api in apis {
+            match api {
+                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    let reason = TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn);
+                    if let Some(receiver) = &efn.receiver {
+                        if receiver.mutable && !receiver.pinned {
+                            insist_extern_types_are_trivial(&receiver.ty, reason);
+                        }
+                    }
+                    for arg in &efn.args {
+                        if let Type::Ref(reff) = &arg.ty {
+                            if reff.mutable && !reff.pinned {
+                                if let Type::Ident(ident) = &reff.inner {
+                                    insist_extern_types_are_trivial(&ident, reason);
+                                }
+                            }
+                        }
+                    }
                 }
                 _ => {}
             }
@@ -310,6 +341,7 @@ pub enum TrivialReason<'a> {
     FunctionReturn(&'a ExternFn),
     BoxTarget,
     VecElement,
+    UnpinnedMutableReferenceFunctionArgument(&'a ExternFn),
 }
 
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index a2c13d3..cd9fc2b 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -32,12 +32,16 @@ pub mod ffi2 {
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial_ref_method(self: &D);
+        fn c_take_trivial_mut_ref_method(self: &mut D);
         fn c_take_trivial(d: D);
         fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
         fn c_take_trivial_ns_ref(g: &G);
         fn c_take_trivial_ns(g: G);
         fn c_take_opaque_ptr(e: UniquePtr<E>);
         fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ref_method(self: &E);
+        fn c_take_opaque_mut_ref_method(self: Pin<&mut E>);
         fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
         fn c_take_opaque_ns_ref(e: &F);
         fn c_return_trivial_ptr() -> UniquePtr<D>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2be1e06..1c8a122 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -529,6 +529,18 @@ void c_take_trivial_ref(const D &d) {
   }
 }
 
+void D::c_take_trivial_ref_method() const {
+  if (d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void D::c_take_trivial_mut_ref_method() {
+  if (d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_trivial(D d) {
   if (d.d == 30) {
     cxx_test_suite_set_correct();
@@ -571,6 +583,18 @@ void c_take_opaque_ref(const E &e) {
   }
 }
 
+void E::c_take_opaque_ref_method() const {
+  if (e == 40 && e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void E::c_take_opaque_mut_ref_method() {
+  if (e == 40 && e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ns_ref(const ::F::F &f) {
   if (f.f == 40 && f.f_str == "hello") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 024ecea..f8d983b 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -59,11 +59,15 @@ private:
 
 struct D {
   uint64_t d;
+  void c_take_trivial_ref_method() const;
+  void c_take_trivial_mut_ref_method();
 };
 
 struct E {
   uint64_t e;
   std::string e_str;
+  void c_take_opaque_ref_method() const;
+  void c_take_opaque_mut_ref_method();
 };
 
 enum COwnedEnum {
diff --git a/tests/test.rs b/tests/test.rs
index 00a7228..b8edf37 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -263,10 +263,14 @@ fn test_rust_name_attribute() {
 
 #[test]
 fn test_extern_trivial() {
-    let d = ffi2::c_return_trivial();
+    let mut d = ffi2::c_return_trivial();
     check!(ffi2::c_take_trivial_ref(&d));
+    check!(d.c_take_trivial_ref_method());
+    check!(d.c_take_trivial_mut_ref_method());
     check!(ffi2::c_take_trivial(d));
-    let d = ffi2::c_return_trivial_ptr();
+    let mut d = ffi2::c_return_trivial_ptr();
+    check!(d.c_take_trivial_ref_method());
+    check!(d.c_take_trivial_mut_ref_method());
     check!(ffi2::c_take_trivial_ptr(d));
     cxx::UniquePtr::new(ffi2::D { d: 42 });
     let d = ffi2::ns_c_return_trivial();
@@ -282,8 +286,10 @@ fn test_extern_trivial() {
 
 #[test]
 fn test_extern_opaque() {
-    let e = ffi2::c_return_opaque_ptr();
+    let mut e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
+    check!(e.c_take_opaque_ref_method());
+    check!(e.pin_mut().c_take_opaque_mut_ref_method());
     check!(ffi2::c_take_opaque_ptr(e));
 
     let f = ffi2::c_return_ns_opaque_ptr();
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 32d5cfc..417eead 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -16,6 +16,12 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<..
 9 |         fn v(v: &mut CxxVector<u8>);
   |                 ^^^^^^^^^^^^^^^^^^
 
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of f
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
 error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
  --> $DIR/pin_mut_opaque.rs:6:14
   |

From 7b443f71b0e2fc949dc795ddf990b86d87b26356 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Dec 08 2020 00:25:59 +0000
Subject: [PATCH 1675/2232] Add reasons for Trivial requirements in C++ errors


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2770a05..de992db 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,3 @@
-use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
@@ -8,6 +7,7 @@ use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
     Type, Types, Var,
 };
+use crate::{gen::block::Block, syntax::types::TrivialReason};
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
 
@@ -117,8 +117,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if out.types.required_trivial.contains_key(&ety.name.rust) {
-                check_trivial_extern_type(out, &ety.name)
+            if let Some(reason) = out.types.required_trivial.get(&ety.name.rust) {
+                check_trivial_extern_type(out, &ety.name, reason)
             }
         }
     }
@@ -366,7 +366,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reason: &TrivialReason) {
     // NOTE: The following static assertion is 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:
@@ -406,8 +406,9 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
     writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
     writeln!(
         out,
-        "    \"type {} marked as Trivial in Rust is not trivially move constructible and trivially destructible in C++\");",
+        "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
         id,
+        reason
     );
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index 80426f9..3f5805e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
-use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
     SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
@@ -326,17 +325,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     }
 
     if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
-        let what = match reason {
-            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
-            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
-            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
-            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
-            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
-            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => format!(
-                "a non-pinned mutable reference argument of {}",
-                efn.name.rust
-            ),
-        };
+        let what = reason.describe_in_context(&ety);
         let msg = format!(
             "needs a cxx::ExternType impl in order to be used as {}",
             what,
diff --git a/syntax/types.rs b/syntax/types.rs
index ddd3c42..4868741 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -8,7 +8,7 @@ use crate::syntax::{
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::BTreeMap as Map;
+use std::{collections::BTreeMap as Map, fmt::Display};
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,
@@ -344,6 +344,35 @@ pub enum TrivialReason<'a> {
     UnpinnedMutableReferenceFunctionArgument(&'a ExternFn),
 }
 
+impl<'a> TrivialReason<'a> {
+    pub fn describe_in_context(&self, ety: &ExternType) -> String {
+        match self {
+            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
+            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
+            _ => self.to_string(),
+        }
+    }
+}
+
+impl<'a> Display for TrivialReason<'a> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
+            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
+            TrivialReason::FunctionReturn(efn) => {
+                write!(f, "a return value of `{}`", efn.name.rust)
+            }
+            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
+            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
+            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => write!(
+                f,
+                "a non-pinned mutable reference argument of {}",
+                efn.name.rust
+            ),
+        }
+    }
+}
+
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
     cx.error(sp, msg);

From f831a5abcf84bf5b21b2154ea5aaf28b668885dd Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Dec 08 2020 00:49:19 +0000
Subject: [PATCH 1676/2232] Display all known reasons why type must be Trivial.


This generates multiple Rust-side and C++-side error messages
when a given opaque C++ type is being used in contexts which
allow only a Trivial type. Previously, we showed just the first
message and discarded all others.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index de992db..6d83226 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -117,8 +117,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if let Some(reason) = out.types.required_trivial.get(&ety.name.rust) {
-                check_trivial_extern_type(out, &ety.name, reason)
+            if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
+                check_trivial_extern_type(out, &ety.name, reasons)
             }
         }
     }
@@ -366,7 +366,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reason: &TrivialReason) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialReason]) {
     // NOTE: The following static assertion is 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:
@@ -402,14 +402,16 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reason: &TrivialReaso
 
     let id = id.to_fully_qualified();
     out.builtin.relocatable = true;
-    writeln!(out, "static_assert(");
-    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
-    writeln!(
-        out,
-        "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
-        id,
-        reason
-    );
+    for reason in reasons {
+        writeln!(out, "static_assert(");
+        writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
+        writeln!(
+            out,
+            "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
+            id,
+            reason
+        );
+    }
 }
 
 fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
diff --git a/syntax/check.rs b/syntax/check.rs
index 3f5805e..6acaa0f 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -324,13 +324,15 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(span, "extern type bounds are not implemented yet");
     }
 
-    if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
-        let what = reason.describe_in_context(&ety);
-        let msg = format!(
-            "needs a cxx::ExternType impl in order to be used as {}",
-            what,
-        );
-        cx.error(ety, msg);
+    if let Some(reasons) = cx.types.required_trivial.get(&ety.name.rust) {
+        for reason in reasons {
+            let what = reason.describe_in_context(&ety);
+            let msg = format!(
+                "needs a cxx::ExternType impl in order to be used as {}",
+                what,
+            );
+            cx.error(ety, msg);
+        }
     }
 }
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 4868741..eb3393a 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -18,7 +18,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
+    pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a RustName, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
@@ -169,14 +169,17 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial = Map::new();
+        let mut required_trivial: Map<_, Vec<_>> = Map::new();
 
         let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
             if cxx.contains(&ident.rust)
                 && !structs.contains_key(&ident.rust)
                 && !enums.contains_key(&ident.rust)
             {
-                required_trivial.entry(&ident.rust).or_insert(reason);
+                required_trivial
+                    .entry(&ident.rust)
+                    .or_default()
+                    .push(reason);
             }
         };
         for api in apis {
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 0a56dd4..4bcce1b 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -22,6 +22,18 @@ error: needs a cxx::ExternType impl in order to be used as a field of `S`
 10 |         type C;
    |         ^^^^^^
 
+error: needs a cxx::ExternType impl in order to be used as an argument of `f`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a return value of `f`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
 error: passing opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 417eead..91a7caa 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -1,16 +1,16 @@
-error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:5:19
   |
 5 |         fn f(arg: &mut Opaque);
   |                   ^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:8:17
   |
 8 |         fn s(s: &mut CxxString);
   |                 ^^^^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:9:17
   |
 9 |         fn v(v: &mut CxxVector<u8>);
@@ -22,13 +22,25 @@ error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable 
 4 |         type Opaque;
   |         ^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of g
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of h
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:6:14
   |
 6 |         fn g(&mut self);
   |              ^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:7:20
   |
 7 |         fn h(self: &mut Opaque);

From 1acc8a0ca7f1e4b2c2ef9eaf31283c9897278515 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 06:35:29 +0000
Subject: [PATCH 1677/2232] Limit instantiation of Vec and Box shims to local element type


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c5063a2..9e4bd6b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -961,6 +961,8 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let span = ident.span();
     quote_spanned! {span=>
         #[doc(hidden)]
+        unsafe impl ::cxx::private::ImplBox for #ident {}
+        #[doc(hidden)]
         #[export_name = #link_uninit]
         unsafe extern "C" fn #local_uninit(
             this: *mut ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
@@ -1000,6 +1002,8 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let span = elem.span();
     quote_spanned! {span=>
         #[doc(hidden)]
+        unsafe impl ::cxx::private::ImplVec for #elem {}
+        #[doc(hidden)]
         #[export_name = #link_new]
         unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
             ::std::ptr::write(this, ::cxx::private::RustVec::new());
diff --git a/src/lib.rs b/src/lib.rs
index 1f24ca2..1e3b212 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -448,7 +448,7 @@ pub mod private {
     pub use crate::rust_slice::RustSlice;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
-    pub use crate::rust_type::RustType;
+    pub use crate::rust_type::{ImplBox, ImplVec, RustType};
     pub use crate::rust_vec::RustVec;
     pub use crate::shared_ptr::SharedPtrTarget;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/rust_type.rs b/src/rust_type.rs
index 2f4f089..7bcf440 100644
--- a/src/rust_type.rs
+++ b/src/rust_type.rs
@@ -1 +1,3 @@
 pub unsafe trait RustType {}
+pub unsafe trait ImplBox {}
+pub unsafe trait ImplVec {}

From 0dee4b4278a4b9f9735cffb6b4cb6ec3fdf9c225 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 06:50:55 +0000
Subject: [PATCH 1678/2232] Merge pull request #555 from dtolnay/impl


Limit instantiation of Vec and Box shims to local element type
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c5063a2..9e4bd6b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -961,6 +961,8 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let span = ident.span();
     quote_spanned! {span=>
         #[doc(hidden)]
+        unsafe impl ::cxx::private::ImplBox for #ident {}
+        #[doc(hidden)]
         #[export_name = #link_uninit]
         unsafe extern "C" fn #local_uninit(
             this: *mut ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
@@ -1000,6 +1002,8 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let span = elem.span();
     quote_spanned! {span=>
         #[doc(hidden)]
+        unsafe impl ::cxx::private::ImplVec for #elem {}
+        #[doc(hidden)]
         #[export_name = #link_new]
         unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
             ::std::ptr::write(this, ::cxx::private::RustVec::new());
diff --git a/src/lib.rs b/src/lib.rs
index 1f24ca2..1e3b212 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -448,7 +448,7 @@ pub mod private {
     pub use crate::rust_slice::RustSlice;
     pub use crate::rust_str::RustStr;
     pub use crate::rust_string::RustString;
-    pub use crate::rust_type::RustType;
+    pub use crate::rust_type::{ImplBox, ImplVec, RustType};
     pub use crate::rust_vec::RustVec;
     pub use crate::shared_ptr::SharedPtrTarget;
     pub use crate::unique_ptr::UniquePtrTarget;
diff --git a/src/rust_type.rs b/src/rust_type.rs
index 2f4f089..7bcf440 100644
--- a/src/rust_type.rs
+++ b/src/rust_type.rs
@@ -1 +1,3 @@
 pub unsafe trait RustType {}
+pub unsafe trait ImplBox {}
+pub unsafe trait ImplVec {}

From 08a03dbb9a6b9829e5d87d6dbf6d3d94d4248ae3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:04:36 +0000
Subject: [PATCH 1679/2232] Include <functional> when deriving Hash impl shim


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 9db95be..3a0d66b 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -27,6 +27,7 @@ pub struct Includes<'a> {
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
+    pub functional: bool,
     pub initializer_list: bool,
     pub iterator: bool,
     pub memory: bool,
@@ -77,6 +78,7 @@ pub(super) fn write(out: &mut OutFile) {
         cstdint,
         cstring,
         exception,
+        functional,
         initializer_list,
         iterator,
         memory,
@@ -107,6 +109,9 @@ pub(super) fn write(out: &mut OutFile) {
     if exception {
         writeln!(out, "#include <exception>");
     }
+    if functional {
+        writeln!(out, "#include <functional>");
+    }
     if initializer_list {
         writeln!(out, "#include <initializer_list>");
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 28a3eec..e29d5f6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -158,6 +158,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
         if let Api::Struct(strct) = api {
             if derive::contains(&strct.derives, Trait::Hash) {
                 out.next_section();
+                out.include.functional = true;
                 let qualified = strct.name.to_fully_qualified();
                 writeln!(out, "template <> struct hash<{}> {{", qualified);
                 writeln!(

From e5ea14e0492721b2c7346d679885ce138512f8da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:11:19 +0000
Subject: [PATCH 1680/2232] Merge pull request #556 from dtolnay/functional


Include <functional> when deriving Hash impl shim
---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 9db95be..3a0d66b 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -27,6 +27,7 @@ pub struct Includes<'a> {
     pub cstdint: bool,
     pub cstring: bool,
     pub exception: bool,
+    pub functional: bool,
     pub initializer_list: bool,
     pub iterator: bool,
     pub memory: bool,
@@ -77,6 +78,7 @@ pub(super) fn write(out: &mut OutFile) {
         cstdint,
         cstring,
         exception,
+        functional,
         initializer_list,
         iterator,
         memory,
@@ -107,6 +109,9 @@ pub(super) fn write(out: &mut OutFile) {
     if exception {
         writeln!(out, "#include <exception>");
     }
+    if functional {
+        writeln!(out, "#include <functional>");
+    }
     if initializer_list {
         writeln!(out, "#include <initializer_list>");
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 28a3eec..e29d5f6 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -158,6 +158,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
         if let Api::Struct(strct) = api {
             if derive::contains(&strct.derives, Trait::Hash) {
                 out.next_section();
+                out.include.functional = true;
                 let qualified = strct.name.to_fully_qualified();
                 writeln!(out, "template <> struct hash<{}> {{", qualified);
                 writeln!(

From 12320e13f82f0799324f8ccf826ee17a6a73abf9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:11:30 +0000
Subject: [PATCH 1681/2232] Include <cstddef> everywhere that size_t makes an appearance


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 837761d..62c3527 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -161,6 +161,7 @@ pub(super) fn write(out: &mut OutFile) {
     out.begin_block(Block::AnonymousNamespace);
 
     if builtin.ptr_len {
+        include.cstddef = true;
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  void *ptr;");
@@ -241,6 +242,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.is_complete {
+        include.cstddef = true;
         include.type_traits = true;
         out.next_section();
         writeln!(out, "template <typename T, typename = size_t>");
@@ -296,6 +298,7 @@ pub(super) fn write(out: &mut OutFile) {
     out.end_block(Block::Namespace("rust"));
 
     if builtin.exception {
+        include.cstddef = true;
         out.begin_block(Block::ExternC);
         writeln!(
             out,
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e29d5f6..03ebeb5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -158,6 +158,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
         if let Api::Struct(strct) = api {
             if derive::contains(&strct.derives, Trait::Hash) {
                 out.next_section();
+                out.include.cstddef = true;
                 out.include.functional = true;
                 let qualified = strct.name.to_fully_qualified();
                 writeln!(out, "template <> struct hash<{}> {{", qualified);
@@ -467,6 +468,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     }
 
     if derive::contains(&strct.derives, Trait::Hash) {
+        out.include.cstddef = true;
         let link_name = mangle::operator(&strct.name, "hash");
         writeln!(
             out,
@@ -1360,6 +1362,8 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(
@@ -1419,6 +1423,8 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
@@ -1671,6 +1677,8 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(

From 056f3303fb3e1257ea6d8141bb7aaf6b3ebb8c67 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:16:33 +0000
Subject: [PATCH 1682/2232] Merge pull request #557 from dtolnay/sizet


Include <cstddef> everywhere that size_t makes an appearance
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 837761d..62c3527 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -161,6 +161,7 @@ pub(super) fn write(out: &mut OutFile) {
     out.begin_block(Block::AnonymousNamespace);
 
     if builtin.ptr_len {
+        include.cstddef = true;
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  void *ptr;");
@@ -241,6 +242,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.is_complete {
+        include.cstddef = true;
         include.type_traits = true;
         out.next_section();
         writeln!(out, "template <typename T, typename = size_t>");
@@ -296,6 +298,7 @@ pub(super) fn write(out: &mut OutFile) {
     out.end_block(Block::Namespace("rust"));
 
     if builtin.exception {
+        include.cstddef = true;
         out.begin_block(Block::ExternC);
         writeln!(
             out,
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e29d5f6..03ebeb5 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -158,6 +158,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
         if let Api::Struct(strct) = api {
             if derive::contains(&strct.derives, Trait::Hash) {
                 out.next_section();
+                out.include.cstddef = true;
                 out.include.functional = true;
                 let qualified = strct.name.to_fully_qualified();
                 writeln!(out, "template <> struct hash<{}> {{", qualified);
@@ -467,6 +468,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     }
 
     if derive::contains(&strct.derives, Trait::Hash) {
+        out.include.cstddef = true;
         let link_name = mangle::operator(&strct.name, "hash");
         writeln!(
             out,
@@ -1360,6 +1362,8 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(
@@ -1419,6 +1423,8 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "template <>");
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
@@ -1671,6 +1677,8 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
+    out.include.cstddef = true;
+
     writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(

From 718ca0f847aa39c2177d0fe5ffddf189738dd082 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:16:57 +0000
Subject: [PATCH 1683/2232] Respect class-specific member operator new in MaybeUninit allocation


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 62c3527..be70a71 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -134,6 +134,34 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
+    out.begin_block(Block::Namespace("detail"));
+
+    if builtin.maybe_uninit {
+        include.cstddef = true;
+        include.new = true;
+        out.next_section();
+        writeln!(out, "template <typename T, typename = void *>");
+        writeln!(out, "struct operator_new {{");
+        writeln!(
+            out,
+            "  void *operator()(size_t sz) {{ return ::operator new(sz); }}",
+        );
+        writeln!(out, "}};");
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(
+            out,
+            "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
+        );
+        writeln!(
+            out,
+            "  void *operator()(size_t sz) {{ return T::operator new(sz); }}",
+        );
+        writeln!(out, "}};");
+    }
+
+    out.end_block(Block::Namespace("detail"));
+
     if builtin.manually_drop {
         out.next_section();
         include.utility = true;
@@ -149,10 +177,15 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.maybe_uninit {
+        include.cstddef = true;
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "union MaybeUninit {{");
         writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  void *operator new(size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
+        );
         writeln!(out, "  MaybeUninit() {{}}");
         writeln!(out, "  ~MaybeUninit() {{}}");
         writeln!(out, "}};");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 03ebeb5..851b953 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1540,7 +1540,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
+    writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
         out.builtin.maybe_uninit = true;
@@ -1554,7 +1554,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
             "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
             inner, inner, inner,
         );
-        writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
+        writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
         writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
@@ -1563,7 +1563,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
+    writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
@@ -1630,7 +1630,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
         "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>();", inner);
+    writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
         out.builtin.maybe_uninit = true;
@@ -1644,7 +1644,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
             "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
             inner, inner, inner,
         );
-        writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
+        writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
         writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
@@ -1653,7 +1653,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
         "void cxxbridge1$shared_ptr${}$clone(const ::std::shared_ptr<{}>& self, ::std::shared_ptr<{}> *ptr) noexcept {{",
         instance, inner, inner,
     );
-    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(self);", inner);
+    writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(self);", inner);
     writeln!(out, "}}");
     writeln!(
         out,

From 8779ecc0f3ade0aac6917d0568262b859e9a2ede Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:27:25 +0000
Subject: [PATCH 1684/2232] Merge pull request #558 from dtolnay/operator-new


Respect class-specific member operator new in MaybeUninit allocation
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 62c3527..be70a71 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -134,6 +134,34 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
+    out.begin_block(Block::Namespace("detail"));
+
+    if builtin.maybe_uninit {
+        include.cstddef = true;
+        include.new = true;
+        out.next_section();
+        writeln!(out, "template <typename T, typename = void *>");
+        writeln!(out, "struct operator_new {{");
+        writeln!(
+            out,
+            "  void *operator()(size_t sz) {{ return ::operator new(sz); }}",
+        );
+        writeln!(out, "}};");
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(
+            out,
+            "struct operator_new<T, decltype(T::operator new(sizeof(T)))> {{",
+        );
+        writeln!(
+            out,
+            "  void *operator()(size_t sz) {{ return T::operator new(sz); }}",
+        );
+        writeln!(out, "}};");
+    }
+
+    out.end_block(Block::Namespace("detail"));
+
     if builtin.manually_drop {
         out.next_section();
         include.utility = true;
@@ -149,10 +177,15 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.maybe_uninit {
+        include.cstddef = true;
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "union MaybeUninit {{");
         writeln!(out, "  T value;");
+        writeln!(
+            out,
+            "  void *operator new(size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
+        );
         writeln!(out, "  MaybeUninit() {{}}");
         writeln!(out, "  ~MaybeUninit() {{}}");
         writeln!(out, "}};");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 03ebeb5..851b953 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1540,7 +1540,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$null(::std::unique_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>();", inner);
+    writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
         out.builtin.maybe_uninit = true;
@@ -1554,7 +1554,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
             "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
             inner, inner, inner,
         );
-        writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
+        writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(uninit);", inner);
         writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
@@ -1563,7 +1563,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         "void cxxbridge1$unique_ptr${}$raw(::std::unique_ptr<{}> *ptr, {} *raw) noexcept {{",
         instance, inner, inner,
     );
-    writeln!(out, "  new (ptr) ::std::unique_ptr<{}>(raw);", inner);
+    writeln!(out, "  ::new (ptr) ::std::unique_ptr<{}>(raw);", inner);
     writeln!(out, "}}");
     writeln!(
         out,
@@ -1630,7 +1630,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
         "void cxxbridge1$shared_ptr${}$null(::std::shared_ptr<{}> *ptr) noexcept {{",
         instance, inner,
     );
-    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>();", inner);
+    writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>();", inner);
     writeln!(out, "}}");
     if can_construct_from_value {
         out.builtin.maybe_uninit = true;
@@ -1644,7 +1644,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
             "  {} *uninit = reinterpret_cast<{} *>(new ::rust::MaybeUninit<{}>);",
             inner, inner, inner,
         );
-        writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
+        writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(uninit);", inner);
         writeln!(out, "  return uninit;");
         writeln!(out, "}}");
     }
@@ -1653,7 +1653,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
         "void cxxbridge1$shared_ptr${}$clone(const ::std::shared_ptr<{}>& self, ::std::shared_ptr<{}> *ptr) noexcept {{",
         instance, inner, inner,
     );
-    writeln!(out, "  new (ptr) ::std::shared_ptr<{}>(self);", inner);
+    writeln!(out, "  ::new (ptr) ::std::shared_ptr<{}>(self);", inner);
     writeln!(out, "}}");
     writeln!(
         out,

From 0beba91b4979ffc37f5c5ce467788c10c866bda9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 07:54:08 +0000
Subject: [PATCH 1685/2232] Improve POD detection for structs with POD fields


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3b5b4d7..31c88c9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,6 +15,7 @@ pub mod mangle;
 mod names;
 pub mod namespace;
 mod parse;
+mod pod;
 pub mod qualified;
 pub mod report;
 pub mod set;
diff --git a/syntax/pod.rs b/syntax/pod.rs
new file mode 100644
index 0000000..d808a99
--- /dev/null
+++ b/syntax/pod.rs
@@ -0,0 +1,35 @@
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{derive, Trait, Type, Types};
+
+impl<'a> Types<'a> {
+    pub fn is_guaranteed_pod(&self, ty: &Type) -> bool {
+        match ty {
+            Type::Ident(ident) => {
+                let ident = &ident.rust;
+                if let Some(atom) = Atom::from(ident) {
+                    match atom {
+                        Bool | Char | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64
+                        | Isize | F32 | F64 => true,
+                        CxxString | RustString => false,
+                    }
+                } else if let Some(strct) = self.structs.get(ident) {
+                    derive::contains(&strct.derives, Trait::Copy)
+                        || strct
+                            .fields
+                            .iter()
+                            .all(|field| self.is_guaranteed_pod(&field.ty))
+                } else {
+                    self.enums.contains_key(ident)
+                }
+            }
+            Type::RustBox(_)
+            | Type::RustVec(_)
+            | Type::UniquePtr(_)
+            | Type::SharedPtr(_)
+            | Type::CxxVector(_)
+            | Type::Void(_) => false,
+            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+            Type::Array(array) => self.is_guaranteed_pod(&array.inner),
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 72216b3..9652eb3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,10 +1,8 @@
-use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
-    derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Trait, Type,
-    TypeAlias,
+    toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -261,22 +259,12 @@ impl<'a> Types<'a> {
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
         match ty {
-            Type::Ident(ident) => {
-                if let Some(strct) = self.structs.get(&ident.rust) {
-                    !self.is_pod(strct)
-                } else {
-                    Atom::from(&ident.rust) == Some(RustString)
-                }
-            }
-            Type::SharedPtr(_) | Type::RustVec(_) | Type::Array(_) => true,
-            _ => false,
+            Type::RustBox(_) | Type::UniquePtr(_) => false,
+            Type::Array(_) => true,
+            _ => !self.is_guaranteed_pod(ty),
         }
     }
 
-    pub fn is_pod(&self, strct: &Struct) -> bool {
-        derive::contains(&strct.derives, Trait::Copy)
-    }
-
     // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
     // they may be otherwise unproblematic to mention in an extern signature.
     // For example in a signature like `extern "C" fn(*const String)`, rustc

From b43417e2a65a32fe9c71cf6359c9eb327edc696d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 19:36:52 +0000
Subject: [PATCH 1686/2232] Merge pull request #559 from dtolnay/pod


Improve POD detection for structs with POD fields
---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3b5b4d7..31c88c9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,6 +15,7 @@ pub mod mangle;
 mod names;
 pub mod namespace;
 mod parse;
+mod pod;
 pub mod qualified;
 pub mod report;
 pub mod set;
diff --git a/syntax/pod.rs b/syntax/pod.rs
new file mode 100644
index 0000000..d808a99
--- /dev/null
+++ b/syntax/pod.rs
@@ -0,0 +1,35 @@
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{derive, Trait, Type, Types};
+
+impl<'a> Types<'a> {
+    pub fn is_guaranteed_pod(&self, ty: &Type) -> bool {
+        match ty {
+            Type::Ident(ident) => {
+                let ident = &ident.rust;
+                if let Some(atom) = Atom::from(ident) {
+                    match atom {
+                        Bool | Char | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64
+                        | Isize | F32 | F64 => true,
+                        CxxString | RustString => false,
+                    }
+                } else if let Some(strct) = self.structs.get(ident) {
+                    derive::contains(&strct.derives, Trait::Copy)
+                        || strct
+                            .fields
+                            .iter()
+                            .all(|field| self.is_guaranteed_pod(&field.ty))
+                } else {
+                    self.enums.contains_key(ident)
+                }
+            }
+            Type::RustBox(_)
+            | Type::RustVec(_)
+            | Type::UniquePtr(_)
+            | Type::SharedPtr(_)
+            | Type::CxxVector(_)
+            | Type::Void(_) => false,
+            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+            Type::Array(array) => self.is_guaranteed_pod(&array.inner),
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 72216b3..9652eb3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,10 +1,8 @@
-use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{
-    derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Trait, Type,
-    TypeAlias,
+    toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -261,22 +259,12 @@ impl<'a> Types<'a> {
 
     pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
         match ty {
-            Type::Ident(ident) => {
-                if let Some(strct) = self.structs.get(&ident.rust) {
-                    !self.is_pod(strct)
-                } else {
-                    Atom::from(&ident.rust) == Some(RustString)
-                }
-            }
-            Type::SharedPtr(_) | Type::RustVec(_) | Type::Array(_) => true,
-            _ => false,
+            Type::RustBox(_) | Type::UniquePtr(_) => false,
+            Type::Array(_) => true,
+            _ => !self.is_guaranteed_pod(ty),
         }
     }
 
-    pub fn is_pod(&self, strct: &Struct) -> bool {
-        derive::contains(&strct.derives, Trait::Copy)
-    }
-
     // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
     // they may be otherwise unproblematic to mention in an extern signature.
     // For example in a signature like `extern "C" fn(*const String)`, rustc

From 5554ebd136e82a55688eb86fbe1e423aeff363c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 19:37:01 +0000
Subject: [PATCH 1687/2232] Mark all shared structs as relocatable


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 851b953..cae9357 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -233,9 +233,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         writeln!(out, "{};", field.ident);
     }
 
-    if !methods.is_empty() || operator_eq || operator_ord {
-        writeln!(out);
-    }
+    writeln!(out);
 
     for method in methods {
         write!(out, "  ");
@@ -281,6 +279,9 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         );
     }
 
+    out.include.type_traits = true;
+    writeln!(out, "  using IsRelocatable = ::std::true_type;");
+
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }

From 665b7f5b6cf0fc5ba61c8e4f5d6d9247eda52e97 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 20:04:51 +0000
Subject: [PATCH 1688/2232] Merge pull request #560 from dtolnay/relocatable


Mark all shared structs as relocatable
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 851b953..cae9357 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -233,9 +233,7 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         writeln!(out, "{};", field.ident);
     }
 
-    if !methods.is_empty() || operator_eq || operator_ord {
-        writeln!(out);
-    }
+    writeln!(out);
 
     for method in methods {
         write!(out, "  ");
@@ -281,6 +279,9 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         );
     }
 
+    out.include.type_traits = true;
+    writeln!(out, "  using IsRelocatable = ::std::true_type;");
+
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }

From a7b2b30c28fa82dd353153c2d8f00418241b6f92 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 10 2020 20:22:18 +0000
Subject: [PATCH 1689/2232] Release 1.0.14


---

diff --git a/Cargo.toml b/Cargo.toml
index d886fde..58e93f8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.13" # remember to update html_root_url
+version = "1.0.14" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.13", path = "macro" }
+cxxbridge-macro = { version = "=1.0.14", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.13", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.14", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.13", path = "gen/build" }
+cxx-build = { version = "=1.0.14", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index a5f33a8..37ba09c 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.13"
+version = "1.0.14"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 59695a2..ec60057 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.13"
+version = "1.0.14"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 00eda7b..9eb1087 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.13"
+version = "1.0.14"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index d9b44dc..330611f 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.13"
+version = "0.7.14"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index d533b4f..825f9e1 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.13"
+version = "1.0.14"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 1e3b212..14357c9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.13")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.14")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 14d67e8..8f9be7a 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.13"
+version = "1.0.14"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.13"
+version = "1.0.14"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.13"
+version = "0.7.14"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.13"
+version = "1.0.14"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.13"
+version = "1.0.14"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.13"
+version = "1.0.14"
 dependencies = [
  "cxx",
  "proc-macro2",

From 53c9b047d66db29156233381b4b5594d192ddef9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 02:27:07 +0000
Subject: [PATCH 1690/2232] Update ui test suite to nightly-2020-12-11


---

diff --git a/tests/ui/root_namespace.stderr b/tests/ui/root_namespace.stderr
index ed07e66..a9c01a2 100644
--- a/tests/ui/root_namespace.stderr
+++ b/tests/ui/root_namespace.stderr
@@ -1,5 +1,5 @@
-error: unexpected token: `]`
+error: expected expression, found `]`
  --> $DIR/root_namespace.rs:9:19
   |
 9 |     #[namespace = ]
-  |                   ^
+  |                   ^ expected expression

From 1cde514d947fa54e8ab60342d6a63c438ba9edf7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 03:48:20 +0000
Subject: [PATCH 1691/2232] Clean up unused mut from Unique-/SharedPtr expansion


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9e4bd6b..f50328a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1056,7 +1056,7 @@ fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
         || types.aliases.contains_key(&ident.rust);
     let new_method = if can_construct_from_value {
         Some(quote! {
-            fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
+            fn __new(value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_uninit]
                     fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
@@ -1136,7 +1136,7 @@ fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
         || types.aliases.contains_key(&ident.rust);
     let new_method = if can_construct_from_value {
         Some(quote! {
-            unsafe fn __new(mut value: Self, new: *mut ::std::ffi::c_void) {
+            unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_uninit]
                     fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;

From 5b16340b6744be3261eca8ce6b255c9301aad9f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 03:48:37 +0000
Subject: [PATCH 1692/2232] Support shared_ptr of primitives


---

diff --git a/src/cxx.cc b/src/cxx.cc
index ac10df1..2be483d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -331,6 +331,15 @@ Error &Error::operator=(Error &&other) noexcept {
 
 const char *Error::what() const noexcept { return this->msg; }
 
+namespace {
+template <typename T>
+union MaybeUninit {
+  T value;
+  MaybeUninit() {}
+  ~MaybeUninit() {}
+};
+} // namespace
+
 } // namespace cxxbridge1
 } // namespace rust
 
@@ -443,6 +452,34 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
+#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE)                                    \
+  static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), "");  \
+  static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), "");    \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null(                           \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    new (ptr) std::shared_ptr<CXX_TYPE>();                                     \
+  }                                                                            \
+  CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit(                    \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    CXX_TYPE *uninit =                                                         \
+        reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>);         \
+    new (ptr) std::shared_ptr<CXX_TYPE>(uninit);                               \
+    return uninit;                                                             \
+  }                                                                            \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone(                          \
+      const std::shared_ptr<CXX_TYPE> &self,                                   \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    new (ptr) std::shared_ptr<CXX_TYPE>(self);                                 \
+  }                                                                            \
+  const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get(                 \
+      const std::shared_ptr<CXX_TYPE> &self) noexcept {                        \
+    return self.get();                                                         \
+  }                                                                            \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop(                           \
+      const std::shared_ptr<CXX_TYPE> *self) noexcept {                        \
+    self->~shared_ptr();                                                       \
+  }
+
 // Usize and isize are the same type as one of the below.
 #define FOR_EACH_NUMERIC(MACRO)                                                \
   MACRO(u8, uint8_t)                                                           \
@@ -468,9 +505,16 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   MACRO(char, char)                                                            \
   MACRO(string, rust::String)
 
+#define FOR_EACH_SHARED_PTR(MACRO)                                             \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
+  MACRO(usize, size_t)                                                         \
+  MACRO(isize, rust::isize)                                                    \
+  MACRO(string, std::string)
+
 extern "C" {
 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
 FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
+FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
 } // extern "C"
 
 namespace rust {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 7fdb356..63ad7d3 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
 use crate::kind::Trivial;
 use crate::ExternType;
 use core::ffi::c_void;
@@ -189,3 +190,77 @@ pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
     unsafe fn __drop(this: *mut c_void);
 }
+
+macro_rules! impl_shared_ptr_target {
+    ($segment:expr, $name:expr, $ty:ty) => {
+        unsafe impl SharedPtrTarget for $ty {
+            const __NAME: &'static dyn Display = &$name;
+            unsafe fn __null(new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")]
+                        fn __null(new: *mut c_void);
+                    }
+                }
+                __null(new);
+            }
+            unsafe fn __new(value: Self, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")]
+                        fn __uninit(new: *mut c_void) -> *mut c_void;
+                    }
+                }
+                __uninit(new).cast::<$ty>().write(value);
+            }
+            unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")]
+                        fn __clone(this: *const c_void, new: *mut c_void);
+                    }
+                }
+                __clone(this, new);
+            }
+            unsafe fn __get(this: *const c_void) -> *const Self {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")]
+                        fn __get(this: *const c_void) -> *const c_void;
+                    }
+                }
+                __get(this).cast()
+            }
+            unsafe fn __drop(this: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")]
+                        fn __drop(this: *mut c_void);
+                    }
+                }
+                __drop(this);
+            }
+        }
+    };
+}
+
+macro_rules! impl_shared_ptr_target_for_primitive {
+    ($ty:ident) => {
+        impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
+impl_shared_ptr_target_for_primitive!(u8);
+impl_shared_ptr_target_for_primitive!(u16);
+impl_shared_ptr_target_for_primitive!(u32);
+impl_shared_ptr_target_for_primitive!(u64);
+impl_shared_ptr_target_for_primitive!(usize);
+impl_shared_ptr_target_for_primitive!(i8);
+impl_shared_ptr_target_for_primitive!(i16);
+impl_shared_ptr_target_for_primitive!(i32);
+impl_shared_ptr_target_for_primitive!(i64);
+impl_shared_ptr_target_for_primitive!(isize);
+impl_shared_ptr_target_for_primitive!(f32);
+impl_shared_ptr_target_for_primitive!(f64);
+
+impl_shared_ptr_target!("string", "CxxString", CxxString);

From f72b0c61820774e6e42c04404f2a7cecc64d5514 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 03:54:22 +0000
Subject: [PATCH 1693/2232] Suppress modernize-use-equals-default


Clang-tidy emits this warning:

    src/cxx.cc:338:3: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
      MaybeUninit() {}
      ^             ~~
                    = default;
    src/cxx.cc:339:3: warning: use '= default' to define a trivial destructor [modernize-use-equals-default]
      ~MaybeUninit() {}
      ^              ~~
                     = default;

but following the suggestion makes the code not compile (the default
implementation of the default constructor "is implicitly deleted because
the default definition would be ill-formed").

    src/cxx.cc: In function ‘std::string* cxxbridge1$std$shared_ptr$string$uninit(std::shared_ptr<std::__cxx11::basic_string<char> >*)’:
    src/cxx.cc:465:48: error: use of deleted function ‘rust::cxxbridge1::{anonymous}::MaybeUninit<T>::MaybeUninit() [with T = std::__cxx11::basic_string<char>]’
      465 |         reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>);         \
          |                                                ^~~~~~~~~~~~~~~~~~~~~
    src/cxx.cc:512:3: note: in expansion of macro ‘SHARED_PTR_OPS’
      512 |   MACRO(string, std::string)
          |   ^~~~~
    src/cxx.cc:517:1: note: in expansion of macro ‘FOR_EACH_SHARED_PTR’
      517 | FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
          | ^~~~~~~~~~~~~~~~~~~
    src/cxx.cc:338:3: note: ‘rust::cxxbridge1::{anonymous}::MaybeUninit<T>::MaybeUninit() [with T = std::__cxx11::basic_string<char>]’ is implicitly deleted because the default definition would be ill-formed:
      338 |   MaybeUninit() = default;
          |   ^~~~~~~~~~~
    src/cxx.cc:337:5: error: union member ‘rust::cxxbridge1::{anonymous}::MaybeUninit<std::__cxx11::basic_string<char> >::value’ with non-trivial ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
      337 |   T value;
          |     ^~~~~

---

diff --git a/.clang-tidy b/.clang-tidy
index 1d45713..b94f5a9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -14,5 +14,6 @@ Checks:
   -cppcoreguidelines-pro-type-reinterpret-cast,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
+  -modernize-use-equals-default,
   -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h

From 9df2aac1342cc670a48074d5565431dfd6d0887b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 04:06:57 +0000
Subject: [PATCH 1694/2232] Remove SharedPtr to &mut conversions


These are broken because multiple SharedPtrs can point to the same data,
and getting a &mut from each of them would result in multiple &mut to
overlapping data.

---

diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 7fdb356..c0aa75a 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -4,8 +4,7 @@ use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem::MaybeUninit;
-use core::ops::{Deref, DerefMut};
-use core::pin::Pin;
+use core::ops::Deref;
 
 /// BInding to C++ `std::shared_ptr<T>`.
 #[repr(C)]
@@ -61,29 +60,6 @@ where
         let this = self as *const Self as *const c_void;
         unsafe { T::__get(this).as_ref() }
     }
-
-    /// Returns a mutable pinned reference to the object owned by this SharedPtr
-    /// if any, otherwise None.
-    pub fn as_mut(&mut self) -> Option<Pin<&mut T>> {
-        let this = self as *mut Self as *mut c_void;
-        unsafe {
-            let mut_reference = (T::__get(this) as *mut T).as_mut()?;
-            Some(Pin::new_unchecked(mut_reference))
-        }
-    }
-
-    /// Returns a mutable pinned reference to the object owned by this
-    /// SharedPtr.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the SharedPtr holds a null pointer.
-    pub fn pin_mut(&mut self) -> Pin<&mut T> {
-        match self.as_mut() {
-            Some(target) => target,
-            None => panic!("called pin_mut on a null SharedPtr<{}>", T::__NAME),
-        }
-    }
 }
 
 unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
@@ -128,18 +104,6 @@ where
     }
 }
 
-impl<T> DerefMut for SharedPtr<T>
-where
-    T: SharedPtrTarget + Unpin,
-{
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        match self.as_mut() {
-            Some(target) => Pin::into_inner(target),
-            None => panic!("called deref_mut on a null SharedPtr<{}>", T::__NAME),
-        }
-    }
-}
-
 impl<T> Debug for SharedPtr<T>
 where
     T: Debug + SharedPtrTarget,

From 265cd4c7dc0a1b311068ae3c1c1d8a6f1b919873 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 04:08:28 +0000
Subject: [PATCH 1695/2232] Merge pull request #563 from dtolnay/shared-ptr-primitive


Support shared_ptr of primitives
---

diff --git a/.clang-tidy b/.clang-tidy
index 1d45713..b94f5a9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -14,5 +14,6 @@ Checks:
   -cppcoreguidelines-pro-type-reinterpret-cast,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
+  -modernize-use-equals-default,
   -modernize-use-trailing-return-type,
 HeaderFilterRegex: cxx\.h
diff --git a/src/cxx.cc b/src/cxx.cc
index ac10df1..2be483d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -331,6 +331,15 @@ Error &Error::operator=(Error &&other) noexcept {
 
 const char *Error::what() const noexcept { return this->msg; }
 
+namespace {
+template <typename T>
+union MaybeUninit {
+  T value;
+  MaybeUninit() {}
+  ~MaybeUninit() {}
+};
+} // namespace
+
 } // namespace cxxbridge1
 } // namespace rust
 
@@ -443,6 +452,34 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
+#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE)                                    \
+  static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), "");  \
+  static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), "");    \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null(                           \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    new (ptr) std::shared_ptr<CXX_TYPE>();                                     \
+  }                                                                            \
+  CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit(                    \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    CXX_TYPE *uninit =                                                         \
+        reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>);         \
+    new (ptr) std::shared_ptr<CXX_TYPE>(uninit);                               \
+    return uninit;                                                             \
+  }                                                                            \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone(                          \
+      const std::shared_ptr<CXX_TYPE> &self,                                   \
+      std::shared_ptr<CXX_TYPE> *ptr) noexcept {                               \
+    new (ptr) std::shared_ptr<CXX_TYPE>(self);                                 \
+  }                                                                            \
+  const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get(                 \
+      const std::shared_ptr<CXX_TYPE> &self) noexcept {                        \
+    return self.get();                                                         \
+  }                                                                            \
+  void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop(                           \
+      const std::shared_ptr<CXX_TYPE> *self) noexcept {                        \
+    self->~shared_ptr();                                                       \
+  }
+
 // Usize and isize are the same type as one of the below.
 #define FOR_EACH_NUMERIC(MACRO)                                                \
   MACRO(u8, uint8_t)                                                           \
@@ -468,9 +505,16 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   MACRO(char, char)                                                            \
   MACRO(string, rust::String)
 
+#define FOR_EACH_SHARED_PTR(MACRO)                                             \
+  FOR_EACH_NUMERIC(MACRO)                                                      \
+  MACRO(usize, size_t)                                                         \
+  MACRO(isize, rust::isize)                                                    \
+  MACRO(string, std::string)
+
 extern "C" {
 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
 FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
+FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
 } // extern "C"
 
 namespace rust {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index c0aa75a..8f25005 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
 use crate::kind::Trivial;
 use crate::ExternType;
 use core::ffi::c_void;
@@ -153,3 +154,77 @@ pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
     unsafe fn __drop(this: *mut c_void);
 }
+
+macro_rules! impl_shared_ptr_target {
+    ($segment:expr, $name:expr, $ty:ty) => {
+        unsafe impl SharedPtrTarget for $ty {
+            const __NAME: &'static dyn Display = &$name;
+            unsafe fn __null(new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")]
+                        fn __null(new: *mut c_void);
+                    }
+                }
+                __null(new);
+            }
+            unsafe fn __new(value: Self, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")]
+                        fn __uninit(new: *mut c_void) -> *mut c_void;
+                    }
+                }
+                __uninit(new).cast::<$ty>().write(value);
+            }
+            unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")]
+                        fn __clone(this: *const c_void, new: *mut c_void);
+                    }
+                }
+                __clone(this, new);
+            }
+            unsafe fn __get(this: *const c_void) -> *const Self {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")]
+                        fn __get(this: *const c_void) -> *const c_void;
+                    }
+                }
+                __get(this).cast()
+            }
+            unsafe fn __drop(this: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")]
+                        fn __drop(this: *mut c_void);
+                    }
+                }
+                __drop(this);
+            }
+        }
+    };
+}
+
+macro_rules! impl_shared_ptr_target_for_primitive {
+    ($ty:ident) => {
+        impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
+impl_shared_ptr_target_for_primitive!(u8);
+impl_shared_ptr_target_for_primitive!(u16);
+impl_shared_ptr_target_for_primitive!(u32);
+impl_shared_ptr_target_for_primitive!(u64);
+impl_shared_ptr_target_for_primitive!(usize);
+impl_shared_ptr_target_for_primitive!(i8);
+impl_shared_ptr_target_for_primitive!(i16);
+impl_shared_ptr_target_for_primitive!(i32);
+impl_shared_ptr_target_for_primitive!(i64);
+impl_shared_ptr_target_for_primitive!(isize);
+impl_shared_ptr_target_for_primitive!(f32);
+impl_shared_ptr_target_for_primitive!(f64);
+
+impl_shared_ptr_target!("string", "CxxString", CxxString);

From 2b3117f5082f06f8ff146c06b05262eb9e548f42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 04:08:45 +0000
Subject: [PATCH 1696/2232] Release 1.0.15


---

diff --git a/Cargo.toml b/Cargo.toml
index 58e93f8..8374c6e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.14" # remember to update html_root_url
+version = "1.0.15" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.14", path = "macro" }
+cxxbridge-macro = { version = "=1.0.15", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.14", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.15", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.14", path = "gen/build" }
+cxx-build = { version = "=1.0.15", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 37ba09c..9682529 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.14"
+version = "1.0.15"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ec60057..ec4f50c 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.14"
+version = "1.0.15"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 9eb1087..f1451cb 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.14"
+version = "1.0.15"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 330611f..975e0fc 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.14"
+version = "0.7.15"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 825f9e1..b83ced7 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.14"
+version = "1.0.15"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 14357c9..d643c75 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.14")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.15")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8f9be7a..d1eecb8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.14"
+version = "1.0.15"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.14"
+version = "1.0.15"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.14"
+version = "0.7.15"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.14"
+version = "1.0.15"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.14"
+version = "1.0.15"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.14"
+version = "1.0.15"
 dependencies = [
  "cxx",
  "proc-macro2",

From dc62d713bc3c5bb3e4cbb812c02e5d698194afea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 21:53:17 +0000
Subject: [PATCH 1697/2232] Expose Vec capacity to C++


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 75f502b..61d2347 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -28,6 +28,7 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
   T *data() noexcept;
+  size_t capacity() const noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index cae9357..aad6429 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1384,6 +1384,11 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     );
     writeln!(
         out,
+        "size_t cxxbridge1$rust_vec${}$capacity(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "const {} *cxxbridge1$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
@@ -1442,6 +1447,11 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::capacity() const noexcept {{", inner);
+    writeln!(out, "  return cxxbridge1$rust_vec${}$capacity(this);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index da0194a..86de118 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -250,6 +250,7 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
   T *data() noexcept;
+  size_t capacity() const noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f50328a..2730b20 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -985,6 +985,7 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
+    let link_capacity = format!("{}capacity", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
@@ -994,6 +995,7 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
+    let local_capacity = format_ident!("{}capacity", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
@@ -1019,6 +1021,11 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
             (*this).len()
         }
         #[doc(hidden)]
+        #[export_name = #link_capacity]
+        unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+            (*this).capacity()
+        }
+        #[doc(hidden)]
         #[export_name = #link_data]
         unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
             (*this).as_ptr()
diff --git a/src/cxx.cc b/src/cxx.cc
index 2be483d..c17e0fb 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -414,6 +414,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
   size_t cxxbridge1$rust_vec$##RUST_TYPE##$len(                                \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity(                           \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data(                      \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
@@ -436,6 +438,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$len(this);                        \
   }                                                                            \
   template <>                                                                  \
+  size_t Vec<CXX_TYPE>::capacity() const noexcept {                            \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this);                   \
+  }                                                                            \
+  template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
     return cxxbridge1$rust_vec$##RUST_TYPE##$data(this);                       \
   }                                                                            \
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 8ddc4a7..126fdbf 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -41,6 +41,10 @@ impl<T> RustVec<T> {
         self.repr.len()
     }
 
+    pub fn capacity(&self) -> usize {
+        self.repr.capacity()
+    }
+
     pub fn as_ptr(&self) -> *const T {
         self.repr.as_ptr()
     }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 4f4b6ff..6aa0b76 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -30,6 +30,12 @@ macro_rules! rust_vec_shims {
                 }
             }
             attr! {
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity")]
+                unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize {
+                    (*this).repr.capacity()
+                }
+            }
+            attr! {
                 #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()

From 381d9530d400c39bc9e17512944ed08d450ba215 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 22:00:20 +0000
Subject: [PATCH 1698/2232] Merge pull request 565 from dtolnay/capacity


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 75f502b..61d2347 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -28,6 +28,7 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
   T *data() noexcept;
+  size_t capacity() const noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/gen/src/write.rs b/gen/src/write.rs
index cae9357..4d8bc55 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1384,6 +1384,11 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     );
     writeln!(
         out,
+        "size_t cxxbridge1$rust_vec${}$capacity(const ::rust::Vec<{}> *ptr) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "const {} *cxxbridge1$rust_vec${}$data(const ::rust::Vec<{0}> *ptr) noexcept;",
         inner, instance,
     );
@@ -1442,6 +1447,15 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(out, "size_t Vec<{}>::capacity() const noexcept {{", inner);
+    writeln!(
+        out,
+        "  return cxxbridge1$rust_vec${}$capacity(this);",
+        instance,
+    );
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index da0194a..86de118 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -250,6 +250,7 @@ public:
   bool empty() const noexcept;
   const T *data() const noexcept;
   T *data() noexcept;
+  size_t capacity() const noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f50328a..2730b20 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -985,6 +985,7 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
+    let link_capacity = format!("{}capacity", link_prefix);
     let link_data = format!("{}data", link_prefix);
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
@@ -994,6 +995,7 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
+    let local_capacity = format_ident!("{}capacity", local_prefix);
     let local_data = format_ident!("{}data", local_prefix);
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
@@ -1019,6 +1021,11 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
             (*this).len()
         }
         #[doc(hidden)]
+        #[export_name = #link_capacity]
+        unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+            (*this).capacity()
+        }
+        #[doc(hidden)]
         #[export_name = #link_data]
         unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
             (*this).as_ptr()
diff --git a/src/cxx.cc b/src/cxx.cc
index 2be483d..c17e0fb 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -414,6 +414,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
   size_t cxxbridge1$rust_vec$##RUST_TYPE##$len(                                \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
+  size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity(                           \
+      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data(                      \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
@@ -436,6 +438,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$len(this);                        \
   }                                                                            \
   template <>                                                                  \
+  size_t Vec<CXX_TYPE>::capacity() const noexcept {                            \
+    return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this);                   \
+  }                                                                            \
+  template <>                                                                  \
   const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
     return cxxbridge1$rust_vec$##RUST_TYPE##$data(this);                       \
   }                                                                            \
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 8ddc4a7..126fdbf 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -41,6 +41,10 @@ impl<T> RustVec<T> {
         self.repr.len()
     }
 
+    pub fn capacity(&self) -> usize {
+        self.repr.capacity()
+    }
+
     pub fn as_ptr(&self) -> *const T {
         self.repr.as_ptr()
     }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 4f4b6ff..6aa0b76 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -30,6 +30,12 @@ macro_rules! rust_vec_shims {
                 }
             }
             attr! {
+                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity")]
+                unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize {
+                    (*this).repr.capacity()
+                }
+            }
+            attr! {
                 #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")]
                 unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty {
                     (*this).repr.as_ptr()

From 9007e46b033c43ddb16215b723e03a73883dc35f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 22:05:12 +0000
Subject: [PATCH 1699/2232] Add Vec copy constructor


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 61d2347..ff8b7ff 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -19,6 +19,7 @@ public:
 
   Vec() noexcept;
   Vec(std::initializer_list<T>);
+  Vec(const Vec &);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
diff --git a/include/cxx.h b/include/cxx.h
index 86de118..22636fd 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -241,6 +241,7 @@ public:
 
   Vec() noexcept;
   Vec(std::initializer_list<T>);
+  Vec(const Vec &);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
@@ -649,6 +650,12 @@ Vec<T>::Vec(std::initializer_list<T> init) : Vec{} {
 }
 
 template <typename T>
+Vec<T>::Vec(const Vec &other) : Vec() {
+  this->reserve_total(other.size());
+  std::copy(other.begin(), other.end(), std::back_inserter(*this));
+}
+
+template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }

From dd42c72287cc775673bfd7c1d35af8583b3d1569 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 22:05:26 +0000
Subject: [PATCH 1700/2232] Add Vec copy assignment operator


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index ff8b7ff..761cbd8 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -24,6 +24,7 @@ public:
   ~Vec() noexcept;
 
   Vec &operator=(Vec &&) noexcept;
+  Vec &operator=(const Vec &);
 
   size_t size() const noexcept;
   bool empty() const noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index 22636fd..e3ef0be 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -246,6 +246,7 @@ public:
   ~Vec() noexcept;
 
   Vec &operator=(Vec &&) noexcept;
+  Vec &operator=(const Vec &);
 
   size_t size() const noexcept;
   bool empty() const noexcept;
@@ -676,6 +677,15 @@ Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
 }
 
 template <typename T>
+Vec<T> &Vec<T>::operator=(const Vec &other) {
+  if (this != &other) {
+    this->drop();
+    new (this) Vec(other);
+  }
+  return *this;
+}
+
+template <typename T>
 bool Vec<T>::empty() const noexcept {
   return size() == 0;
 }

From a42c638efe75cdd54f69f62292866e52a478752c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 22:12:32 +0000
Subject: [PATCH 1701/2232] Merge pull request #566 from dtolnay/vec-copy


Add Vec copy constructor and copy assignment operator
---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 61d2347..761cbd8 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -19,10 +19,12 @@ public:
 
   Vec() noexcept;
   Vec(std::initializer_list<T>);
+  Vec(const Vec &);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
   Vec &operator=(Vec &&) noexcept;
+  Vec &operator=(const Vec &);
 
   size_t size() const noexcept;
   bool empty() const noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index 86de118..e3ef0be 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -241,10 +241,12 @@ public:
 
   Vec() noexcept;
   Vec(std::initializer_list<T>);
+  Vec(const Vec &);
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
   Vec &operator=(Vec &&) noexcept;
+  Vec &operator=(const Vec &);
 
   size_t size() const noexcept;
   bool empty() const noexcept;
@@ -649,6 +651,12 @@ Vec<T>::Vec(std::initializer_list<T> init) : Vec{} {
 }
 
 template <typename T>
+Vec<T>::Vec(const Vec &other) : Vec() {
+  this->reserve_total(other.size());
+  std::copy(other.begin(), other.end(), std::back_inserter(*this));
+}
+
+template <typename T>
 Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) {
   new (&other) Vec();
 }
@@ -669,6 +677,15 @@ Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
 }
 
 template <typename T>
+Vec<T> &Vec<T>::operator=(const Vec &other) {
+  if (this != &other) {
+    this->drop();
+    new (this) Vec(other);
+  }
+  return *this;
+}
+
+template <typename T>
 bool Vec<T>::empty() const noexcept {
   return size() == 0;
 }

From 38f6fe2d3717821f37399fffb70308b4a52d9a0d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 11 2020 22:13:18 +0000
Subject: [PATCH 1702/2232] Release 1.0.16


---

diff --git a/Cargo.toml b/Cargo.toml
index 8374c6e..de7e132 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.15" # remember to update html_root_url
+version = "1.0.16" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.15", path = "macro" }
+cxxbridge-macro = { version = "=1.0.16", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.15", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.16", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.15", path = "gen/build" }
+cxx-build = { version = "=1.0.16", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 9682529..a770f11 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.15"
+version = "1.0.16"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ec4f50c..8c40e94 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.15"
+version = "1.0.16"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index f1451cb..f6d59d2 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.15"
+version = "1.0.16"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 975e0fc..5d723d0 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.15"
+version = "0.7.16"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index b83ced7..40fd07f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.15"
+version = "1.0.16"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index d643c75..f9fd9ae 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.15")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.16")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index d1eecb8..6d5a2e9 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.15"
+version = "1.0.16"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.15"
+version = "1.0.16"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.15"
+version = "0.7.16"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.15"
+version = "1.0.16"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.15"
+version = "1.0.16"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.15"
+version = "1.0.16"
 dependencies = [
  "cxx",
  "proc-macro2",

From 665178e9142a7ded11e0c16ca6a677e3a280db75 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 16:50:07 +0000
Subject: [PATCH 1703/2232] Fix omitted typenames incompatible with Visual C++ 2015


---

diff --git a/include/cxx.h b/include/cxx.h
index e3ef0be..8a91f26 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -783,7 +783,7 @@ Vec<T>::iterator::operator->() const noexcept {
 
 template <typename T>
 typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto pos = static_cast<char *>(this->pos) + this->stride * n;
   return *static_cast<T *>(pos);
 }
@@ -815,22 +815,22 @@ typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
 }
 
 template <typename T>
-typename Vec<T>::iterator &
-Vec<T>::iterator::operator+=(Vec<T>::iterator::difference_type n) noexcept {
+typename Vec<T>::iterator &Vec<T>::iterator::operator+=(
+    typename Vec<T>::iterator::difference_type n) noexcept {
   this->pos = static_cast<char *>(this->pos) + this->stride * n;
   return *this;
 }
 
 template <typename T>
-typename Vec<T>::iterator &
-Vec<T>::iterator::operator-=(Vec<T>::iterator::difference_type n) noexcept {
+typename Vec<T>::iterator &Vec<T>::iterator::operator-=(
+    typename Vec<T>::iterator::difference_type n) noexcept {
   this->pos = static_cast<char *>(this->pos) - this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator+(
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto ret = iterator(*this);
   ret.pos = static_cast<char *>(this->pos) + this->stride * n;
   return ret;
@@ -838,7 +838,7 @@ typename Vec<T>::iterator Vec<T>::iterator::operator+(
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator-(
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto ret = iterator(*this);
   ret.pos = static_cast<char *>(this->pos) - this->stride * n;
   return ret;

From 8693392e58529cf662bd6ca3bf76f34be8c12f28 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 16:57:07 +0000
Subject: [PATCH 1704/2232] Merge pull request #569 from dtolnay/typename


Fix omitted typenames incompatible with Visual C++ 2015
---

diff --git a/include/cxx.h b/include/cxx.h
index e3ef0be..8a91f26 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -783,7 +783,7 @@ Vec<T>::iterator::operator->() const noexcept {
 
 template <typename T>
 typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto pos = static_cast<char *>(this->pos) + this->stride * n;
   return *static_cast<T *>(pos);
 }
@@ -815,22 +815,22 @@ typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
 }
 
 template <typename T>
-typename Vec<T>::iterator &
-Vec<T>::iterator::operator+=(Vec<T>::iterator::difference_type n) noexcept {
+typename Vec<T>::iterator &Vec<T>::iterator::operator+=(
+    typename Vec<T>::iterator::difference_type n) noexcept {
   this->pos = static_cast<char *>(this->pos) + this->stride * n;
   return *this;
 }
 
 template <typename T>
-typename Vec<T>::iterator &
-Vec<T>::iterator::operator-=(Vec<T>::iterator::difference_type n) noexcept {
+typename Vec<T>::iterator &Vec<T>::iterator::operator-=(
+    typename Vec<T>::iterator::difference_type n) noexcept {
   this->pos = static_cast<char *>(this->pos) - this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator+(
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto ret = iterator(*this);
   ret.pos = static_cast<char *>(this->pos) + this->stride * n;
   return ret;
@@ -838,7 +838,7 @@ typename Vec<T>::iterator Vec<T>::iterator::operator+(
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::iterator::operator-(
-    Vec<T>::iterator::difference_type n) const noexcept {
+    typename Vec<T>::iterator::difference_type n) const noexcept {
   auto ret = iterator(*this);
   ret.pos = static_cast<char *>(this->pos) - this->stride * n;
   return ret;

From faf22e81122d5813a966a589a3b30ea683e7308d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 17:59:02 +0000
Subject: [PATCH 1705/2232] Release 1.0.17


---

diff --git a/Cargo.toml b/Cargo.toml
index de7e132..b1ce4ea 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.16" # remember to update html_root_url
+version = "1.0.17" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.16", path = "macro" }
+cxxbridge-macro = { version = "=1.0.17", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.16", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.17", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.16", path = "gen/build" }
+cxx-build = { version = "=1.0.17", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index a770f11..70e1230 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.16"
+version = "1.0.17"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 8c40e94..eee7055 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.16"
+version = "1.0.17"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index f6d59d2..cd0925d 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.16"
+version = "1.0.17"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 5d723d0..f8ef24a 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.16"
+version = "0.7.17"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 40fd07f..795bb58 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.16"
+version = "1.0.17"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index f9fd9ae..b57ea0e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.16")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.17")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 6d5a2e9..2328de4 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.16"
+version = "1.0.17"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.16"
+version = "1.0.17"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.16"
+version = "0.7.17"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.16"
+version = "1.0.17"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.16"
+version = "1.0.17"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.16"
+version = "1.0.17"
 dependencies = [
  "cxx",
  "proc-macro2",

From c4b3422dee7de0c6e8f86f940ca4e88daf8449db Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 23:24:52 +0000
Subject: [PATCH 1706/2232] Delete private Box default constructor


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4d8bc55..fc0872f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1348,8 +1348,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "#define CXXBRIDGE1_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge1$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
+        "{} *cxxbridge1$box${}$alloc() noexcept;",
+        inner, instance,
     );
     writeln!(
         out,
@@ -1415,8 +1415,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge1$box${}$uninit(this);", instance);
+    writeln!(out, "{} *Box<{}>::alloc() noexcept {{", inner, inner);
+    writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
diff --git a/include/cxx.h b/include/cxx.h
index 8a91f26..9ba49a1 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -200,6 +200,7 @@ public:
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
 
+  Box() = delete;
   Box(const Box &);
   Box(Box &&) noexcept;
   ~Box() noexcept;
@@ -225,8 +226,9 @@ public:
   T *into_raw() noexcept;
 
 private:
-  Box() noexcept;
-  void uninit() noexcept;
+  class uninit;
+  Box(uninit) noexcept;
+  static T *alloc() noexcept;
   void drop() noexcept;
   T *ptr;
 };
@@ -546,6 +548,9 @@ typename Slice<T>::iterator Slice<T>::end() const noexcept {
 #ifndef CXXBRIDGE1_RUST_BOX
 #define CXXBRIDGE1_RUST_BOX
 template <typename T>
+class Box<T>::uninit {};
+
+template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
 template <typename T>
@@ -554,14 +559,12 @@ Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
 }
 
 template <typename T>
-Box<T>::Box(const T &val) {
-  this->uninit();
+Box<T>::Box(const T &val) : ptr(alloc()) {
   ::new (this->ptr) T(val);
 }
 
 template <typename T>
-Box<T>::Box(T &&val) {
-  this->uninit();
+Box<T>::Box(T &&val) : ptr(alloc()) {
   ::new (this->ptr) T(std::move(val));
 }
 
@@ -578,7 +581,7 @@ Box<T> &Box<T>::operator=(const Box &other) {
     if (this->ptr) {
       **this = *other;
     } else {
-      this->uninit();
+      this->ptr = alloc();
       ::new (this->ptr) T(*other);
     }
   }
@@ -618,15 +621,15 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  Box box;
-  box.uninit();
+  Box box = uninit{};
+  box.ptr = alloc();
   ::new (box.ptr) T{std::forward<Fields>(fields)...};
   return box;
 }
 
 template <typename T>
 Box<T> Box<T>::from_raw(T *raw) noexcept {
-  Box box;
+  Box box = uninit{};
   box.ptr = raw;
   return box;
 }
@@ -639,7 +642,7 @@ T *Box<T>::into_raw() noexcept {
 }
 
 template <typename T>
-Box<T>::Box() noexcept = default;
+Box<T>::Box(uninit) noexcept {}
 #endif // CXXBRIDGE1_RUST_BOX
 
 #ifndef CXXBRIDGE1_RUST_VEC
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2730b20..4a17161 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -951,11 +951,11 @@ fn type_id(name: &Pair) -> TokenStream {
 
 fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
-    let link_uninit = format!("{}uninit", link_prefix);
+    let link_alloc = format!("{}alloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
     let local_prefix = format_ident!("{}__box_", &ident.rust);
-    let local_uninit = format_ident!("{}uninit", local_prefix);
+    let local_alloc = format_ident!("{}alloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
     let span = ident.span();
@@ -963,14 +963,9 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
         #[doc(hidden)]
         unsafe impl ::cxx::private::ImplBox for #ident {}
         #[doc(hidden)]
-        #[export_name = #link_uninit]
-        unsafe extern "C" fn #local_uninit(
-            this: *mut ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
-        ) {
-            ::std::ptr::write(
-                this,
-                ::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()),
-            );
+        #[export_name = #link_alloc]
+        unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
+            ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
         #[export_name = #link_drop]

From 6f18248fe4268be152ea7da37fe175c6440a968c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 23:44:32 +0000
Subject: [PATCH 1707/2232] Merge pull request #571 from dtolnay/box


Delete private Box default constructor
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4d8bc55..fc0872f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1348,8 +1348,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "#define CXXBRIDGE1_RUST_BOX_{}", instance);
     writeln!(
         out,
-        "void cxxbridge1$box${}$uninit(::rust::Box<{}> *ptr) noexcept;",
-        instance, inner,
+        "{} *cxxbridge1$box${}$alloc() noexcept;",
+        inner, instance,
     );
     writeln!(
         out,
@@ -1415,8 +1415,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
-    writeln!(out, "void Box<{}>::uninit() noexcept {{", inner);
-    writeln!(out, "  cxxbridge1$box${}$uninit(this);", instance);
+    writeln!(out, "{} *Box<{}>::alloc() noexcept {{", inner, inner);
+    writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
diff --git a/include/cxx.h b/include/cxx.h
index 8a91f26..9ba49a1 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -200,6 +200,7 @@ public:
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
 
+  Box() = delete;
   Box(const Box &);
   Box(Box &&) noexcept;
   ~Box() noexcept;
@@ -225,8 +226,9 @@ public:
   T *into_raw() noexcept;
 
 private:
-  Box() noexcept;
-  void uninit() noexcept;
+  class uninit;
+  Box(uninit) noexcept;
+  static T *alloc() noexcept;
   void drop() noexcept;
   T *ptr;
 };
@@ -546,6 +548,9 @@ typename Slice<T>::iterator Slice<T>::end() const noexcept {
 #ifndef CXXBRIDGE1_RUST_BOX
 #define CXXBRIDGE1_RUST_BOX
 template <typename T>
+class Box<T>::uninit {};
+
+template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
 template <typename T>
@@ -554,14 +559,12 @@ Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
 }
 
 template <typename T>
-Box<T>::Box(const T &val) {
-  this->uninit();
+Box<T>::Box(const T &val) : ptr(alloc()) {
   ::new (this->ptr) T(val);
 }
 
 template <typename T>
-Box<T>::Box(T &&val) {
-  this->uninit();
+Box<T>::Box(T &&val) : ptr(alloc()) {
   ::new (this->ptr) T(std::move(val));
 }
 
@@ -578,7 +581,7 @@ Box<T> &Box<T>::operator=(const Box &other) {
     if (this->ptr) {
       **this = *other;
     } else {
-      this->uninit();
+      this->ptr = alloc();
       ::new (this->ptr) T(*other);
     }
   }
@@ -618,15 +621,15 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  Box box;
-  box.uninit();
+  Box box = uninit{};
+  box.ptr = alloc();
   ::new (box.ptr) T{std::forward<Fields>(fields)...};
   return box;
 }
 
 template <typename T>
 Box<T> Box<T>::from_raw(T *raw) noexcept {
-  Box box;
+  Box box = uninit{};
   box.ptr = raw;
   return box;
 }
@@ -639,7 +642,7 @@ T *Box<T>::into_raw() noexcept {
 }
 
 template <typename T>
-Box<T>::Box() noexcept = default;
+Box<T>::Box(uninit) noexcept {}
 #endif // CXXBRIDGE1_RUST_BOX
 
 #ifndef CXXBRIDGE1_RUST_VEC
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 2730b20..4a17161 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -951,11 +951,11 @@ fn type_id(name: &Pair) -> TokenStream {
 
 fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
-    let link_uninit = format!("{}uninit", link_prefix);
+    let link_alloc = format!("{}alloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
     let local_prefix = format_ident!("{}__box_", &ident.rust);
-    let local_uninit = format_ident!("{}uninit", local_prefix);
+    let local_alloc = format_ident!("{}alloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
     let span = ident.span();
@@ -963,14 +963,9 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
         #[doc(hidden)]
         unsafe impl ::cxx::private::ImplBox for #ident {}
         #[doc(hidden)]
-        #[export_name = #link_uninit]
-        unsafe extern "C" fn #local_uninit(
-            this: *mut ::std::boxed::Box<::std::mem::MaybeUninit<#ident>>,
-        ) {
-            ::std::ptr::write(
-                this,
-                ::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()),
-            );
+        #[export_name = #link_alloc]
+        unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
+            ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
         #[export_name = #link_drop]

From c5dc45a0b33f812e52ee8d2832017e8ee6615b45 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 23:44:46 +0000
Subject: [PATCH 1708/2232] Fix uninitialized Drop on exception in rust::Box<T>::in_place


---

diff --git a/include/cxx.h b/include/cxx.h
index 9ba49a1..34b8771 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -621,10 +621,7 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  Box box = uninit{};
-  box.ptr = alloc();
-  ::new (box.ptr) T{std::forward<Fields>(fields)...};
-  return box;
+  return from_raw(::new (alloc()) T{std::forward<Fields>(fields)...});
 }
 
 template <typename T>

From 0f1ac8b3fd900c624621b7ea99ad4a2058afc48e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 12 2020 23:50:45 +0000
Subject: [PATCH 1709/2232] Merge pull request #572 from dtolnay/box


Fix uninitialized Drop on exception in rust::Box<T>::in_place
---

diff --git a/include/cxx.h b/include/cxx.h
index 9ba49a1..34b8771 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -621,10 +621,7 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  Box box = uninit{};
-  box.ptr = alloc();
-  ::new (box.ptr) T{std::forward<Fields>(fields)...};
-  return box;
+  return from_raw(::new (alloc()) T{std::forward<Fields>(fields)...});
 }
 
 template <typename T>

From a141674f56cc5fc9b2fc5f3c49fad6535b01182e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:21:24 +0000
Subject: [PATCH 1710/2232] Add Box construction tests


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cabcdbc..d6be097 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -276,6 +276,8 @@ pub mod ffi {
     struct Dag4 {
         dag0: Dag0,
     }
+
+    impl Box<Shared> {}
 }
 
 mod other {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2be1e06..2834801 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -50,6 +50,15 @@ Shared c_return_shared() { return Shared{2020}; }
 ::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; }
 
 rust::Box<R> c_return_box() {
+  Shared shared{0};
+  rust::Box<Shared> box{shared}; // explicit constructor from const T&
+  rust::Box<Shared> other{std::move(shared)}; // explicit constructor from T&&
+  box = other;                                // copy assignment
+  box = std::move(other);                     // move assignment
+  rust::Box<Shared> box2(box);                // copy constructor
+  rust::Box<Shared> other2(std::move(other)); // move constructor
+  rust::Box<Shared>::in_place(shared.z);      // placement static factory
+  rust::Box<Shared>::in_place<size_t>(0);
   return rust::Box<R>::from_raw(cxx_test_suite_get_box());
 }
 

From 4bd77b65dfda3777ae15771059f18b6ce2c7ad0b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:29:20 +0000
Subject: [PATCH 1711/2232] Merge pull request #573 from dtolnay/box


Add Box construction tests
---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cabcdbc..d6be097 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -276,6 +276,8 @@ pub mod ffi {
     struct Dag4 {
         dag0: Dag0,
     }
+
+    impl Box<Shared> {}
 }
 
 mod other {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2be1e06..2834801 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -50,6 +50,15 @@ Shared c_return_shared() { return Shared{2020}; }
 ::A::B::ABShared c_return_nested_ns_shared() { return ::A::B::ABShared{2020}; }
 
 rust::Box<R> c_return_box() {
+  Shared shared{0};
+  rust::Box<Shared> box{shared}; // explicit constructor from const T&
+  rust::Box<Shared> other{std::move(shared)}; // explicit constructor from T&&
+  box = other;                                // copy assignment
+  box = std::move(other);                     // move assignment
+  rust::Box<Shared> box2(box);                // copy constructor
+  rust::Box<Shared> other2(std::move(other)); // move constructor
+  rust::Box<Shared>::in_place(shared.z);      // placement static factory
+  rust::Box<Shared>::in_place<size_t>(0);
   return rust::Box<R>::from_raw(cxx_test_suite_get_box());
 }
 

From 25b3c1d1e212e854c0140818b86de7287f6301e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:29:34 +0000
Subject: [PATCH 1712/2232] Add dealloc shim for Box to dealloc without running T's Drop


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index fc0872f..cbad93c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1353,6 +1353,11 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     );
     writeln!(
         out,
+        "void cxxbridge1$box${}$dealloc({} *) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
@@ -1420,6 +1425,15 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(
+        out,
+        "void Box<{}>::dealloc({} *ptr) noexcept {{",
+        inner, inner,
+    );
+    writeln!(out, "  cxxbridge1$box${}$dealloc(ptr);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index 34b8771..a1e1700 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -229,6 +229,7 @@ private:
   class uninit;
   Box(uninit) noexcept;
   static T *alloc() noexcept;
+  static void dealloc(T *) noexcept;
   void drop() noexcept;
   T *ptr;
 };
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4a17161..433eca6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -952,10 +952,12 @@ fn type_id(name: &Pair) -> TokenStream {
 fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
+    let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
     let local_prefix = format_ident!("{}__box_", &ident.rust);
     let local_alloc = format_ident!("{}alloc", local_prefix);
+    let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
     let span = ident.span();
@@ -968,6 +970,11 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
             ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
+        #[export_name = #link_dealloc]
+        unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
+            ::std::boxed::Box::from_raw(ptr);
+        }
+        #[doc(hidden)]
         #[export_name = #link_drop]
         unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
             ::std::ptr::drop_in_place(this);

From e5703162e8896f038a93de07e1630f9bc0d891ca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:31:01 +0000
Subject: [PATCH 1713/2232] Move Box alloc/dealloc functions to guard object


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index cbad93c..44978f1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1420,14 +1420,18 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
-    writeln!(out, "{} *Box<{}>::alloc() noexcept {{", inner, inner);
+    writeln!(
+        out,
+        "{} *Box<{}>::allocation::alloc() noexcept {{",
+        inner, inner,
+    );
     writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
     writeln!(
         out,
-        "void Box<{}>::dealloc({} *ptr) noexcept {{",
+        "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
         inner, inner,
     );
     writeln!(out, "  cxxbridge1$box${}$dealloc(ptr);", instance);
diff --git a/include/cxx.h b/include/cxx.h
index a1e1700..52136cc 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -227,9 +227,8 @@ public:
 
 private:
   class uninit;
+  class allocation;
   Box(uninit) noexcept;
-  static T *alloc() noexcept;
-  static void dealloc(T *) noexcept;
   void drop() noexcept;
   T *ptr;
 };
@@ -552,6 +551,14 @@ template <typename T>
 class Box<T>::uninit {};
 
 template <typename T>
+class Box<T>::allocation {
+public:
+  static T *alloc() noexcept;
+  static void dealloc(T *) noexcept;
+  T *ptr;
+};
+
+template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
 template <typename T>
@@ -560,12 +567,12 @@ Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
 }
 
 template <typename T>
-Box<T>::Box(const T &val) : ptr(alloc()) {
+Box<T>::Box(const T &val) : ptr(allocation::alloc()) {
   ::new (this->ptr) T(val);
 }
 
 template <typename T>
-Box<T>::Box(T &&val) : ptr(alloc()) {
+Box<T>::Box(T &&val) : ptr(allocation::alloc()) {
   ::new (this->ptr) T(std::move(val));
 }
 
@@ -582,7 +589,7 @@ Box<T> &Box<T>::operator=(const Box &other) {
     if (this->ptr) {
       **this = *other;
     } else {
-      this->ptr = alloc();
+      this->ptr = allocation::alloc();
       ::new (this->ptr) T(*other);
     }
   }
@@ -622,7 +629,8 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  return from_raw(::new (alloc()) T{std::forward<Fields>(fields)...});
+  return from_raw(::new (allocation::alloc())
+                      T{std::forward<Fields>(fields)...});
 }
 
 template <typename T>

From e7d662d51d470caf9e54a1f55240ea81b7326de4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:38:22 +0000
Subject: [PATCH 1714/2232] Free Box allocation on T constructor exception


---

diff --git a/include/cxx.h b/include/cxx.h
index 52136cc..956c46e 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -553,6 +553,12 @@ class Box<T>::uninit {};
 template <typename T>
 class Box<T>::allocation {
 public:
+  allocation() noexcept : ptr(alloc()) {}
+  ~allocation() noexcept {
+    if (this->ptr) {
+      dealloc(this->ptr);
+    }
+  }
   static T *alloc() noexcept;
   static void dealloc(T *) noexcept;
   T *ptr;
@@ -567,13 +573,19 @@ Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
 }
 
 template <typename T>
-Box<T>::Box(const T &val) : ptr(allocation::alloc()) {
-  ::new (this->ptr) T(val);
+Box<T>::Box(const T &val) {
+  allocation alloc;
+  ::new (alloc.ptr) T(val);
+  this->ptr = alloc.ptr;
+  alloc.ptr = nullptr;
 }
 
 template <typename T>
-Box<T>::Box(T &&val) : ptr(allocation::alloc()) {
-  ::new (this->ptr) T(std::move(val));
+Box<T>::Box(T &&val) {
+  allocation alloc;
+  ::new (alloc.ptr) T(std::move(val));
+  this->ptr = alloc.ptr;
+  alloc.ptr = nullptr;
 }
 
 template <typename T>
@@ -589,8 +601,10 @@ Box<T> &Box<T>::operator=(const Box &other) {
     if (this->ptr) {
       **this = *other;
     } else {
-      this->ptr = allocation::alloc();
-      ::new (this->ptr) T(*other);
+      allocation alloc;
+      ::new (alloc.ptr) T(*other);
+      this->ptr = alloc.ptr;
+      alloc.ptr = nullptr;
     }
   }
   return *this;
@@ -629,8 +643,11 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  return from_raw(::new (allocation::alloc())
-                      T{std::forward<Fields>(fields)...});
+  allocation alloc;
+  auto ptr = alloc.ptr;
+  ::new (ptr) T{std::forward<Fields>(fields)...};
+  alloc.ptr = nullptr;
+  return from_raw(ptr);
 }
 
 template <typename T>

From f448e2007564ddeb5d7589d09945e1a87250d35e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:42:45 +0000
Subject: [PATCH 1715/2232] Hide raw alloc/dealloc functions


---

diff --git a/include/cxx.h b/include/cxx.h
index 956c46e..0a9df91 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -552,6 +552,8 @@ class Box<T>::uninit {};
 
 template <typename T>
 class Box<T>::allocation {
+  static T *alloc() noexcept;
+  static void dealloc(T *) noexcept;
 public:
   allocation() noexcept : ptr(alloc()) {}
   ~allocation() noexcept {
@@ -559,8 +561,6 @@ public:
       dealloc(this->ptr);
     }
   }
-  static T *alloc() noexcept;
-  static void dealloc(T *) noexcept;
   T *ptr;
 };
 

From 448624173c75283f0366e4db307f3d8752de217f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 00:52:20 +0000
Subject: [PATCH 1716/2232] Merge pull request #574 from dtolnay/box


Free Box allocation on T constructor exception
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index fc0872f..44978f1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1353,6 +1353,11 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     );
     writeln!(
         out,
+        "void cxxbridge1$box${}$dealloc({} *) noexcept;",
+        instance, inner,
+    );
+    writeln!(
+        out,
         "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
@@ -1415,11 +1420,24 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
-    writeln!(out, "{} *Box<{}>::alloc() noexcept {{", inner, inner);
+    writeln!(
+        out,
+        "{} *Box<{}>::allocation::alloc() noexcept {{",
+        inner, inner,
+    );
     writeln!(out, "  return cxxbridge1$box${}$alloc();", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    writeln!(
+        out,
+        "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
+        inner, inner,
+    );
+    writeln!(out, "  cxxbridge1$box${}$dealloc(ptr);", instance);
+    writeln!(out, "}}");
+
+    writeln!(out, "template <>");
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
     writeln!(out, "}}");
diff --git a/include/cxx.h b/include/cxx.h
index 34b8771..0a9df91 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -227,8 +227,8 @@ public:
 
 private:
   class uninit;
+  class allocation;
   Box(uninit) noexcept;
-  static T *alloc() noexcept;
   void drop() noexcept;
   T *ptr;
 };
@@ -551,6 +551,20 @@ template <typename T>
 class Box<T>::uninit {};
 
 template <typename T>
+class Box<T>::allocation {
+  static T *alloc() noexcept;
+  static void dealloc(T *) noexcept;
+public:
+  allocation() noexcept : ptr(alloc()) {}
+  ~allocation() noexcept {
+    if (this->ptr) {
+      dealloc(this->ptr);
+    }
+  }
+  T *ptr;
+};
+
+template <typename T>
 Box<T>::Box(const Box &other) : Box(*other) {}
 
 template <typename T>
@@ -559,13 +573,19 @@ Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
 }
 
 template <typename T>
-Box<T>::Box(const T &val) : ptr(alloc()) {
-  ::new (this->ptr) T(val);
+Box<T>::Box(const T &val) {
+  allocation alloc;
+  ::new (alloc.ptr) T(val);
+  this->ptr = alloc.ptr;
+  alloc.ptr = nullptr;
 }
 
 template <typename T>
-Box<T>::Box(T &&val) : ptr(alloc()) {
-  ::new (this->ptr) T(std::move(val));
+Box<T>::Box(T &&val) {
+  allocation alloc;
+  ::new (alloc.ptr) T(std::move(val));
+  this->ptr = alloc.ptr;
+  alloc.ptr = nullptr;
 }
 
 template <typename T>
@@ -581,8 +601,10 @@ Box<T> &Box<T>::operator=(const Box &other) {
     if (this->ptr) {
       **this = *other;
     } else {
-      this->ptr = alloc();
-      ::new (this->ptr) T(*other);
+      allocation alloc;
+      ::new (alloc.ptr) T(*other);
+      this->ptr = alloc.ptr;
+      alloc.ptr = nullptr;
     }
   }
   return *this;
@@ -621,7 +643,11 @@ T &Box<T>::operator*() noexcept {
 template <typename T>
 template <typename... Fields>
 Box<T> Box<T>::in_place(Fields &&... fields) {
-  return from_raw(::new (alloc()) T{std::forward<Fields>(fields)...});
+  allocation alloc;
+  auto ptr = alloc.ptr;
+  ::new (ptr) T{std::forward<Fields>(fields)...};
+  alloc.ptr = nullptr;
+  return from_raw(ptr);
 }
 
 template <typename T>
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4a17161..433eca6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -952,10 +952,12 @@ fn type_id(name: &Pair) -> TokenStream {
 fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
+    let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
     let local_prefix = format_ident!("{}__box_", &ident.rust);
     let local_alloc = format_ident!("{}alloc", local_prefix);
+    let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
     let span = ident.span();
@@ -968,6 +970,11 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
             ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
+        #[export_name = #link_dealloc]
+        unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
+            ::std::boxed::Box::from_raw(ptr);
+        }
+        #[doc(hidden)]
         #[export_name = #link_drop]
         unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
             ::std::ptr::drop_in_place(this);

From 439ed0b91a129a2980072855b9534a9303e5fbd1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 01:01:06 +0000
Subject: [PATCH 1717/2232] Remove unneeded self check in Box<T>::operator=


As long as T's operator= correctly handles self assignment, this logic
is correct without the additional check.

---

diff --git a/include/cxx.h b/include/cxx.h
index 0a9df91..ab03f32 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -597,15 +597,13 @@ Box<T>::~Box() noexcept {
 
 template <typename T>
 Box<T> &Box<T>::operator=(const Box &other) {
-  if (this != &other) {
-    if (this->ptr) {
-      **this = *other;
-    } else {
-      allocation alloc;
-      ::new (alloc.ptr) T(*other);
-      this->ptr = alloc.ptr;
-      alloc.ptr = nullptr;
-    }
+  if (this->ptr) {
+    **this = *other;
+  } else {
+    allocation alloc;
+    ::new (alloc.ptr) T(*other);
+    this->ptr = alloc.ptr;
+    alloc.ptr = nullptr;
   }
   return *this;
 }

From 5f702bbc840797d578e6d491cbf5b039175dbcdf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 01:15:44 +0000
Subject: [PATCH 1718/2232] Express Slice documentation using concepts requires clause


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 4f9d74a..fc2b4da 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -18,10 +18,9 @@ public:
   Slice(const Slice<T> &) noexcept;
   Slice(T *, size_t count) noexcept;
 
-  // if std::is_const<T> {
-  Slice &operator=(const Slice<T> &) noexcept;
-  // }
   Slice &operator=(Slice<T> &&) noexcept;
+  Slice &operator=(const Slice<T> &) noexcept
+    requires std::is_const_v<T>;
 
   T *data() const noexcept;
   size_t size() const noexcept;

From 2e637d96d109c1b501a86115e52103dad0cba432 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 05:08:01 +0000
Subject: [PATCH 1719/2232] Format with clang-format 10


---

diff --git a/include/cxx.h b/include/cxx.h
index ab03f32..575ec77 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -554,6 +554,7 @@ template <typename T>
 class Box<T>::allocation {
   static T *alloc() noexcept;
   static void dealloc(T *) noexcept;
+
 public:
   allocation() noexcept : ptr(alloc()) {}
   ~allocation() noexcept {

From 03c43f56f0adb94200e42b1998b582f9b972bac7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 05:11:16 +0000
Subject: [PATCH 1720/2232] Document and static assert assumptions on size_t size


---

diff --git a/src/cxx.cc b/src/cxx.cc
index c17e0fb..a11ba12 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -249,6 +249,23 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+// Rust specifies that usize is ABI compatible with C's uintptr_t.
+// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
+// However there is no direct Rust equivalent for size_t. C does not guarantee
+// that size_t and uintptr_t are compatible. In practice though, on all
+// platforms supported by Rust, they are identical for ABI purposes. See the
+// libc crate which unconditionally defines libc::size_t = usize. We expect the
+// same here and these assertions are just here to explicitly document that.
+// *Note that no assumption is made about C++ name mangling of signatures
+// containing these types, not here nor anywhere in CXX.*
+static_assert(sizeof(size_t) == sizeof(uintptr_t), "unsupported size_t size");
+static_assert(alignof(size_t) == alignof(uintptr_t),
+              "unsupported size_t alignment");
+static_assert(sizeof(rust::isize) == sizeof(intptr_t),
+              "unsupported ssize_t size");
+static_assert(alignof(rust::isize) == alignof(intptr_t),
+              "unsupported ssize_t alignment");
+
 static_assert(std::is_trivially_copy_constructible<Str>::value,
               "trivial Str(const Str &)");
 static_assert(std::is_trivially_copy_assignable<Str>::value,

From 8192e1b848fc0fdbd0616a9a38ed62214ca4aaeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 05:31:13 +0000
Subject: [PATCH 1721/2232] Merge pull request #576 from dtolnay/size_t


Document and static assert assumptions on size_t layout
---

diff --git a/src/cxx.cc b/src/cxx.cc
index c17e0fb..a11ba12 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -249,6 +249,23 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+// Rust specifies that usize is ABI compatible with C's uintptr_t.
+// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
+// However there is no direct Rust equivalent for size_t. C does not guarantee
+// that size_t and uintptr_t are compatible. In practice though, on all
+// platforms supported by Rust, they are identical for ABI purposes. See the
+// libc crate which unconditionally defines libc::size_t = usize. We expect the
+// same here and these assertions are just here to explicitly document that.
+// *Note that no assumption is made about C++ name mangling of signatures
+// containing these types, not here nor anywhere in CXX.*
+static_assert(sizeof(size_t) == sizeof(uintptr_t), "unsupported size_t size");
+static_assert(alignof(size_t) == alignof(uintptr_t),
+              "unsupported size_t alignment");
+static_assert(sizeof(rust::isize) == sizeof(intptr_t),
+              "unsupported ssize_t size");
+static_assert(alignof(rust::isize) == alignof(intptr_t),
+              "unsupported ssize_t alignment");
+
 static_assert(std::is_trivially_copy_constructible<Str>::value,
               "trivial Str(const Str &)");
 static_assert(std::is_trivially_copy_assignable<Str>::value,

From 1e784a3487190dcd5337b3d104f8c5de1c8ee760 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 05:34:52 +0000
Subject: [PATCH 1722/2232] Add aliases for the Rust numeric primitives


---

diff --git a/include/cxx.h b/include/cxx.h
index 575ec77..3ff671a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -417,6 +417,18 @@ public:
 template <typename T>
 struct IsRelocatable;
 
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+using usize = size_t; // see static asserts in cxx.cc
+using i8 = int8_t;
+using i16 = int16_t;
+using i32 = int32_t;
+using i64 = int64_t;
+using f32 = float;
+using f64 = double;
+
 // Snake case aliases for use in code that uses this style for type names.
 using string = String;
 using str = Str;

From 74dd66f781248173acd4d26fd86d23146bc95748 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 06:03:58 +0000
Subject: [PATCH 1723/2232] Import sys/types.h for ssize_t


Previously the header file generated for the following bridge did not
compile.

    #[cxx::bridge]
    mod ffi {
        struct S {
            x: isize,
        }
    }

    example-ecfac19134395bcc/out/cxxbridge/sources/example/src/main.rs.cc:15:15: error: ‘ssize_t’ does not name a type
       15 | using isize = ssize_t;
          |               ^~~~~~~
    example-ecfac19134395bcc/out/cxxbridge/sources/example/src/main.rs.cc:26:11: error: ‘isize’ in namespace ‘rust’ does not name a type
       26 |   ::rust::isize x;
          |           ^~~~~

---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index be70a71..cee188d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -93,6 +93,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     if builtin.rust_isize {
         include.basetsd = true;
+        include.sys_types = true;
     }
 
     if builtin.relocatable {
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 3a0d66b..6b7e580 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -37,6 +37,7 @@ pub struct Includes<'a> {
     pub utility: bool,
     pub vector: bool,
     pub basetsd: bool,
+    pub sys_types: bool,
     pub content: Content<'a>,
 }
 
@@ -88,6 +89,7 @@ pub(super) fn write(out: &mut OutFile) {
         utility,
         vector,
         basetsd,
+        sys_types,
         content: _,
     } = *include;
 
@@ -139,6 +141,18 @@ pub(super) fn write(out: &mut OutFile) {
     if basetsd {
         writeln!(out, "#if defined(_WIN32)");
         writeln!(out, "#include <basetsd.h>");
+    }
+    if sys_types {
+        if basetsd {
+            writeln!(out, "#else");
+        } else {
+            writeln!(out, "#if not defined(_WIN32)");
+        }
+    }
+    if sys_types {
+        writeln!(out, "#include <sys/types.h>");
+    }
+    if basetsd || sys_types {
         writeln!(out, "#endif");
     }
 }
diff --git a/include/cxx.h b/include/cxx.h
index 3ff671a..227b3fc 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -15,6 +15,8 @@
 #include <vector>
 #if defined(_WIN32)
 #include <basetsd.h>
+#else
+#include <sys/types.h>
 #endif
 
 namespace rust {

From 08679aeae2ea1b8af6979890a7356fa04408a47f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 06:10:01 +0000
Subject: [PATCH 1724/2232] Include cstddef for std::ptrdiff_t in iterator difference_type


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index cee188d..b32443c 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -59,6 +59,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_slice {
+        include.cstddef = true;
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
@@ -73,6 +74,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_vec {
         include.algorithm = true;
         include.array = true;
+        include.cstddef = true;
         include.initializer_list = true;
         include.iterator = true;
         include.new = true;

From be3cbf76940dfe83b9ebd34029d452e4b6dcb784 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 06:16:01 +0000
Subject: [PATCH 1725/2232] Use integer standard library types from std namespace


The implementation is not required to define these types in the global
namespace.

---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index b32443c..1de36e1 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -147,7 +147,7 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "struct operator_new {{");
         writeln!(
             out,
-            "  void *operator()(size_t sz) {{ return ::operator new(sz); }}",
+            "  void *operator()(::std::size_t sz) {{ return ::operator new(sz); }}",
         );
         writeln!(out, "}};");
         out.next_section();
@@ -158,7 +158,7 @@ pub(super) fn write(out: &mut OutFile) {
         );
         writeln!(
             out,
-            "  void *operator()(size_t sz) {{ return T::operator new(sz); }}",
+            "  void *operator()(::std::size_t sz) {{ return T::operator new(sz); }}",
         );
         writeln!(out, "}};");
     }
@@ -187,7 +187,7 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "  T value;");
         writeln!(
             out,
-            "  void *operator new(size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
+            "  void *operator new(::std::size_t sz) {{ return detail::operator_new<T>{{}}(sz); }}",
         );
         writeln!(out, "  MaybeUninit() {{}}");
         writeln!(out, "  ~MaybeUninit() {{}}");
@@ -201,7 +201,7 @@ pub(super) fn write(out: &mut OutFile) {
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  void *ptr;");
-        writeln!(out, "  size_t len;");
+        writeln!(out, "  ::std::size_t len;");
         writeln!(out, "}};");
         out.end_block(Block::Namespace("repr"));
     }
@@ -281,7 +281,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.cstddef = true;
         include.type_traits = true;
         out.next_section();
-        writeln!(out, "template <typename T, typename = size_t>");
+        writeln!(out, "template <typename T, typename = ::std::size_t>");
         writeln!(out, "struct is_complete : std::false_type {{}};");
         out.next_section();
         writeln!(out, "template <typename T>");
@@ -338,7 +338,7 @@ pub(super) fn write(out: &mut OutFile) {
         out.begin_block(Block::ExternC);
         writeln!(
             out,
-            "const char *cxxbridge1$exception(const char *, size_t);",
+            "const char *cxxbridge1$exception(const char *, ::std::size_t);",
         );
         out.end_block(Block::ExternC);
     }
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 44978f1..812c324 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -164,7 +164,7 @@ fn write_std_specializations(out: &mut OutFile, apis: &[Api]) {
                 writeln!(out, "template <> struct hash<{}> {{", qualified);
                 writeln!(
                     out,
-                    "  size_t operator()(const {} &self) const noexcept {{",
+                    "  ::std::size_t operator()(const {} &self) const noexcept {{",
                     qualified,
                 );
                 let link_name = mangle::operator(&strct.name, "hash");
@@ -473,7 +473,7 @@ fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
         let link_name = mangle::operator(&strct.name, "hash");
         writeln!(
             out,
-            "size_t {}(const {} &) noexcept;",
+            "::std::size_t {}(const {} &) noexcept;",
             link_name, strct.name.cxx,
         );
     }
@@ -1165,15 +1165,15 @@ fn write_atom(out: &mut OutFile, atom: Atom) {
     match atom {
         Bool => write!(out, "bool"),
         Char => write!(out, "char"),
-        U8 => write!(out, "uint8_t"),
-        U16 => write!(out, "uint16_t"),
-        U32 => write!(out, "uint32_t"),
-        U64 => write!(out, "uint64_t"),
-        Usize => write!(out, "size_t"),
-        I8 => write!(out, "int8_t"),
-        I16 => write!(out, "int16_t"),
-        I32 => write!(out, "int32_t"),
-        I64 => write!(out, "int64_t"),
+        U8 => write!(out, "::std::uint8_t"),
+        U16 => write!(out, "::std::uint16_t"),
+        U32 => write!(out, "::std::uint32_t"),
+        U64 => write!(out, "::std::uint64_t"),
+        Usize => write!(out, "::std::size_t"),
+        I8 => write!(out, "::std::int8_t"),
+        I16 => write!(out, "::std::int16_t"),
+        I32 => write!(out, "::std::int32_t"),
+        I64 => write!(out, "::std::int64_t"),
         Isize => write!(out, "::rust::isize"),
         F32 => write!(out, "float"),
         F64 => write!(out, "double"),
@@ -1384,12 +1384,12 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     );
     writeln!(
         out,
-        "size_t cxxbridge1$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
+        "::std::size_t cxxbridge1$rust_vec${}$len(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge1$rust_vec${}$capacity(const ::rust::Vec<{}> *ptr) noexcept;",
+        "::std::size_t cxxbridge1$rust_vec${}$capacity(const ::rust::Vec<{}> *ptr) noexcept;",
         instance, inner,
     );
     writeln!(
@@ -1399,17 +1399,17 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     );
     writeln!(
         out,
-        "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, size_t cap) noexcept;",
+        "void cxxbridge1$rust_vec${}$reserve_total(::rust::Vec<{}> *ptr, ::std::size_t cap) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, size_t len) noexcept;",
+        "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
         instance, inner,
     );
     writeln!(
         out,
-        "size_t cxxbridge1$rust_vec${}$stride() noexcept;",
+        "::std::size_t cxxbridge1$rust_vec${}$stride() noexcept;",
         instance,
     );
     writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
@@ -1460,12 +1460,20 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::size() const noexcept {{", inner);
+    writeln!(
+        out,
+        "::std::size_t Vec<{}>::size() const noexcept {{",
+        inner,
+    );
     writeln!(out, "  return cxxbridge1$rust_vec${}$len(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::capacity() const noexcept {{", inner);
+    writeln!(
+        out,
+        "::std::size_t Vec<{}>::capacity() const noexcept {{",
+        inner,
+    );
     writeln!(
         out,
         "  return cxxbridge1$rust_vec${}$capacity(this);",
@@ -1481,7 +1489,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "template <>");
     writeln!(
         out,
-        "void Vec<{}>::reserve_total(size_t cap) noexcept {{",
+        "void Vec<{}>::reserve_total(::std::size_t cap) noexcept {{",
         inner,
     );
     writeln!(
@@ -1492,7 +1500,11 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "void Vec<{}>::set_len(size_t len) noexcept {{", inner);
+    writeln!(
+        out,
+        "void Vec<{}>::set_len(::std::size_t len) noexcept {{",
+        inner,
+    );
     writeln!(
         out,
         "  return cxxbridge1$rust_vec${}$set_len(this, len);",
@@ -1501,7 +1513,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
-    writeln!(out, "size_t Vec<{}>::stride() noexcept {{", inner);
+    writeln!(out, "::std::size_t Vec<{}>::stride() noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$stride();", instance);
     writeln!(out, "}}");
 }
@@ -1716,14 +1728,14 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(
         out,
-        "size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
+        "::std::size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
         instance, inner,
     );
     writeln!(out, "  return s.size();");
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, size_t pos) noexcept {{",
+        "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, ::std::size_t pos) noexcept {{",
         inner, instance, inner,
     );
     writeln!(out, "  return &s[pos];");
diff --git a/include/cxx.h b/include/cxx.h
index 227b3fc..f41dde7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -41,7 +41,7 @@ public:
 
   String(const std::string &);
   String(const char *);
-  String(const char *, size_t);
+  String(const char *, std::size_t);
 
   String &operator=(const String &) noexcept;
   String &operator=(String &&) noexcept;
@@ -50,8 +50,8 @@ public:
 
   // Note: no null terminator.
   const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
+  std::size_t size() const noexcept;
+  std::size_t length() const noexcept;
 
   using iterator = char *;
   iterator begin() noexcept;
@@ -75,7 +75,7 @@ public:
 
 private:
   // Size and alignment statically verified by rust_string.rs.
-  std::array<uintptr_t, 3> repr;
+  std::array<std::uintptr_t, 3> repr;
 };
 #endif // CXXBRIDGE1_RUST_STRING
 
@@ -87,7 +87,7 @@ public:
   Str(const String &) noexcept;
   Str(const std::string &);
   Str(const char *);
-  Str(const char *, size_t);
+  Str(const char *, std::size_t);
 
   Str &operator=(const Str &) noexcept = default;
 
@@ -95,8 +95,8 @@ public:
 
   // Note: no null terminator.
   const char *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
+  std::size_t size() const noexcept;
+  std::size_t length() const noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
@@ -121,7 +121,7 @@ private:
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
-  size_t len;
+  std::size_t len;
 };
 #endif // CXXBRIDGE1_RUST_STR
 
@@ -145,14 +145,14 @@ class Slice final
     : private detail::copy_assignable_if<std::is_const<T>::value> {
 public:
   Slice() noexcept;
-  Slice(T *, size_t count) noexcept;
+  Slice(T *, std::size_t count) noexcept;
 
   Slice &operator=(const Slice<T> &) noexcept = default;
   Slice &operator=(Slice<T> &&) noexcept = default;
 
   T *data() const noexcept;
-  size_t size() const noexcept;
-  size_t length() const noexcept;
+  std::size_t size() const noexcept;
+  std::size_t length() const noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Slice(const Slice<T> &) noexcept = default;
@@ -167,13 +167,13 @@ private:
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   T *ptr;
-  size_t len;
+  std::size_t len;
 };
 
 template <typename T>
 class Slice<T>::iterator final {
 public:
-  using difference_type = ptrdiff_t;
+  using difference_type = std::ptrdiff_t;
   using value_type = T;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
@@ -252,23 +252,23 @@ public:
   Vec &operator=(Vec &&) noexcept;
   Vec &operator=(const Vec &);
 
-  size_t size() const noexcept;
+  std::size_t size() const noexcept;
   bool empty() const noexcept;
   const T *data() const noexcept;
   T *data() noexcept;
-  size_t capacity() const noexcept;
+  std::size_t capacity() const noexcept;
 
-  const T &operator[](size_t n) const noexcept;
-  const T &at(size_t n) const;
+  const T &operator[](std::size_t n) const noexcept;
+  const T &at(std::size_t n) const;
   const T &front() const;
   const T &back() const;
 
-  T &operator[](size_t n) noexcept;
-  T &at(size_t n);
+  T &operator[](std::size_t n) noexcept;
+  T &at(std::size_t n);
   T &front();
   T &back();
 
-  void reserve(size_t new_cap);
+  void reserve(std::size_t new_cap);
   void push_back(const T &value);
   void push_back(T &&value);
   template <typename... Args>
@@ -288,13 +288,13 @@ public:
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
 private:
-  static size_t stride() noexcept;
-  void reserve_total(size_t cap) noexcept;
-  void set_len(size_t len) noexcept;
+  static std::size_t stride() noexcept;
+  void reserve_total(std::size_t cap) noexcept;
+  void set_len(std::size_t len) noexcept;
   void drop() noexcept;
 
   // Size and alignment statically verified by rust_vec.rs.
-  std::array<uintptr_t, 3> repr;
+  std::array<std::uintptr_t, 3> repr;
 };
 
 template <typename T>
@@ -302,7 +302,7 @@ class Vec<T>::iterator final {
 public:
   using iterator_category = std::random_access_iterator_tag;
   using value_type = T;
-  using difference_type = ptrdiff_t;
+  using difference_type = std::ptrdiff_t;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
 
@@ -332,7 +332,7 @@ private:
   friend class Vec;
   friend class Vec<typename std::remove_const<T>::type>;
   void *pos;
-  size_t stride;
+  std::size_t stride;
 };
 #endif // CXXBRIDGE1_RUST_VEC
 
@@ -371,7 +371,7 @@ private:
   Error() noexcept = default;
   friend impl<Error>;
   const char *msg;
-  size_t len;
+  std::size_t len;
 };
 #endif // CXXBRIDGE1_RUST_ERROR
 
@@ -419,15 +419,15 @@ public:
 template <typename T>
 struct IsRelocatable;
 
-using u8 = uint8_t;
-using u16 = uint16_t;
-using u32 = uint32_t;
-using u64 = uint64_t;
-using usize = size_t; // see static asserts in cxx.cc
-using i8 = int8_t;
-using i16 = int16_t;
-using i32 = int32_t;
-using i64 = int64_t;
+using u8 = std::uint8_t;
+using u16 = std::uint16_t;
+using u32 = std::uint32_t;
+using u64 = std::uint64_t;
+using usize = std::size_t; // see static asserts in cxx.cc
+using i8 = std::int8_t;
+using i16 = std::int16_t;
+using i32 = std::int32_t;
+using i64 = std::int64_t;
 using f32 = float;
 using f64 = double;
 
@@ -483,9 +483,9 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #define CXXBRIDGE1_RUST_STR
 inline const char *Str::data() const noexcept { return this->ptr; }
 
-inline size_t Str::size() const noexcept { return this->len; }
+inline std::size_t Str::size() const noexcept { return this->len; }
 
-inline size_t Str::length() const noexcept { return this->len; }
+inline std::size_t Str::length() const noexcept { return this->len; }
 #endif // CXXBRIDGE1_RUST_STR
 
 #ifndef CXXBRIDGE1_RUST_SLICE
@@ -494,7 +494,7 @@ template <typename T>
 Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(alignof(T))), len(0) {}
 
 template <typename T>
-Slice<T>::Slice(T *s, size_t count) noexcept : ptr(s), len(count) {}
+Slice<T>::Slice(T *s, std::size_t count) noexcept : ptr(s), len(count) {}
 
 template <typename T>
 T *Slice<T>::data() const noexcept {
@@ -502,12 +502,12 @@ T *Slice<T>::data() const noexcept {
 }
 
 template <typename T>
-size_t Slice<T>::size() const noexcept {
+std::size_t Slice<T>::size() const noexcept {
   return this->len;
 }
 
 template <typename T>
-size_t Slice<T>::length() const noexcept {
+std::size_t Slice<T>::length() const noexcept {
   return this->len;
 }
 
@@ -735,13 +735,13 @@ T *Vec<T>::data() noexcept {
 }
 
 template <typename T>
-const T &Vec<T>::operator[](size_t n) const noexcept {
+const T &Vec<T>::operator[](std::size_t n) const noexcept {
   auto data = reinterpret_cast<const char *>(this->data());
   return *reinterpret_cast<const T *>(data + n * this->stride());
 }
 
 template <typename T>
-const T &Vec<T>::at(size_t n) const {
+const T &Vec<T>::at(std::size_t n) const {
   if (n >= this->size()) {
     panic<std::out_of_range>("rust::Vec index out of range");
   }
@@ -759,13 +759,13 @@ const T &Vec<T>::back() const {
 }
 
 template <typename T>
-T &Vec<T>::operator[](size_t n) noexcept {
+T &Vec<T>::operator[](std::size_t n) noexcept {
   auto data = reinterpret_cast<char *>(this->data());
   return *reinterpret_cast<T *>(data + n * this->stride());
 }
 
 template <typename T>
-T &Vec<T>::at(size_t n) {
+T &Vec<T>::at(std::size_t n) {
   if (n >= this->size()) {
     panic<std::out_of_range>("rust::Vec index out of range");
   }
@@ -783,7 +783,7 @@ T &Vec<T>::back() {
 }
 
 template <typename T>
-void Vec<T>::reserve(size_t new_cap) {
+void Vec<T>::reserve(std::size_t new_cap) {
   this->reserve_total(new_cap);
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index a11ba12..776663e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -10,8 +10,8 @@
 #include <vector>
 
 extern "C" {
-void cxxbridge1$cxx_string$init(std::string *s, const uint8_t *ptr,
-                                size_t len) noexcept {
+void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
+                                std::size_t len) noexcept {
   new (s) std::string(reinterpret_cast<const char *>(ptr), len);
 }
 
@@ -24,12 +24,12 @@ const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept {
   return s.data();
 }
 
-size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
+std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept {
   return s.length();
 }
 
-void cxxbridge1$cxx_string$push(std::string &s, const uint8_t *ptr,
-                                size_t len) noexcept {
+void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr,
+                                std::size_t len) noexcept {
   s.append(reinterpret_cast<const char *>(ptr), len);
 }
 
@@ -38,13 +38,13 @@ void cxxbridge1$string$new(rust::String *self) noexcept;
 void cxxbridge1$string$clone(rust::String *self,
                              const rust::String &other) noexcept;
 bool cxxbridge1$string$from(rust::String *self, const char *ptr,
-                            size_t len) noexcept;
+                            std::size_t len) noexcept;
 void cxxbridge1$string$drop(rust::String *self) noexcept;
 const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
-size_t cxxbridge1$string$len(const rust::String *self) noexcept;
+std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
 
 // rust::Str
-bool cxxbridge1$str$valid(const char *ptr, size_t len) noexcept;
+bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
 } // extern "C"
 
 namespace rust {
@@ -74,7 +74,7 @@ String::String(String &&other) noexcept : repr(other.repr) {
 
 String::~String() noexcept { cxxbridge1$string$drop(this); }
 
-static void initString(String *self, const char *s, size_t len) {
+static void initString(String *self, const char *s, std::size_t len) {
   if (!cxxbridge1$string$from(self, s, len)) {
     panic<std::invalid_argument>("data for rust::String is not utf-8");
   }
@@ -87,7 +87,7 @@ String::String(const char *s) {
   initString(this, s, std::strlen(s));
 }
 
-String::String(const char *s, size_t len) {
+String::String(const char *s, std::size_t len) {
   assert(s != nullptr || len == 0);
   initString(this,
              s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
@@ -119,9 +119,13 @@ const char *String::data() const noexcept {
   return cxxbridge1$string$ptr(this);
 }
 
-size_t String::size() const noexcept { return cxxbridge1$string$len(this); }
+std::size_t String::size() const noexcept {
+  return cxxbridge1$string$len(this);
+}
 
-size_t String::length() const noexcept { return cxxbridge1$string$len(this); }
+std::size_t String::length() const noexcept {
+  return cxxbridge1$string$len(this);
+}
 
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
@@ -177,7 +181,7 @@ Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
 
 Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
 
-static void initStr(const char *ptr, size_t len) {
+static void initStr(const char *ptr, std::size_t len) {
   if (!cxxbridge1$str$valid(ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
@@ -192,7 +196,7 @@ Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
   initStr(this->ptr, this->len);
 }
 
-Str::Str(const char *s, size_t len)
+Str::Str(const char *s, std::size_t len)
     : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
       len(len) {
   assert(s != nullptr || len == 0);
@@ -258,12 +262,13 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
 // same here and these assertions are just here to explicitly document that.
 // *Note that no assumption is made about C++ name mangling of signatures
 // containing these types, not here nor anywhere in CXX.*
-static_assert(sizeof(size_t) == sizeof(uintptr_t), "unsupported size_t size");
-static_assert(alignof(size_t) == alignof(uintptr_t),
+static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t),
+              "unsupported size_t size");
+static_assert(alignof(std::size_t) == alignof(std::uintptr_t),
               "unsupported size_t alignment");
-static_assert(sizeof(rust::isize) == sizeof(intptr_t),
+static_assert(sizeof(rust::isize) == sizeof(std::intptr_t),
               "unsupported ssize_t size");
-static_assert(alignof(rust::isize) == alignof(intptr_t),
+static_assert(alignof(rust::isize) == alignof(std::intptr_t),
               "unsupported ssize_t alignment");
 
 static_assert(std::is_trivially_copy_constructible<Str>::value,
@@ -272,40 +277,44 @@ static_assert(std::is_trivially_copy_assignable<Str>::value,
               "trivial operator=(const Str &)");
 static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()");
 
-static_assert(std::is_trivially_copy_constructible<Slice<const uint8_t>>::value,
-              "trivial Slice(const Slice &)");
-static_assert(std::is_trivially_move_constructible<Slice<const uint8_t>>::value,
-              "trivial Slice(Slice &&)");
-static_assert(std::is_trivially_copy_assignable<Slice<const uint8_t>>::value,
-              "trivial Slice::operator=(const Slice &) for const slices");
-static_assert(std::is_trivially_move_assignable<Slice<const uint8_t>>::value,
-              "trivial Slice::operator=(Slice &&)");
-static_assert(std::is_trivially_destructible<Slice<const uint8_t>>::value,
+static_assert(
+    std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value,
+    "trivial Slice(const Slice &)");
+static_assert(
+    std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value,
+    "trivial Slice(Slice &&)");
+static_assert(
+    std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value,
+    "trivial Slice::operator=(const Slice &) for const slices");
+static_assert(
+    std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value,
+    "trivial Slice::operator=(Slice &&)");
+static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value,
               "trivial ~Slice()");
 
-static_assert(std::is_trivially_copy_constructible<Slice<uint8_t>>::value,
+static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value,
               "trivial Slice(const Slice &)");
-static_assert(std::is_trivially_move_constructible<Slice<uint8_t>>::value,
+static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value,
               "trivial Slice(Slice &&)");
-static_assert(!std::is_copy_assignable<Slice<uint8_t>>::value,
+static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value,
               "delete Slice::operator=(const Slice &) for mut slices");
-static_assert(std::is_trivially_move_assignable<Slice<uint8_t>>::value,
+static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value,
               "trivial Slice::operator=(Slice &&)");
-static_assert(std::is_trivially_destructible<Slice<uint8_t>>::value,
+static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value,
               "trivial ~Slice()");
 
-static_assert(std::is_same<Vec<uint8_t>::const_iterator,
-                           Vec<const uint8_t>::iterator>::value,
+static_assert(std::is_same<Vec<std::uint8_t>::const_iterator,
+                           Vec<const std::uint8_t>::iterator>::value,
               "Vec<T>::const_iterator == Vec<const T>::iterator");
-static_assert(std::is_same<Vec<const uint8_t>::const_iterator,
-                           Vec<const uint8_t>::iterator>::value,
+static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator,
+                           Vec<const std::uint8_t>::iterator>::value,
               "Vec<const T>::const_iterator == Vec<const T>::iterator");
-static_assert(
-    !std::is_same<Vec<uint8_t>::const_iterator, Vec<uint8_t>::iterator>::value,
-    "Vec<T>::const_iterator != Vec<T>::iterator");
+static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
+                            Vec<std::uint8_t>::iterator>::value,
+              "Vec<T>::const_iterator != Vec<T>::iterator");
 
 extern "C" {
-const char *cxxbridge1$error(const char *ptr, size_t len) {
+const char *cxxbridge1$error(const char *ptr, std::size_t len) {
   char *copy = new char[len];
   std::strncpy(copy, ptr, len);
   return copy;
@@ -384,7 +393,7 @@ void cxxbridge1$unique_ptr$std$string$drop(
 } // extern "C"
 
 namespace {
-const size_t kMaxExpectedWordsInString = 8;
+const std::size_t kMaxExpectedWordsInString = 8;
 static_assert(alignof(std::string) <= alignof(void *),
               "unexpectedly large std::string alignment");
 static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
@@ -392,12 +401,12 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 } // namespace
 
 #define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
-  size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                             \
+  std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size(                        \
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
   const CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(           \
-      const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
+      const std::vector<CXX_TYPE> &s, std::size_t pos) noexcept {              \
     return &s[pos];                                                            \
   }                                                                            \
   void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null(                    \
@@ -429,17 +438,17 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
   void cxxbridge1$rust_vec$##RUST_TYPE##$drop(                                 \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
-  size_t cxxbridge1$rust_vec$##RUST_TYPE##$len(                                \
+  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len(                           \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
-  size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity(                           \
+  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity(                      \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data(                      \
       const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
-      rust::Vec<CXX_TYPE> *ptr, size_t cap) noexcept;                          \
+      rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept;                     \
   void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,     \
-                                                 size_t len) noexcept;         \
-  size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
+                                                 std::size_t len) noexcept;    \
+  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
@@ -451,11 +460,11 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this);                       \
   }                                                                            \
   template <>                                                                  \
-  size_t Vec<CXX_TYPE>::size() const noexcept {                                \
+  std::size_t Vec<CXX_TYPE>::size() const noexcept {                           \
     return cxxbridge1$rust_vec$##RUST_TYPE##$len(this);                        \
   }                                                                            \
   template <>                                                                  \
-  size_t Vec<CXX_TYPE>::capacity() const noexcept {                            \
+  std::size_t Vec<CXX_TYPE>::capacity() const noexcept {                       \
     return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this);                   \
   }                                                                            \
   template <>                                                                  \
@@ -463,15 +472,15 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     return cxxbridge1$rust_vec$##RUST_TYPE##$data(this);                       \
   }                                                                            \
   template <>                                                                  \
-  void Vec<CXX_TYPE>::reserve_total(size_t cap) noexcept {                     \
+  void Vec<CXX_TYPE>::reserve_total(std::size_t cap) noexcept {                \
     cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, cap);                \
   }                                                                            \
   template <>                                                                  \
-  void Vec<CXX_TYPE>::set_len(size_t len) noexcept {                           \
+  void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept {                      \
     cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len);                      \
   }                                                                            \
   template <>                                                                  \
-  size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
+  std::size_t Vec<CXX_TYPE>::stride() noexcept {                               \
     return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
@@ -505,20 +514,20 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 
 // Usize and isize are the same type as one of the below.
 #define FOR_EACH_NUMERIC(MACRO)                                                \
-  MACRO(u8, uint8_t)                                                           \
-  MACRO(u16, uint16_t)                                                         \
-  MACRO(u32, uint32_t)                                                         \
-  MACRO(u64, uint64_t)                                                         \
-  MACRO(i8, int8_t)                                                            \
-  MACRO(i16, int16_t)                                                          \
-  MACRO(i32, int32_t)                                                          \
-  MACRO(i64, int64_t)                                                          \
+  MACRO(u8, std::uint8_t)                                                      \
+  MACRO(u16, std::uint16_t)                                                    \
+  MACRO(u32, std::uint32_t)                                                    \
+  MACRO(u64, std::uint64_t)                                                    \
+  MACRO(i8, std::int8_t)                                                       \
+  MACRO(i16, std::int16_t)                                                     \
+  MACRO(i32, std::int32_t)                                                     \
+  MACRO(i64, std::int64_t)                                                     \
   MACRO(f32, float)                                                            \
   MACRO(f64, double)
 
 #define FOR_EACH_STD_VECTOR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
-  MACRO(usize, size_t)                                                         \
+  MACRO(usize, std::size_t)                                                    \
   MACRO(isize, rust::isize)                                                    \
   MACRO(string, std::string)
 
@@ -530,7 +539,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 
 #define FOR_EACH_SHARED_PTR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
-  MACRO(usize, size_t)                                                         \
+  MACRO(usize, std::size_t)                                                    \
   MACRO(isize, rust::isize)                                                    \
   MACRO(string, std::string)
 

From bac25829d1b7dae8bd416288f5bc1033f0fe1e2b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 07:14:01 +0000
Subject: [PATCH 1726/2232] Shorten name of string and vector modules


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 037fe6a..cf15e73 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,6 +1,6 @@
-use crate::cxx_string::CxxString;
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
+use crate::string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
diff --git a/src/lib.rs b/src/lib.rs
index b57ea0e..0142197 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -392,8 +392,6 @@ extern crate std;
 #[macro_use]
 mod macros;
 
-mod cxx_string;
-mod cxx_vector;
 mod exception;
 mod extern_type;
 mod function;
@@ -405,16 +403,20 @@ mod rust_string;
 mod rust_type;
 mod rust_vec;
 mod shared_ptr;
+#[path = "cxx_string.rs"]
+mod string;
 mod symbols;
 mod unique_ptr;
 mod unwind;
+#[path = "cxx_vector.rs"]
+mod vector;
 
-pub use crate::cxx_string::CxxString;
-pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
+pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
+pub use crate::vector::CxxVector;
 pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
@@ -439,8 +441,6 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
-    pub use crate::cxx_string::StackString;
-    pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
@@ -451,8 +451,10 @@ pub mod private {
     pub use crate::rust_type::{ImplBox, ImplVec, RustType};
     pub use crate::rust_vec::RustVec;
     pub use crate::shared_ptr::SharedPtrTarget;
+    pub use crate::string::StackString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
+    pub use crate::vector::VectorElement;
 }
 
 mod actually_private {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 8f25005..f355d9c 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,5 +1,5 @@
-use crate::cxx_string::CxxString;
 use crate::kind::Trivial;
+use crate::string::CxxString;
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 3655a7a..0f9fa8f 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,6 +1,6 @@
-use crate::cxx_string::CxxString;
-use crate::cxx_vector::{self, CxxVector, VectorElement};
 use crate::kind::Trivial;
+use crate::string::CxxString;
+use crate::vector::{self, CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -237,7 +237,7 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
     T: VectorElement + 'static,
 {
-    const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
+    const __NAME: &'static dyn Display = &vector::TypeName::<T>::new();
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }

From d854ea03fd3c0197e828bb5304a9710c0e04ba46 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 07:24:33 +0000
Subject: [PATCH 1727/2232] Merge pull request #579 from dtolnay/module


Shorten name of string and vector modules
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 037fe6a..cf15e73 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,6 +1,6 @@
-use crate::cxx_string::CxxString;
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
+use crate::string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
 use core::marker::{PhantomData, PhantomPinned};
diff --git a/src/lib.rs b/src/lib.rs
index b57ea0e..0142197 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -392,8 +392,6 @@ extern crate std;
 #[macro_use]
 mod macros;
 
-mod cxx_string;
-mod cxx_vector;
 mod exception;
 mod extern_type;
 mod function;
@@ -405,16 +403,20 @@ mod rust_string;
 mod rust_type;
 mod rust_vec;
 mod shared_ptr;
+#[path = "cxx_string.rs"]
+mod string;
 mod symbols;
 mod unique_ptr;
 mod unwind;
+#[path = "cxx_vector.rs"]
+mod vector;
 
-pub use crate::cxx_string::CxxString;
-pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
+pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
+pub use crate::vector::CxxVector;
 pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
@@ -439,8 +441,6 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
-    pub use crate::cxx_string::StackString;
-    pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
@@ -451,8 +451,10 @@ pub mod private {
     pub use crate::rust_type::{ImplBox, ImplVec, RustType};
     pub use crate::rust_vec::RustVec;
     pub use crate::shared_ptr::SharedPtrTarget;
+    pub use crate::string::StackString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
+    pub use crate::vector::VectorElement;
 }
 
 mod actually_private {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 8f25005..f355d9c 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,5 +1,5 @@
-use crate::cxx_string::CxxString;
 use crate::kind::Trivial;
+use crate::string::CxxString;
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 3655a7a..0f9fa8f 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,6 +1,6 @@
-use crate::cxx_string::CxxString;
-use crate::cxx_vector::{self, CxxVector, VectorElement};
 use crate::kind::Trivial;
+use crate::string::CxxString;
+use crate::vector::{self, CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -237,7 +237,7 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
     T: VectorElement + 'static,
 {
-    const __NAME: &'static dyn Display = &cxx_vector::TypeName::<T>::new();
+    const __NAME: &'static dyn Display = &vector::TypeName::<T>::new();
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }

From b5d039c44874dc3053be25899ddd76784e6cb0fd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 07:29:53 +0000
Subject: [PATCH 1728/2232] Expose public vector module


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index cf15e73..df29616 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,6 @@
+//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
+//! itself is exposed at the crate root.
+
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use crate::string::CxxString;
@@ -8,6 +11,9 @@ use core::mem;
 use core::ptr;
 use core::slice;
 
+#[doc(inline)]
+pub use crate::Vector;
+
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
 /// # Invariants
@@ -94,6 +100,9 @@ where
     }
 }
 
+/// Iterator over elements of a `CxxVector` by shared reference.
+///
+/// The iterator element type is `&'a T`.
 pub struct Iter<'a, T> {
     v: &'a CxxVector<T>,
     index: usize,
@@ -133,7 +142,7 @@ where
     }
 }
 
-pub struct TypeName<T> {
+pub(crate) struct TypeName<T> {
     element: PhantomData<T>,
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 0142197..8e1c5e3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -409,13 +409,14 @@ mod symbols;
 mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
-mod vector;
+pub mod vector;
 
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
 pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
+#[doc(inline)]
 pub use crate::vector::CxxVector;
 pub use cxxbridge_macro::bridge;
 

From 9b7f3dfe11862df108da083eb487806d7d0e64c2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 13 2020 07:51:46 +0000
Subject: [PATCH 1729/2232] Merge pull request #580 from dtolnay/vector


Expose public vector module
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index cf15e73..df29616 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,6 @@
+//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
+//! itself is exposed at the crate root.
+
 use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use crate::string::CxxString;
@@ -8,6 +11,9 @@ use core::mem;
 use core::ptr;
 use core::slice;
 
+#[doc(inline)]
+pub use crate::Vector;
+
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
 /// # Invariants
@@ -94,6 +100,9 @@ where
     }
 }
 
+/// Iterator over elements of a `CxxVector` by shared reference.
+///
+/// The iterator element type is `&'a T`.
 pub struct Iter<'a, T> {
     v: &'a CxxVector<T>,
     index: usize,
@@ -133,7 +142,7 @@ where
     }
 }
 
-pub struct TypeName<T> {
+pub(crate) struct TypeName<T> {
     element: PhantomData<T>,
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 0142197..8e1c5e3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -409,13 +409,14 @@ mod symbols;
 mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
-mod vector;
+pub mod vector;
 
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
 pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
+#[doc(inline)]
 pub use crate::vector::CxxVector;
 pub use cxxbridge_macro::bridge;
 

From ab3238ca8d645124fec35c668016dc2e02197385 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:02:02 +0000
Subject: [PATCH 1730/2232] Release 1.0.18


---

diff --git a/Cargo.toml b/Cargo.toml
index b1ce4ea..44dac8b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.17" # remember to update html_root_url
+version = "1.0.18" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.17", path = "macro" }
+cxxbridge-macro = { version = "=1.0.18", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.17", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.18", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.17", path = "gen/build" }
+cxx-build = { version = "=1.0.18", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 70e1230..751cf42 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.17"
+version = "1.0.18"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index eee7055..2522a72 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.17"
+version = "1.0.18"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index cd0925d..b109cb7 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.17"
+version = "1.0.18"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index f8ef24a..fa4eed6 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.17"
+version = "0.7.18"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 795bb58..f8206e7 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.17"
+version = "1.0.18"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 8e1c5e3..24fdc41 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.17")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.18")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2328de4..69d81b8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.17"
+version = "1.0.18"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.17"
+version = "1.0.18"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.17"
+version = "0.7.18"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.17"
+version = "1.0.18"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.17"
+version = "1.0.18"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.17"
+version = "1.0.18"
 dependencies = [
  "cxx",
  "proc-macro2",

From 724ac7581ec2d61ee6eadfaeef123c7717d1ed99 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:08:19 +0000
Subject: [PATCH 1731/2232] Make CxxVector's iterator an ExactSizeIterator


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index df29616..31dc11c 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -128,9 +128,23 @@ where
 
     fn next(&mut self) -> Option<Self::Item> {
         let next = self.v.get(self.index);
-        self.index += 1;
+        self.index += next.is_some() as usize;
         next
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T>
+where
+    T: VectorElement,
+{
+    fn len(&self) -> usize {
+        self.v.len() - self.index
+    }
 }
 
 impl<T> Debug for CxxVector<T>

From 0f3d3b542e15cc3504f542a97eb62756309359c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:08:19 +0000
Subject: [PATCH 1732/2232] Set iterator size hint for OrderedSet iteration


---

diff --git a/syntax/set.rs b/syntax/set.rs
index 6508f55..0618564 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -102,9 +102,14 @@ pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
 
 impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
     type Item = &'a T;
+
     fn next(&mut self) -> Option<Self::Item> {
         self.0.next().copied()
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
 }
 
 impl<'a, T> Debug for OrderedSet<&'a T>

From 4429a9e50ca3baaa64341e0c4d1732aa7714c9d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:20:52 +0000
Subject: [PATCH 1733/2232] Merge pull request #581 from dtolnay/exactsize


Make CxxVector's iterator an ExactSizeIterator
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index df29616..31dc11c 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -128,9 +128,23 @@ where
 
     fn next(&mut self) -> Option<Self::Item> {
         let next = self.v.get(self.index);
-        self.index += 1;
+        self.index += next.is_some() as usize;
         next
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T>
+where
+    T: VectorElement,
+{
+    fn len(&self) -> usize {
+        self.v.len() - self.index
+    }
 }
 
 impl<T> Debug for CxxVector<T>

From 526faa22142707fef19a8b9c943e4eda44f7dcfa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:21:02 +0000
Subject: [PATCH 1734/2232] Mark CxxVector iterator as FusedIterator


The contract is that once it's returned None, it is guaranteed to
continue returning None as many time as called again.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 31dc11c..d4bd711 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -6,6 +6,7 @@ use crate::kind::Trivial;
 use crate::string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
+use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
@@ -147,6 +148,8 @@ where
     }
 }
 
+impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
+
 impl<T> Debug for CxxVector<T>
 where
     T: VectorElement + Debug,

From d167e20c7192dc66809855f9ff3d626c593ac2ca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 00:38:46 +0000
Subject: [PATCH 1735/2232] Merge pull request #582 from dtolnay/fused


Mark CxxVector iterator as FusedIterator
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 31dc11c..d4bd711 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -6,6 +6,7 @@ use crate::kind::Trivial;
 use crate::string::CxxString;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
+use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
 use core::ptr;
@@ -147,6 +148,8 @@ where
     }
 }
 
+impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
+
 impl<T> Debug for CxxVector<T>
 where
     T: VectorElement + Debug,

From 8d6f7710f1cb8fc979c17c35279c30e58db6e54a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 09:44:49 +0000
Subject: [PATCH 1736/2232] Reflect generalized Slice support in table on website


---

diff --git a/book/src/bindings.md b/book/src/bindings.md
index b2069b8..4943f01 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -11,8 +11,8 @@ returns of extern functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
-<tr><td style="padding:3px 6px">&amp;[u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;[T] not implemented yet</i></sup></td></tr>
-<tr><td style="padding:3px 6px">&amp;mut [u8]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;uint8_t&gt;</a></b></td><td style="padding:3px 6px"><sup><i>arbitrary &amp;mut [T] not implemented yet</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>

From 83cbe894dcf6605ab3ad44ca851476b6e3e7dcf1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 14 2020 09:50:25 +0000
Subject: [PATCH 1737/2232] Remove shared_ptr from pending bindings table since it is done


---

diff --git a/book/src/bindings.md b/book/src/bindings.md
index 4943f01..b6e0e30 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -52,5 +52,4 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::shared_ptr&lt;T&gt;</td></tr>
 </table>

From b03d41d5d4a415815c9c810709ffc1e1336f958d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 16 2020 18:18:29 +0000
Subject: [PATCH 1738/2232] Remove unneeded Unpin import


Unpin is always available via the std prelude.

---

diff --git a/tests/ui/opaque_autotraits.rs b/tests/ui/opaque_autotraits.rs
index 322a000..99406d7 100644
--- a/tests/ui/opaque_autotraits.rs
+++ b/tests/ui/opaque_autotraits.rs
@@ -1,5 +1,3 @@
-use std::marker::Unpin;
-
 #[cxx::bridge]
 mod ffi {
     extern "C++" {
diff --git a/tests/ui/opaque_autotraits.stderr b/tests/ui/opaque_autotraits.stderr
index 61e9179..4f469ef 100644
--- a/tests/ui/opaque_autotraits.stderr
+++ b/tests/ui/opaque_autotraits.stderr
@@ -1,10 +1,10 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
-  --> $DIR/opaque_autotraits.rs:15:5
+  --> $DIR/opaque_autotraits.rs:13:5
    |
-10 | fn assert_send<T: Send>() {}
+8  | fn assert_send<T: Send>() {}
    |                   ---- required by this bound in `assert_send`
 ...
-15 |     assert_send::<ffi::Opaque>();
+13 |     assert_send::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const u8`
@@ -13,12 +13,12 @@ error[E0277]: `*const u8` cannot be sent between threads safely
    = note: required because it appears within the type `ffi::Opaque`
 
 error[E0277]: `*const u8` cannot be shared between threads safely
-  --> $DIR/opaque_autotraits.rs:16:5
+  --> $DIR/opaque_autotraits.rs:14:5
    |
-11 | fn assert_sync<T: Sync>() {}
+9  | fn assert_sync<T: Sync>() {}
    |                   ---- required by this bound in `assert_sync`
 ...
-16 |     assert_sync::<ffi::Opaque>();
+14 |     assert_sync::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const u8` cannot be shared between threads safely
    |
    = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const u8`
@@ -27,12 +27,12 @@ error[E0277]: `*const u8` cannot be shared between threads safely
    = note: required because it appears within the type `ffi::Opaque`
 
 error[E0277]: `PhantomPinned` cannot be unpinned
-  --> $DIR/opaque_autotraits.rs:17:5
+  --> $DIR/opaque_autotraits.rs:15:5
    |
-12 | fn assert_unpin<T: Unpin>() {}
+10 | fn assert_unpin<T: Unpin>() {}
    |                    ----- required by this bound in `assert_unpin`
 ...
-17 |     assert_unpin::<ffi::Opaque>();
+15 |     assert_unpin::<ffi::Opaque>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned`
    |
    = note: required because it appears within the type `PhantomData<PhantomPinned>`
diff --git a/tests/ui/unpin_impl.rs b/tests/ui/unpin_impl.rs
index e10cc72..129fcb1 100644
--- a/tests/ui/unpin_impl.rs
+++ b/tests/ui/unpin_impl.rs
@@ -1,5 +1,3 @@
-use std::marker::Unpin;
-
 #[cxx::bridge]
 mod ffi {
     extern "C++" {
diff --git a/tests/ui/unpin_impl.stderr b/tests/ui/unpin_impl.stderr
index 37e4f9d..01ee19c 100644
--- a/tests/ui/unpin_impl.stderr
+++ b/tests/ui/unpin_impl.stderr
@@ -1,8 +1,8 @@
 error[E0282]: type annotations needed for `fn()`
- --> $DIR/unpin_impl.rs:6:14
+ --> $DIR/unpin_impl.rs:4:14
   |
-3 | #[cxx::bridge]
+1 | #[cxx::bridge]
   | -------------- consider giving this pattern the explicit type `fn()`, with the type parameters specified
 ...
-6 |         type Opaque;
+4 |         type Opaque;
   |              ^^^^^^ cannot infer type

From 515ba1b420d8c73c7846b0ceb80a7bbd1cdb181e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 19:04:18 +0000
Subject: [PATCH 1739/2232] Test some C++ member functions returning references


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d6be097..2c065d9 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -165,9 +165,13 @@ pub mod ffi {
         fn get(self: &C) -> usize;
         fn set(self: Pin<&mut C>, n: usize) -> usize;
         fn get2(&self) -> usize;
+        fn getRef(self: &C) -> &usize;
+        fn getMut(self: Pin<&mut C>) -> &mut usize;
         fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
         fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
+        fn c_method_ref_on_shared(self: &Shared) -> &usize;
+        fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
         fn c_set_array(self: &mut Array, value: i32);
 
         #[rust_name = "i32_overloaded_method"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2834801..eeca98a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -22,6 +22,10 @@ size_t C::get() const { return this->n; }
 
 size_t C::get2() const { return this->n; }
 
+const size_t &C::getRef() const { return this->n; }
+
+size_t &C::getMut() { return this->n; }
+
 size_t C::set(size_t n) {
   this->n = n;
   return this->n;
@@ -33,6 +37,12 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 size_t Shared::c_method_on_shared() const noexcept { return 2021; }
 
+const size_t &Shared::c_method_ref_on_shared() const noexcept {
+  return this->z;
+}
+
+size_t &Shared::c_method_mut_on_shared() noexcept { return this->z; }
+
 void Array::c_set_array(int32_t val) noexcept {
   this->a = {val, val, val, val};
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 024ecea..355406d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -45,6 +45,8 @@ public:
   size_t get() const;
   size_t set(size_t n);
   size_t get2() const;
+  const size_t &getRef() const;
+  size_t &getMut();
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
diff --git a/tests/test.rs b/tests/test.rs
index 00a7228..165ae50 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -210,9 +210,13 @@ fn test_c_method_calls() {
     assert_eq!(2021, unique_ptr.pin_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
+    assert_eq!(2021, *unique_ptr.getRef());
+    assert_eq!(2021, *unique_ptr.pin_mut().getMut());
     assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap());
     assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
+    assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared());
+    assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared());
 
     let val = 42;
     let mut array = ffi::Array { a: [0, 0, 0, 0] };

From a020d10143b6e2f5b1efbdfc6bc3c10af97e4d42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 19:04:18 +0000
Subject: [PATCH 1740/2232] Consider mut receiver for allowing mut C++ return type


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 3b7b513..03b4724 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -464,6 +464,12 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
         _ => return,
     }
 
+    if let Some(r) = &efn.receiver {
+        if r.mutable {
+            return;
+        }
+    }
+
     for arg in &efn.args {
         if let Type::Ref(ty) = &arg.ty {
             if ty.mutable {

From 40319b4ab381c5811eacccc24210f5096649a31c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 19:16:11 +0000
Subject: [PATCH 1741/2232] Merge pull request #585 from dtolnay/mut


Consider mut receiver for allowing mut C++ return type

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 3b7b513..03b4724 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -464,6 +464,12 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
         _ => return,
     }
 
+    if let Some(r) = &efn.receiver {
+        if r.mutable {
+            return;
+        }
+    }
+
     for arg in &efn.args {
         if let Type::Ref(ty) = &arg.ty {
             if ty.mutable {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d6be097..2c065d9 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -165,9 +165,13 @@ pub mod ffi {
         fn get(self: &C) -> usize;
         fn set(self: Pin<&mut C>, n: usize) -> usize;
         fn get2(&self) -> usize;
+        fn getRef(self: &C) -> &usize;
+        fn getMut(self: Pin<&mut C>) -> &mut usize;
         fn set_succeed(self: Pin<&mut C>, n: usize) -> Result<usize>;
         fn get_fail(self: Pin<&mut C>) -> Result<usize>;
         fn c_method_on_shared(self: &Shared) -> usize;
+        fn c_method_ref_on_shared(self: &Shared) -> &usize;
+        fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
         fn c_set_array(self: &mut Array, value: i32);
 
         #[rust_name = "i32_overloaded_method"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2834801..eeca98a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -22,6 +22,10 @@ size_t C::get() const { return this->n; }
 
 size_t C::get2() const { return this->n; }
 
+const size_t &C::getRef() const { return this->n; }
+
+size_t &C::getMut() { return this->n; }
+
 size_t C::set(size_t n) {
   this->n = n;
   return this->n;
@@ -33,6 +37,12 @@ size_t C::get_fail() { throw std::runtime_error("unimplemented"); }
 
 size_t Shared::c_method_on_shared() const noexcept { return 2021; }
 
+const size_t &Shared::c_method_ref_on_shared() const noexcept {
+  return this->z;
+}
+
+size_t &Shared::c_method_mut_on_shared() noexcept { return this->z; }
+
 void Array::c_set_array(int32_t val) noexcept {
   this->a = {val, val, val, val};
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 024ecea..355406d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -45,6 +45,8 @@ public:
   size_t get() const;
   size_t set(size_t n);
   size_t get2() const;
+  const size_t &getRef() const;
+  size_t &getMut();
   size_t set_succeed(size_t n);
   size_t get_fail();
   const std::vector<uint8_t> &get_v() const;
diff --git a/tests/test.rs b/tests/test.rs
index 00a7228..165ae50 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -210,9 +210,13 @@ fn test_c_method_calls() {
     assert_eq!(2021, unique_ptr.pin_mut().set(2021));
     assert_eq!(2021, unique_ptr.get());
     assert_eq!(2021, unique_ptr.get2());
+    assert_eq!(2021, *unique_ptr.getRef());
+    assert_eq!(2021, *unique_ptr.pin_mut().getMut());
     assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap());
     assert!(unique_ptr.pin_mut().get_fail().is_err());
     assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared());
+    assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared());
+    assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared());
 
     let val = 42;
     let mut array = ffi::Array { a: [0, 0, 0, 0] };

From 917bb6f96e6593e84661848f8543c459890f65d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 19:27:14 +0000
Subject: [PATCH 1742/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 69d81b8..dd540d5 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -298,18 +298,18 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.5.7"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75cf45bb0bef80604d001caaec0d09da99611b3c0fd39d3080468875cdb65645"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "trybuild"
-version = "1.0.35"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7d30fe369fd650072b352b1a9cb9587669de6b89be3b8225544012c1c45292d"
+checksum = "17b06f8610494cbeb9a7665b398306f0109ab8708296d7f24b0bcd89178bb350"
 dependencies = [
  "dissimilar",
  "glob",

From 3077818a1fa82abd2838adb13abfe0cdcc0f9499 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 19:27:27 +0000
Subject: [PATCH 1743/2232] Release 1.0.19


---

diff --git a/Cargo.toml b/Cargo.toml
index 44dac8b..f725c26 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.18" # remember to update html_root_url
+version = "1.0.19" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.18", path = "macro" }
+cxxbridge-macro = { version = "=1.0.19", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.18", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.19", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.18", path = "gen/build" }
+cxx-build = { version = "=1.0.19", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 751cf42..fbd28f1 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.18"
+version = "1.0.19"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 2522a72..e83d30c 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.18"
+version = "1.0.19"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b109cb7..7711f92 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.18"
+version = "1.0.19"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index fa4eed6..d219e9b 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.18"
+version = "0.7.19"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index f8206e7..a75c092 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.18"
+version = "1.0.19"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 24fdc41..2cc2766 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.18")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.19")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index dd540d5..ba0ffaa 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.18"
+version = "1.0.19"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.18"
+version = "1.0.19"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.18"
+version = "0.7.19"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.18"
+version = "1.0.19"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.18"
+version = "1.0.19"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.18"
+version = "1.0.19"
 dependencies = [
  "cxx",
  "proc-macro2",

From cca2e616e092c88cd476ebb4521ad4e6bba8387b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 20:49:56 +0000
Subject: [PATCH 1744/2232] Add c_str() member function for rust::String


---

diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index c4a1b6a..8dc1ee4 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -33,6 +33,8 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  const char *c_str() noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index f41dde7..fc63095 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -53,6 +53,8 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
+  const char *c_str() noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index 776663e..6863129 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -42,6 +42,7 @@ bool cxxbridge1$string$from(rust::String *self, const char *ptr,
 void cxxbridge1$string$drop(rust::String *self) noexcept;
 const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
 std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
+void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
 
 // rust::Str
 bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
@@ -127,6 +128,14 @@ std::size_t String::length() const noexcept {
   return cxxbridge1$string$len(this);
 }
 
+const char *String::c_str() noexcept {
+  auto len = this->length();
+  cxxbridge1$string$reserve_total(this, len + 1);
+  auto ptr = this->data();
+  const_cast<char *>(ptr)[len] = '\0';
+  return ptr;
+}
+
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
 }
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 944aec4..91fd78a 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -45,3 +45,8 @@ unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
+
+#[export_name = "cxxbridge1$string$reserve_total"]
+unsafe extern "C" fn string_reserve_total(this: &mut String, cap: usize) {
+    this.reserve(cap);
+}

From 8bc83389f1e735660ea6653e54944957ac70bb4c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 18 2020 20:54:47 +0000
Subject: [PATCH 1745/2232] Add String c_str test


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index eeca98a..ca2bb6a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -716,6 +716,12 @@ extern "C" const char *cxx_run_test() noexcept {
     ASSERT((second.*cmp)(sec) == second_sec);
   }
 
+  rust::String cstring = "test";
+  ASSERT(cstring.length() == 4);
+  ASSERT(strncmp(cstring.data(), "test", 4) == 0);
+  ASSERT(strncmp(cstring.c_str(), "test", 5) == 0);
+  ASSERT(cstring.length() == 4);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 06183a751fe4c363a04f3e35b38ddb11f78c13b2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 20 2020 08:27:45 +0000
Subject: [PATCH 1746/2232] Merge pull request 586 from dtolnay/c_str


Add c_str() member function for rust::String

---

diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index c4a1b6a..8dc1ee4 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -33,6 +33,8 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  const char *c_str() noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index f41dde7..fc63095 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -53,6 +53,8 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
+  const char *c_str() noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/src/cxx.cc b/src/cxx.cc
index 776663e..6863129 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -42,6 +42,7 @@ bool cxxbridge1$string$from(rust::String *self, const char *ptr,
 void cxxbridge1$string$drop(rust::String *self) noexcept;
 const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
 std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
+void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
 
 // rust::Str
 bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
@@ -127,6 +128,14 @@ std::size_t String::length() const noexcept {
   return cxxbridge1$string$len(this);
 }
 
+const char *String::c_str() noexcept {
+  auto len = this->length();
+  cxxbridge1$string$reserve_total(this, len + 1);
+  auto ptr = this->data();
+  const_cast<char *>(ptr)[len] = '\0';
+  return ptr;
+}
+
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
 }
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 944aec4..91fd78a 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -45,3 +45,8 @@ unsafe extern "C" fn string_ptr(this: &String) -> *const u8 {
 unsafe extern "C" fn string_len(this: &String) -> usize {
     this.len()
 }
+
+#[export_name = "cxxbridge1$string$reserve_total"]
+unsafe extern "C" fn string_reserve_total(this: &mut String, cap: usize) {
+    this.reserve(cap);
+}
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index eeca98a..ca2bb6a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -716,6 +716,12 @@ extern "C" const char *cxx_run_test() noexcept {
     ASSERT((second.*cmp)(sec) == second_sec);
   }
 
+  rust::String cstring = "test";
+  ASSERT(cstring.length() == 4);
+  ASSERT(strncmp(cstring.data(), "test", 4) == 0);
+  ASSERT(strncmp(cstring.c_str(), "test", 5) == 0);
+  ASSERT(cstring.length() == 4);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 12b4a161988332a4dc79f16eb3494382ca97ecff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 04:25:09 +0000
Subject: [PATCH 1747/2232] Merge pull request #550 from adetaylor/no-pin-trivial-2


Allow un-pinned Trivial extern types to be passed by reference as arguments
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 812c324..4b95613 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,4 +1,3 @@
-use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
@@ -8,6 +7,7 @@ use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
     Type, Types, Var,
 };
+use crate::{gen::block::Block, syntax::types::TrivialReason};
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
 
@@ -117,8 +117,8 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
-            if out.types.required_trivial.contains_key(&ety.name.rust) {
-                check_trivial_extern_type(out, &ety.name)
+            if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
+                check_trivial_extern_type(out, &ety.name, reasons)
             }
         }
     }
@@ -369,7 +369,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
+fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialReason]) {
     // NOTE: The following static assertion is 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:
@@ -405,13 +405,16 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair) {
 
     let id = id.to_fully_qualified();
     out.builtin.relocatable = true;
-    writeln!(out, "static_assert(");
-    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
-    writeln!(
-        out,
-        "    \"type {} marked as Trivial in Rust is not trivially move constructible and trivially destructible in C++\");",
-        id,
-    );
+    for reason in reasons {
+        writeln!(out, "static_assert(");
+        writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
+        writeln!(
+            out,
+            "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
+            id,
+            reason
+        );
+    }
 }
 
 fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
diff --git a/syntax/check.rs b/syntax/check.rs
index 03b4724..65c0288 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,6 +1,5 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
-use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
     SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
@@ -189,7 +188,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
             cx.error(
                 ty,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}> or declare the type Trivial in a cxx::ExternType impl",
                     requires_pin,
                 ),
             );
@@ -325,19 +324,15 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(span, "extern type bounds are not implemented yet");
     }
 
-    if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
-        let what = match reason {
-            TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
-            TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
-            TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
-            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
-            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
-        };
-        let msg = format!(
-            "needs a cxx::ExternType impl in order to be used as {}",
-            what,
-        );
-        cx.error(ety, msg);
+    if let Some(reasons) = cx.types.required_trivial.get(&ety.name.rust) {
+        for reason in reasons {
+            let what = reason.describe_in_context(&ety);
+            let msg = format!(
+                "needs a cxx::ExternType impl in order to be used as {}",
+                what,
+            );
+            cx.error(ety, msg);
+        }
     }
 }
 
@@ -385,7 +380,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(
                 span,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use `self: Pin<&mut {}>`",
+                    "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>` or declare the type Trivial in a cxx::ExternType impl",
                     receiver.ty.rust,
                 ),
             );
diff --git a/syntax/types.rs b/syntax/types.rs
index 9652eb3..5ea59cf 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -6,7 +6,7 @@ use crate::syntax::{
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::BTreeMap as Map;
+use std::{collections::BTreeMap as Map, fmt::Display};
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,
@@ -16,7 +16,7 @@ pub struct Types<'a> {
     pub rust: Set<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
+    pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
     pub explicit_impls: Set<&'a Impl>,
     pub resolutions: Map<&'a RustName, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
@@ -167,15 +167,17 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial = Map::new();
-        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
-            if let Type::Ident(ident) = ty {
-                if cxx.contains(&ident.rust)
-                    && !structs.contains_key(&ident.rust)
-                    && !enums.contains_key(&ident.rust)
-                {
-                    required_trivial.entry(&ident.rust).or_insert(reason);
-                }
+        let mut required_trivial: Map<_, Vec<_>> = Map::new();
+
+        let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
+            if cxx.contains(&ident.rust)
+                && !structs.contains_key(&ident.rust)
+                && !enums.contains_key(&ident.rust)
+            {
+                required_trivial
+                    .entry(&ident.rust)
+                    .or_default()
+                    .push(reason);
             }
         };
         for api in apis {
@@ -183,17 +185,23 @@ impl<'a> Types<'a> {
                 Api::Struct(strct) => {
                     let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
-                        insist_alias_types_are_trivial(&field.ty, reason);
+                        if let Type::Ident(ident) = &field.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                     let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
-                        insist_alias_types_are_trivial(&arg.ty, reason);
+                        if let Type::Ident(ident) = &arg.ty {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                     if let Some(ret) = &efn.ret {
                         let reason = TrivialReason::FunctionReturn(efn);
-                        insist_alias_types_are_trivial(&ret, reason);
+                        if let Type::Ident(ident) = &ret {
+                            insist_extern_types_are_trivial(&ident, reason);
+                        }
                     }
                 }
                 _ => {}
@@ -203,11 +211,37 @@ impl<'a> Types<'a> {
             match ty {
                 Type::RustBox(ty) => {
                     let reason = TrivialReason::BoxTarget;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
                 }
                 Type::RustVec(ty) => {
                     let reason = TrivialReason::VecElement;
-                    insist_alias_types_are_trivial(&ty.inner, reason);
+                    if let Type::Ident(ident) = &ty.inner {
+                        insist_extern_types_are_trivial(&ident, reason);
+                    }
+                }
+                _ => {}
+            }
+        }
+        for api in apis {
+            match api {
+                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    let reason = TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn);
+                    if let Some(receiver) = &efn.receiver {
+                        if receiver.mutable && !receiver.pinned {
+                            insist_extern_types_are_trivial(&receiver.ty, reason);
+                        }
+                    }
+                    for arg in &efn.args {
+                        if let Type::Ref(reff) = &arg.ty {
+                            if reff.mutable && !reff.pinned {
+                                if let Type::Ident(ident) = &reff.inner {
+                                    insist_extern_types_are_trivial(&ident, reason);
+                                }
+                            }
+                        }
+                    }
                 }
                 _ => {}
             }
@@ -298,6 +332,36 @@ pub enum TrivialReason<'a> {
     FunctionReturn(&'a ExternFn),
     BoxTarget,
     VecElement,
+    UnpinnedMutableReferenceFunctionArgument(&'a ExternFn),
+}
+
+impl<'a> TrivialReason<'a> {
+    pub fn describe_in_context(&self, ety: &ExternType) -> String {
+        match self {
+            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
+            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
+            _ => self.to_string(),
+        }
+    }
+}
+
+impl<'a> Display for TrivialReason<'a> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
+            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
+            TrivialReason::FunctionReturn(efn) => {
+                write!(f, "a return value of `{}`", efn.name.rust)
+            }
+            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
+            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
+            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => write!(
+                f,
+                "a non-pinned mutable reference argument of {}",
+                efn.name.rust
+            ),
+        }
+    }
 }
 
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index a2c13d3..cd9fc2b 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -32,12 +32,16 @@ pub mod ffi2 {
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial_ref_method(self: &D);
+        fn c_take_trivial_mut_ref_method(self: &mut D);
         fn c_take_trivial(d: D);
         fn c_take_trivial_ns_ptr(g: UniquePtr<G>);
         fn c_take_trivial_ns_ref(g: &G);
         fn c_take_trivial_ns(g: G);
         fn c_take_opaque_ptr(e: UniquePtr<E>);
         fn c_take_opaque_ref(e: &E);
+        fn c_take_opaque_ref_method(self: &E);
+        fn c_take_opaque_mut_ref_method(self: Pin<&mut E>);
         fn c_take_opaque_ns_ptr(e: UniquePtr<F>);
         fn c_take_opaque_ns_ref(e: &F);
         fn c_return_trivial_ptr() -> UniquePtr<D>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index ca2bb6a..cd367d8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -548,6 +548,18 @@ void c_take_trivial_ref(const D &d) {
   }
 }
 
+void D::c_take_trivial_ref_method() const {
+  if (d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void D::c_take_trivial_mut_ref_method() {
+  if (d == 30) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_trivial(D d) {
   if (d.d == 30) {
     cxx_test_suite_set_correct();
@@ -590,6 +602,18 @@ void c_take_opaque_ref(const E &e) {
   }
 }
 
+void E::c_take_opaque_ref_method() const {
+  if (e == 40 && e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void E::c_take_opaque_mut_ref_method() {
+  if (e == 40 && e_str == "hello") {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_opaque_ns_ref(const ::F::F &f) {
   if (f.f == 40 && f.f_str == "hello") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 355406d..fba176c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -61,11 +61,15 @@ private:
 
 struct D {
   uint64_t d;
+  void c_take_trivial_ref_method() const;
+  void c_take_trivial_mut_ref_method();
 };
 
 struct E {
   uint64_t e;
   std::string e_str;
+  void c_take_opaque_ref_method() const;
+  void c_take_opaque_mut_ref_method();
 };
 
 enum COwnedEnum {
diff --git a/tests/test.rs b/tests/test.rs
index 165ae50..c825e24 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -267,10 +267,14 @@ fn test_rust_name_attribute() {
 
 #[test]
 fn test_extern_trivial() {
-    let d = ffi2::c_return_trivial();
+    let mut d = ffi2::c_return_trivial();
     check!(ffi2::c_take_trivial_ref(&d));
+    check!(d.c_take_trivial_ref_method());
+    check!(d.c_take_trivial_mut_ref_method());
     check!(ffi2::c_take_trivial(d));
-    let d = ffi2::c_return_trivial_ptr();
+    let mut d = ffi2::c_return_trivial_ptr();
+    check!(d.c_take_trivial_ref_method());
+    check!(d.c_take_trivial_mut_ref_method());
     check!(ffi2::c_take_trivial_ptr(d));
     cxx::UniquePtr::new(ffi2::D { d: 42 });
     let d = ffi2::ns_c_return_trivial();
@@ -286,8 +290,10 @@ fn test_extern_trivial() {
 
 #[test]
 fn test_extern_opaque() {
-    let e = ffi2::c_return_opaque_ptr();
+    let mut e = ffi2::c_return_opaque_ptr();
     check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
+    check!(e.c_take_opaque_ref_method());
+    check!(e.pin_mut().c_take_opaque_mut_ref_method());
     check!(ffi2::c_take_opaque_ptr(e));
 
     let f = ffi2::c_return_ns_opaque_ptr();
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 0a56dd4..4bcce1b 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -22,6 +22,18 @@ error: needs a cxx::ExternType impl in order to be used as a field of `S`
 10 |         type C;
    |         ^^^^^^
 
+error: needs a cxx::ExternType impl in order to be used as an argument of `f`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a return value of `f`
+  --> $DIR/by_value_not_supported.rs:10:9
+   |
+10 |         type C;
+   |         ^^^^^^
+
 error: passing opaque C++ type by value is not supported
   --> $DIR/by_value_not_supported.rs:16:14
    |
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 32d5cfc..91a7caa 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -1,28 +1,46 @@
-error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:5:19
   |
 5 |         fn f(arg: &mut Opaque);
   |                   ^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:8:17
   |
 8 |         fn s(s: &mut CxxString);
   |                 ^^^^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>>
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>> or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:9:17
   |
 9 |         fn v(v: &mut CxxVector<u8>);
   |                 ^^^^^^^^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of f
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of g
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of h
+ --> $DIR/pin_mut_opaque.rs:4:9
+  |
+4 |         type Opaque;
+  |         ^^^^^^^^^^^
+
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:6:14
   |
 6 |         fn g(&mut self);
   |              ^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use `self: Pin<&mut Opaque>`
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
  --> $DIR/pin_mut_opaque.rs:7:20
   |
 7 |         fn h(self: &mut Opaque);

From b725d5a933d41190aec995eb1b38e57af82426f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 04:29:47 +0000
Subject: [PATCH 1748/2232] Touch up PR 550


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4b95613..89e6ddd 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1,13 +1,14 @@
+use crate::gen::block::Block;
 use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
+use crate::syntax::types::TrivialReason;
 use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
     Type, Types, Var,
 };
-use crate::{gen::block::Block, syntax::types::TrivialReason};
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 5ea59cf..d1cccf0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -6,7 +6,8 @@ use crate::syntax::{
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::{collections::BTreeMap as Map, fmt::Display};
+use std::collections::BTreeMap as Map;
+use std::fmt::Display;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,
@@ -186,7 +187,7 @@ impl<'a> Types<'a> {
                     let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
                         if let Type::Ident(ident) = &field.ty {
-                            insist_extern_types_are_trivial(&ident, reason);
+                            insist_extern_types_are_trivial(ident, reason);
                         }
                     }
                 }
@@ -194,13 +195,13 @@ impl<'a> Types<'a> {
                     let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
                         if let Type::Ident(ident) = &arg.ty {
-                            insist_extern_types_are_trivial(&ident, reason);
+                            insist_extern_types_are_trivial(ident, reason);
                         }
                     }
                     if let Some(ret) = &efn.ret {
                         let reason = TrivialReason::FunctionReturn(efn);
                         if let Type::Ident(ident) = &ret {
-                            insist_extern_types_are_trivial(&ident, reason);
+                            insist_extern_types_are_trivial(ident, reason);
                         }
                     }
                 }
@@ -212,13 +213,13 @@ impl<'a> Types<'a> {
                 Type::RustBox(ty) => {
                     let reason = TrivialReason::BoxTarget;
                     if let Type::Ident(ident) = &ty.inner {
-                        insist_extern_types_are_trivial(&ident, reason);
+                        insist_extern_types_are_trivial(ident, reason);
                     }
                 }
                 Type::RustVec(ty) => {
                     let reason = TrivialReason::VecElement;
                     if let Type::Ident(ident) = &ty.inner {
-                        insist_extern_types_are_trivial(&ident, reason);
+                        insist_extern_types_are_trivial(ident, reason);
                     }
                 }
                 _ => {}
@@ -237,7 +238,7 @@ impl<'a> Types<'a> {
                         if let Type::Ref(reff) = &arg.ty {
                             if reff.mutable && !reff.pinned {
                                 if let Type::Ident(ident) = &reff.inner {
-                                    insist_extern_types_are_trivial(&ident, reason);
+                                    insist_extern_types_are_trivial(ident, reason);
                                 }
                             }
                         }

From d0a6c0b575df23865279ae043d7fea12d053d32b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 04:37:56 +0000
Subject: [PATCH 1749/2232] Condense name of unpinned mutable arg trivial reason


---

diff --git a/syntax/types.rs b/syntax/types.rs
index d1cccf0..c07ab17 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -228,7 +228,7 @@ impl<'a> Types<'a> {
         for api in apis {
             match api {
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let reason = TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn);
+                    let reason = TrivialReason::UnpinnedMutArg(efn);
                     if let Some(receiver) = &efn.receiver {
                         if receiver.mutable && !receiver.pinned {
                             insist_extern_types_are_trivial(&receiver.ty, reason);
@@ -333,7 +333,7 @@ pub enum TrivialReason<'a> {
     FunctionReturn(&'a ExternFn),
     BoxTarget,
     VecElement,
-    UnpinnedMutableReferenceFunctionArgument(&'a ExternFn),
+    UnpinnedMutArg(&'a ExternFn),
 }
 
 impl<'a> TrivialReason<'a> {
@@ -356,7 +356,7 @@ impl<'a> Display for TrivialReason<'a> {
             }
             TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
             TrivialReason::VecElement => write!(f, "a Vec<...> element"),
-            TrivialReason::UnpinnedMutableReferenceFunctionArgument(efn) => write!(
+            TrivialReason::UnpinnedMutArg(efn) => write!(
                 f,
                 "a non-pinned mutable reference argument of {}",
                 efn.name.rust

From 93fcfa401f7b8f5054821c4d965672f1f22ce59f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 04:38:20 +0000
Subject: [PATCH 1750/2232] Rearrange trivial reason detection


---

diff --git a/syntax/types.rs b/syntax/types.rs
index c07ab17..fa027eb 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -184,23 +184,23 @@ impl<'a> Types<'a> {
         for api in apis {
             match api {
                 Api::Struct(strct) => {
-                    let reason = TrivialReason::StructField(strct);
                     for field in &strct.fields {
                         if let Type::Ident(ident) = &field.ty {
+                            let reason = TrivialReason::StructField(strct);
                             insist_extern_types_are_trivial(ident, reason);
                         }
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let reason = TrivialReason::FunctionArgument(efn);
                     for arg in &efn.args {
                         if let Type::Ident(ident) = &arg.ty {
+                            let reason = TrivialReason::FunctionArgument(efn);
                             insist_extern_types_are_trivial(ident, reason);
                         }
                     }
                     if let Some(ret) = &efn.ret {
-                        let reason = TrivialReason::FunctionReturn(efn);
                         if let Type::Ident(ident) = &ret {
+                            let reason = TrivialReason::FunctionReturn(efn);
                             insist_extern_types_are_trivial(ident, reason);
                         }
                     }
@@ -211,14 +211,14 @@ impl<'a> Types<'a> {
         for ty in &all {
             match ty {
                 Type::RustBox(ty) => {
-                    let reason = TrivialReason::BoxTarget;
                     if let Type::Ident(ident) = &ty.inner {
+                        let reason = TrivialReason::BoxTarget;
                         insist_extern_types_are_trivial(ident, reason);
                     }
                 }
                 Type::RustVec(ty) => {
-                    let reason = TrivialReason::VecElement;
                     if let Type::Ident(ident) = &ty.inner {
+                        let reason = TrivialReason::VecElement;
                         insist_extern_types_are_trivial(ident, reason);
                     }
                 }
@@ -228,9 +228,9 @@ impl<'a> Types<'a> {
         for api in apis {
             match api {
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    let reason = TrivialReason::UnpinnedMutArg(efn);
                     if let Some(receiver) = &efn.receiver {
                         if receiver.mutable && !receiver.pinned {
+                            let reason = TrivialReason::UnpinnedMutArg(efn);
                             insist_extern_types_are_trivial(&receiver.ty, reason);
                         }
                     }
@@ -238,6 +238,7 @@ impl<'a> Types<'a> {
                         if let Type::Ref(reff) = &arg.ty {
                             if reff.mutable && !reff.pinned {
                                 if let Type::Ident(ident) = &reff.inner {
+                                    let reason = TrivialReason::UnpinnedMutArg(efn);
                                     insist_extern_types_are_trivial(ident, reason);
                                 }
                             }

From ee20544e01f75ceae26588b9531f7cfeaaa032f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 04:41:32 +0000
Subject: [PATCH 1751/2232] Merge trivial detection loops over function apis


---

diff --git a/syntax/types.rs b/syntax/types.rs
index fa027eb..173610d 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -192,10 +192,27 @@ impl<'a> Types<'a> {
                     }
                 }
                 Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                    if let Some(receiver) = &efn.receiver {
+                        if receiver.mutable && !receiver.pinned {
+                            let reason = TrivialReason::UnpinnedMutArg(efn);
+                            insist_extern_types_are_trivial(&receiver.ty, reason);
+                        }
+                    }
                     for arg in &efn.args {
-                        if let Type::Ident(ident) = &arg.ty {
-                            let reason = TrivialReason::FunctionArgument(efn);
-                            insist_extern_types_are_trivial(ident, reason);
+                        match &arg.ty {
+                            Type::Ident(ident) => {
+                                let reason = TrivialReason::FunctionArgument(efn);
+                                insist_extern_types_are_trivial(ident, reason);
+                            }
+                            Type::Ref(ty) => {
+                                if ty.mutable && !ty.pinned {
+                                    if let Type::Ident(ident) = &ty.inner {
+                                        let reason = TrivialReason::UnpinnedMutArg(efn);
+                                        insist_extern_types_are_trivial(ident, reason);
+                                    }
+                                }
+                            }
+                            _ => {}
                         }
                     }
                     if let Some(ret) = &efn.ret {
@@ -225,29 +242,6 @@ impl<'a> Types<'a> {
                 _ => {}
             }
         }
-        for api in apis {
-            match api {
-                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    if let Some(receiver) = &efn.receiver {
-                        if receiver.mutable && !receiver.pinned {
-                            let reason = TrivialReason::UnpinnedMutArg(efn);
-                            insist_extern_types_are_trivial(&receiver.ty, reason);
-                        }
-                    }
-                    for arg in &efn.args {
-                        if let Type::Ref(reff) = &arg.ty {
-                            if reff.mutable && !reff.pinned {
-                                if let Type::Ident(ident) = &reff.inner {
-                                    let reason = TrivialReason::UnpinnedMutArg(efn);
-                                    insist_extern_types_are_trivial(ident, reason);
-                                }
-                            }
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
 
         let mut types = Types {
             all,

From 0634b1f28caaead0902027a775c9017e55d6495d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 05:12:11 +0000
Subject: [PATCH 1752/2232] Extract trivial extern type alias detection to module


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 89e6ddd..bf60432 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -4,7 +4,7 @@ use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
-use crate::syntax::types::TrivialReason;
+use crate::syntax::trivial::TrivialReason;
 use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
     Type, Types, Var,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 31c88c9..4cedc28 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -22,6 +22,7 @@ pub mod set;
 pub mod symbol;
 mod tokens;
 mod toposort;
+pub mod trivial;
 pub mod types;
 
 use self::discriminant::Discriminant;
diff --git a/syntax/trivial.rs b/syntax/trivial.rs
new file mode 100644
index 0000000..7a77937
--- /dev/null
+++ b/syntax/trivial.rs
@@ -0,0 +1,131 @@
+use crate::syntax::set::OrderedSet as Set;
+use crate::syntax::{Api, Enum, ExternFn, ExternType, RustName, Struct, Type};
+use proc_macro2::Ident;
+use std::collections::BTreeMap as Map;
+use std::fmt::Display;
+
+#[derive(Copy, Clone)]
+pub enum TrivialReason<'a> {
+    StructField(&'a Struct),
+    FunctionArgument(&'a ExternFn),
+    FunctionReturn(&'a ExternFn),
+    BoxTarget,
+    VecElement,
+    UnpinnedMutArg(&'a ExternFn),
+}
+
+pub fn required_trivial_reasons<'a>(
+    apis: &'a [Api],
+    all: &Set<&'a Type>,
+    structs: &Map<&'a Ident, &'a Struct>,
+    enums: &Map<&'a Ident, &'a Enum>,
+    cxx: &Set<&'a Ident>,
+) -> Map<&'a Ident, Vec<TrivialReason<'a>>> {
+    let mut required_trivial = Map::new();
+
+    let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
+        if cxx.contains(&ident.rust)
+            && !structs.contains_key(&ident.rust)
+            && !enums.contains_key(&ident.rust)
+        {
+            required_trivial
+                .entry(&ident.rust)
+                .or_insert_with(Vec::new)
+                .push(reason);
+        }
+    };
+
+    for api in apis {
+        match api {
+            Api::Struct(strct) => {
+                for field in &strct.fields {
+                    if let Type::Ident(ident) = &field.ty {
+                        let reason = TrivialReason::StructField(strct);
+                        insist_extern_types_are_trivial(ident, reason);
+                    }
+                }
+            }
+            Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+                if let Some(receiver) = &efn.receiver {
+                    if receiver.mutable && !receiver.pinned {
+                        let reason = TrivialReason::UnpinnedMutArg(efn);
+                        insist_extern_types_are_trivial(&receiver.ty, reason);
+                    }
+                }
+                for arg in &efn.args {
+                    match &arg.ty {
+                        Type::Ident(ident) => {
+                            let reason = TrivialReason::FunctionArgument(efn);
+                            insist_extern_types_are_trivial(ident, reason);
+                        }
+                        Type::Ref(ty) => {
+                            if ty.mutable && !ty.pinned {
+                                if let Type::Ident(ident) = &ty.inner {
+                                    let reason = TrivialReason::UnpinnedMutArg(efn);
+                                    insist_extern_types_are_trivial(ident, reason);
+                                }
+                            }
+                        }
+                        _ => {}
+                    }
+                }
+                if let Some(ret) = &efn.ret {
+                    if let Type::Ident(ident) = &ret {
+                        let reason = TrivialReason::FunctionReturn(efn);
+                        insist_extern_types_are_trivial(ident, reason);
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    for ty in all {
+        match ty {
+            Type::RustBox(ty) => {
+                if let Type::Ident(ident) = &ty.inner {
+                    let reason = TrivialReason::BoxTarget;
+                    insist_extern_types_are_trivial(ident, reason);
+                }
+            }
+            Type::RustVec(ty) => {
+                if let Type::Ident(ident) = &ty.inner {
+                    let reason = TrivialReason::VecElement;
+                    insist_extern_types_are_trivial(ident, reason);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    required_trivial
+}
+
+impl<'a> TrivialReason<'a> {
+    pub fn describe_in_context(&self, ety: &ExternType) -> String {
+        match self {
+            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
+            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
+            _ => self.to_string(),
+        }
+    }
+}
+
+impl<'a> Display for TrivialReason<'a> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
+            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
+            TrivialReason::FunctionReturn(efn) => {
+                write!(f, "a return value of `{}`", efn.name.rust)
+            }
+            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
+            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
+            TrivialReason::UnpinnedMutArg(efn) => write!(
+                f,
+                "a non-pinned mutable reference argument of {}",
+                efn.name.rust
+            ),
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 173610d..1056854 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,13 +1,13 @@
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
+use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
+    toposort, Api, Enum, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
 use std::collections::BTreeMap as Map;
-use std::fmt::Display;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,
@@ -168,80 +168,8 @@ impl<'a> Types<'a> {
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
         // which is declared subsequently.
-        let mut required_trivial: Map<_, Vec<_>> = Map::new();
-
-        let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
-            if cxx.contains(&ident.rust)
-                && !structs.contains_key(&ident.rust)
-                && !enums.contains_key(&ident.rust)
-            {
-                required_trivial
-                    .entry(&ident.rust)
-                    .or_default()
-                    .push(reason);
-            }
-        };
-        for api in apis {
-            match api {
-                Api::Struct(strct) => {
-                    for field in &strct.fields {
-                        if let Type::Ident(ident) = &field.ty {
-                            let reason = TrivialReason::StructField(strct);
-                            insist_extern_types_are_trivial(ident, reason);
-                        }
-                    }
-                }
-                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                    if let Some(receiver) = &efn.receiver {
-                        if receiver.mutable && !receiver.pinned {
-                            let reason = TrivialReason::UnpinnedMutArg(efn);
-                            insist_extern_types_are_trivial(&receiver.ty, reason);
-                        }
-                    }
-                    for arg in &efn.args {
-                        match &arg.ty {
-                            Type::Ident(ident) => {
-                                let reason = TrivialReason::FunctionArgument(efn);
-                                insist_extern_types_are_trivial(ident, reason);
-                            }
-                            Type::Ref(ty) => {
-                                if ty.mutable && !ty.pinned {
-                                    if let Type::Ident(ident) = &ty.inner {
-                                        let reason = TrivialReason::UnpinnedMutArg(efn);
-                                        insist_extern_types_are_trivial(ident, reason);
-                                    }
-                                }
-                            }
-                            _ => {}
-                        }
-                    }
-                    if let Some(ret) = &efn.ret {
-                        if let Type::Ident(ident) = &ret {
-                            let reason = TrivialReason::FunctionReturn(efn);
-                            insist_extern_types_are_trivial(ident, reason);
-                        }
-                    }
-                }
-                _ => {}
-            }
-        }
-        for ty in &all {
-            match ty {
-                Type::RustBox(ty) => {
-                    if let Type::Ident(ident) = &ty.inner {
-                        let reason = TrivialReason::BoxTarget;
-                        insist_extern_types_are_trivial(ident, reason);
-                    }
-                }
-                Type::RustVec(ty) => {
-                    if let Type::Ident(ident) = &ty.inner {
-                        let reason = TrivialReason::VecElement;
-                        insist_extern_types_are_trivial(ident, reason);
-                    }
-                }
-                _ => {}
-            }
-        }
+        let required_trivial =
+            trivial::required_trivial_reasons(apis, &all, &structs, &enums, &cxx);
 
         let mut types = Types {
             all,
@@ -321,45 +249,6 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
     }
 }
 
-#[derive(Copy, Clone)]
-pub enum TrivialReason<'a> {
-    StructField(&'a Struct),
-    FunctionArgument(&'a ExternFn),
-    FunctionReturn(&'a ExternFn),
-    BoxTarget,
-    VecElement,
-    UnpinnedMutArg(&'a ExternFn),
-}
-
-impl<'a> TrivialReason<'a> {
-    pub fn describe_in_context(&self, ety: &ExternType) -> String {
-        match self {
-            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
-            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
-            _ => self.to_string(),
-        }
-    }
-}
-
-impl<'a> Display for TrivialReason<'a> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
-            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
-            TrivialReason::FunctionReturn(efn) => {
-                write!(f, "a return value of `{}`", efn.name.rust)
-            }
-            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
-            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
-            TrivialReason::UnpinnedMutArg(efn) => write!(
-                f,
-                "a non-pinned mutable reference argument of {}",
-                efn.name.rust
-            ),
-        }
-    }
-}
-
 fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
     let msg = format!("the name `{}` is defined multiple times", ident);
     cx.error(sp, msg);

From 0286de80117915ce8c6f1913d61bbd80acf885ee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 06:00:20 +0000
Subject: [PATCH 1753/2232] Clean up type name in IsRelocatable static assertion message


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index bf60432..434ca17 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -412,8 +412,8 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialRea
         writeln!(
             out,
             "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
-            id,
-            reason
+            id.trim_start_matches("::"),
+            reason,
         );
     }
 }

From ee0ccbe4cd61caee7d8510ebe611a974841416ec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:05:55 +0000
Subject: [PATCH 1754/2232] Focus pin mut opaque message on Pin suggestion


In common usage the Pin<&mut T> is going to be the right fix most of the
time. In all of these cases the user is *also* going to receive a
suggestion to implement ExternType. That suggestion will appear pointing
to the opaque extern `type` item.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 65c0288..32d147b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -188,7 +188,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
             cx.error(
                 ty,
                 format!(
-                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}> or declare the type Trivial in a cxx::ExternType impl",
+                    "mutable reference to C++ type requires a pin -- use Pin<&mut {}>",
                     requires_pin,
                 ),
             );
@@ -380,7 +380,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             cx.error(
                 span,
                 format!(
-                    "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>` or declare the type Trivial in a cxx::ExternType impl",
+                    "mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut {}>`",
                     receiver.ty.rust,
                 ),
             );
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 91a7caa..2de4264 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -1,16 +1,16 @@
-error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque> or declare the type Trivial in a cxx::ExternType impl
+error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque>
  --> $DIR/pin_mut_opaque.rs:5:19
   |
 5 |         fn f(arg: &mut Opaque);
   |                   ^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString> or declare the type Trivial in a cxx::ExternType impl
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString>
  --> $DIR/pin_mut_opaque.rs:8:17
   |
 8 |         fn s(s: &mut CxxString);
   |                 ^^^^^^^^^^^^^^
 
-error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>> or declare the type Trivial in a cxx::ExternType impl
+error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>>
  --> $DIR/pin_mut_opaque.rs:9:17
   |
 9 |         fn v(v: &mut CxxVector<u8>);
@@ -34,13 +34,13 @@ error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable 
 4 |         type Opaque;
   |         ^^^^^^^^^^^
 
-error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>`
  --> $DIR/pin_mut_opaque.rs:6:14
   |
 6 |         fn g(&mut self);
   |              ^^^^^^^^^
 
-error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` or declare the type Trivial in a cxx::ExternType impl
+error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>`
  --> $DIR/pin_mut_opaque.rs:7:20
   |
 7 |         fn h(self: &mut Opaque);

From 5b1d863c1eb7397a51c5805e58a57aff57b09358 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:13:35 +0000
Subject: [PATCH 1755/2232] Join trivial reasons in one message


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 434ca17..315fb35 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -4,10 +4,10 @@ use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
-use crate::syntax::trivial::TrivialReason;
+use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
-    Type, Types, Var,
+    Type, TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
@@ -119,7 +119,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     for api in apis {
         if let Api::TypeAlias(ety) = api {
             if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
-                check_trivial_extern_type(out, &ety.name, reasons)
+                check_trivial_extern_type(out, ety, reasons)
             }
         }
     }
@@ -370,7 +370,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialReason]) {
+fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[TrivialReason]) {
     // NOTE: The following static assertion is 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:
@@ -404,18 +404,16 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialRea
     //    + struct rust::IsRelocatable<MyType> : std::true_type {};
     //
 
-    let id = id.to_fully_qualified();
+    let id = alias.name.to_fully_qualified();
     out.builtin.relocatable = true;
-    for reason in reasons {
-        writeln!(out, "static_assert(");
-        writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
-        writeln!(
-            out,
-            "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
-            id.trim_start_matches("::"),
-            reason,
-        );
-    }
+    writeln!(out, "static_assert(");
+    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
+    writeln!(
+        out,
+        "    \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");",
+        id.trim_start_matches("::"),
+        trivial::as_what(&alias.name, reasons),
+    );
 }
 
 fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
diff --git a/syntax/check.rs b/syntax/check.rs
index 32d147b..d0b0ba0 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,8 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
-    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref,
+    Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -325,14 +325,11 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     }
 
     if let Some(reasons) = cx.types.required_trivial.get(&ety.name.rust) {
-        for reason in reasons {
-            let what = reason.describe_in_context(&ety);
-            let msg = format!(
-                "needs a cxx::ExternType impl in order to be used as {}",
-                what,
-            );
-            cx.error(ety, msg);
-        }
+        let msg = format!(
+            "needs a cxx::ExternType impl in order to be used as {}",
+            trivial::as_what(&ety.name, reasons),
+        );
+        cx.error(ety, msg);
     }
 }
 
diff --git a/syntax/set.rs b/syntax/set.rs
index 0618564..0df5f87 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -50,11 +50,21 @@ mod ordered {
         }
     }
 
+    impl<'a, T> OrderedSet<&'a T> {
+        pub fn is_empty(&self) -> bool {
+            self.vec.is_empty()
+        }
+
+        pub fn iter(&self) -> Iter<'_, 'a, T> {
+            Iter(self.vec.iter())
+        }
+    }
+
     impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
         type Item = &'a T;
         type IntoIter = Iter<'s, 'a, T>;
         fn into_iter(self) -> Self::IntoIter {
-            Iter(self.vec.iter())
+            self.iter()
         }
     }
 }
diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index 7a77937..85184d8 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -1,8 +1,8 @@
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Enum, ExternFn, ExternType, RustName, Struct, Type};
+use crate::syntax::{Api, Enum, ExternFn, Pair, RustName, Struct, Type};
 use proc_macro2::Ident;
 use std::collections::BTreeMap as Map;
-use std::fmt::Display;
+use std::fmt::{self, Display};
 
 #[derive(Copy, Clone)]
 pub enum TrivialReason<'a> {
@@ -101,31 +101,146 @@ pub fn required_trivial_reasons<'a>(
     required_trivial
 }
 
-impl<'a> TrivialReason<'a> {
-    pub fn describe_in_context(&self, ety: &ExternType) -> String {
-        match self {
-            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
-            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
-            _ => self.to_string(),
+// Context:
+// "type {type} should be trivially move constructible and trivially destructible in C++ to be used as {what} in Rust"
+// "needs a cxx::ExternType impl in order to be used as {what}"
+pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display + 'a {
+    struct Description<'a> {
+        name: &'a Pair,
+        reasons: &'a [TrivialReason<'a>],
+    }
+
+    impl<'a> Display for Description<'a> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            let mut field_of = Set::new();
+            let mut argument_of = Set::new();
+            let mut return_of = Set::new();
+            let mut box_target = false;
+            let mut vec_element = false;
+            let mut unpinned_mut = Set::new();
+
+            for reason in self.reasons {
+                match reason {
+                    TrivialReason::StructField(strct) => {
+                        field_of.insert(&strct.name.rust);
+                    }
+                    TrivialReason::FunctionArgument(efn) => {
+                        argument_of.insert(&efn.name.rust);
+                    }
+                    TrivialReason::FunctionReturn(efn) => {
+                        return_of.insert(&efn.name.rust);
+                    }
+                    TrivialReason::BoxTarget => box_target = true,
+                    TrivialReason::VecElement => vec_element = true,
+                    TrivialReason::UnpinnedMutArg(efn) => {
+                        unpinned_mut.insert(&efn.name.rust);
+                    }
+                }
+            }
+
+            let mut clauses = Vec::new();
+            if !field_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "field of",
+                    set: &field_of,
+                });
+            }
+            if !argument_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "an",
+                    desc: "argument of",
+                    set: &argument_of,
+                });
+            }
+            if !return_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "return value of",
+                    set: &return_of,
+                });
+            }
+            if box_target {
+                clauses.push(Clause::Ty1 {
+                    article: "type",
+                    desc: "Box",
+                    param: self.name,
+                });
+            }
+            if vec_element {
+                clauses.push(Clause::Ty1 {
+                    article: "a",
+                    desc: "vector element in Vec",
+                    param: self.name,
+                });
+            }
+            if !unpinned_mut.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "non-pinned mutable reference argument of",
+                    set: &unpinned_mut,
+                });
+            }
+
+            for (i, clause) in clauses.iter().enumerate() {
+                if i == 0 {
+                    write!(f, "{} ", clause.article())?;
+                } else if i + 1 < clauses.len() {
+                    write!(f, ", ")?;
+                } else {
+                    write!(f, " or ")?;
+                }
+                clause.fmt(f)?;
+            }
+
+            Ok(())
         }
     }
-}
 
-impl<'a> Display for TrivialReason<'a> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
-            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
-            TrivialReason::FunctionReturn(efn) => {
-                write!(f, "a return value of `{}`", efn.name.rust)
+    enum Clause<'a> {
+        Set {
+            article: &'a str,
+            desc: &'a str,
+            set: &'a Set<&'a Ident>,
+        },
+        Ty1 {
+            article: &'a str,
+            desc: &'a str,
+            param: &'a Pair,
+        },
+    }
+
+    impl<'a> Clause<'a> {
+        fn article(&self) -> &'a str {
+            match self {
+                Clause::Set { article, .. } | Clause::Ty1 { article, .. } => article,
+            }
+        }
+
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            match self {
+                Clause::Set {
+                    article: _,
+                    desc,
+                    set,
+                } => {
+                    write!(f, "{} ", desc)?;
+                    for (i, ident) in set.iter().take(3).enumerate() {
+                        if i > 0 {
+                            write!(f, ", ")?;
+                        }
+                        write!(f, "`{}`", ident)?;
+                    }
+                    Ok(())
+                }
+                Clause::Ty1 {
+                    article: _,
+                    desc,
+                    param,
+                } => write!(f, "{}<{}>", desc, param.rust),
             }
-            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
-            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
-            TrivialReason::UnpinnedMutArg(efn) => write!(
-                f,
-                "a non-pinned mutable reference argument of {}",
-                efn.name.rust
-            ),
         }
     }
+
+    Description { name, reasons }
 }
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 4bcce1b..7288c93 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,19 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `S`
-  --> $DIR/by_value_not_supported.rs:10:9
-   |
-10 |         type C;
-   |         ^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as an argument of `f`
-  --> $DIR/by_value_not_supported.rs:10:9
-   |
-10 |         type C;
-   |         ^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a return value of `f`
+error: needs a cxx::ExternType impl in order to be used as a field of `S`, argument of `f` or return value of `f`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 2de4264..53e651e 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -16,19 +16,7 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<..
 9 |         fn v(v: &mut CxxVector<u8>);
   |                 ^^^^^^^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of f
- --> $DIR/pin_mut_opaque.rs:4:9
-  |
-4 |         type Opaque;
-  |         ^^^^^^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of g
- --> $DIR/pin_mut_opaque.rs:4:9
-  |
-4 |         type Opaque;
-  |         ^^^^^^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of h
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of `f`, `g`, `h`
  --> $DIR/pin_mut_opaque.rs:4:9
   |
 4 |         type Opaque;

From 8a01b9d1a1cc0a60fa4b2024275fc761c7ec8acf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:22:48 +0000
Subject: [PATCH 1756/2232] Merge pull request #587 from dtolnay/trivial


Join trivial reasons in one message
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 434ca17..315fb35 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -4,10 +4,10 @@ use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::symbol::Symbol;
-use crate::syntax::trivial::TrivialReason;
+use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
     derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
-    Type, Types, Var,
+    Type, TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
 use std::collections::{HashMap, HashSet};
@@ -119,7 +119,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     for api in apis {
         if let Api::TypeAlias(ety) = api {
             if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
-                check_trivial_extern_type(out, &ety.name, reasons)
+                check_trivial_extern_type(out, ety, reasons)
             }
         }
     }
@@ -370,7 +370,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     }
 }
 
-fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialReason]) {
+fn check_trivial_extern_type(out: &mut OutFile, alias: &TypeAlias, reasons: &[TrivialReason]) {
     // NOTE: The following static assertion is 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:
@@ -404,18 +404,16 @@ fn check_trivial_extern_type(out: &mut OutFile, id: &Pair, reasons: &[TrivialRea
     //    + struct rust::IsRelocatable<MyType> : std::true_type {};
     //
 
-    let id = id.to_fully_qualified();
+    let id = alias.name.to_fully_qualified();
     out.builtin.relocatable = true;
-    for reason in reasons {
-        writeln!(out, "static_assert(");
-        writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
-        writeln!(
-            out,
-            "    \"type {} is not move constructible and trivially destructible in C++ yet is used as a trivial type in Rust ({})\");",
-            id.trim_start_matches("::"),
-            reason,
-        );
-    }
+    writeln!(out, "static_assert(");
+    writeln!(out, "    ::rust::IsRelocatable<{}>::value,", id);
+    writeln!(
+        out,
+        "    \"type {} should be trivially move constructible and trivially destructible in C++ to be used as {} in Rust\");",
+        id.trim_start_matches("::"),
+        trivial::as_what(&alias.name, reasons),
+    );
 }
 
 fn write_struct_operator_decls<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
diff --git a/syntax/check.rs b/syntax/check.rs
index 32d147b..d0b0ba0 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,8 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
-    error, ident, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
-    SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref,
+    Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -325,14 +325,11 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     }
 
     if let Some(reasons) = cx.types.required_trivial.get(&ety.name.rust) {
-        for reason in reasons {
-            let what = reason.describe_in_context(&ety);
-            let msg = format!(
-                "needs a cxx::ExternType impl in order to be used as {}",
-                what,
-            );
-            cx.error(ety, msg);
-        }
+        let msg = format!(
+            "needs a cxx::ExternType impl in order to be used as {}",
+            trivial::as_what(&ety.name, reasons),
+        );
+        cx.error(ety, msg);
     }
 }
 
diff --git a/syntax/set.rs b/syntax/set.rs
index 0618564..0df5f87 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -50,11 +50,21 @@ mod ordered {
         }
     }
 
+    impl<'a, T> OrderedSet<&'a T> {
+        pub fn is_empty(&self) -> bool {
+            self.vec.is_empty()
+        }
+
+        pub fn iter(&self) -> Iter<'_, 'a, T> {
+            Iter(self.vec.iter())
+        }
+    }
+
     impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
         type Item = &'a T;
         type IntoIter = Iter<'s, 'a, T>;
         fn into_iter(self) -> Self::IntoIter {
-            Iter(self.vec.iter())
+            self.iter()
         }
     }
 }
diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index 7a77937..85184d8 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -1,8 +1,8 @@
 use crate::syntax::set::OrderedSet as Set;
-use crate::syntax::{Api, Enum, ExternFn, ExternType, RustName, Struct, Type};
+use crate::syntax::{Api, Enum, ExternFn, Pair, RustName, Struct, Type};
 use proc_macro2::Ident;
 use std::collections::BTreeMap as Map;
-use std::fmt::Display;
+use std::fmt::{self, Display};
 
 #[derive(Copy, Clone)]
 pub enum TrivialReason<'a> {
@@ -101,31 +101,146 @@ pub fn required_trivial_reasons<'a>(
     required_trivial
 }
 
-impl<'a> TrivialReason<'a> {
-    pub fn describe_in_context(&self, ety: &ExternType) -> String {
-        match self {
-            TrivialReason::BoxTarget => format!("Box<{}>", ety.name.rust),
-            TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
-            _ => self.to_string(),
+// Context:
+// "type {type} should be trivially move constructible and trivially destructible in C++ to be used as {what} in Rust"
+// "needs a cxx::ExternType impl in order to be used as {what}"
+pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display + 'a {
+    struct Description<'a> {
+        name: &'a Pair,
+        reasons: &'a [TrivialReason<'a>],
+    }
+
+    impl<'a> Display for Description<'a> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            let mut field_of = Set::new();
+            let mut argument_of = Set::new();
+            let mut return_of = Set::new();
+            let mut box_target = false;
+            let mut vec_element = false;
+            let mut unpinned_mut = Set::new();
+
+            for reason in self.reasons {
+                match reason {
+                    TrivialReason::StructField(strct) => {
+                        field_of.insert(&strct.name.rust);
+                    }
+                    TrivialReason::FunctionArgument(efn) => {
+                        argument_of.insert(&efn.name.rust);
+                    }
+                    TrivialReason::FunctionReturn(efn) => {
+                        return_of.insert(&efn.name.rust);
+                    }
+                    TrivialReason::BoxTarget => box_target = true,
+                    TrivialReason::VecElement => vec_element = true,
+                    TrivialReason::UnpinnedMutArg(efn) => {
+                        unpinned_mut.insert(&efn.name.rust);
+                    }
+                }
+            }
+
+            let mut clauses = Vec::new();
+            if !field_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "field of",
+                    set: &field_of,
+                });
+            }
+            if !argument_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "an",
+                    desc: "argument of",
+                    set: &argument_of,
+                });
+            }
+            if !return_of.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "return value of",
+                    set: &return_of,
+                });
+            }
+            if box_target {
+                clauses.push(Clause::Ty1 {
+                    article: "type",
+                    desc: "Box",
+                    param: self.name,
+                });
+            }
+            if vec_element {
+                clauses.push(Clause::Ty1 {
+                    article: "a",
+                    desc: "vector element in Vec",
+                    param: self.name,
+                });
+            }
+            if !unpinned_mut.is_empty() {
+                clauses.push(Clause::Set {
+                    article: "a",
+                    desc: "non-pinned mutable reference argument of",
+                    set: &unpinned_mut,
+                });
+            }
+
+            for (i, clause) in clauses.iter().enumerate() {
+                if i == 0 {
+                    write!(f, "{} ", clause.article())?;
+                } else if i + 1 < clauses.len() {
+                    write!(f, ", ")?;
+                } else {
+                    write!(f, " or ")?;
+                }
+                clause.fmt(f)?;
+            }
+
+            Ok(())
         }
     }
-}
 
-impl<'a> Display for TrivialReason<'a> {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            TrivialReason::StructField(strct) => write!(f, "a field of `{}`", strct.name.rust),
-            TrivialReason::FunctionArgument(efn) => write!(f, "an argument of `{}`", efn.name.rust),
-            TrivialReason::FunctionReturn(efn) => {
-                write!(f, "a return value of `{}`", efn.name.rust)
+    enum Clause<'a> {
+        Set {
+            article: &'a str,
+            desc: &'a str,
+            set: &'a Set<&'a Ident>,
+        },
+        Ty1 {
+            article: &'a str,
+            desc: &'a str,
+            param: &'a Pair,
+        },
+    }
+
+    impl<'a> Clause<'a> {
+        fn article(&self) -> &'a str {
+            match self {
+                Clause::Set { article, .. } | Clause::Ty1 { article, .. } => article,
+            }
+        }
+
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            match self {
+                Clause::Set {
+                    article: _,
+                    desc,
+                    set,
+                } => {
+                    write!(f, "{} ", desc)?;
+                    for (i, ident) in set.iter().take(3).enumerate() {
+                        if i > 0 {
+                            write!(f, ", ")?;
+                        }
+                        write!(f, "`{}`", ident)?;
+                    }
+                    Ok(())
+                }
+                Clause::Ty1 {
+                    article: _,
+                    desc,
+                    param,
+                } => write!(f, "{}<{}>", desc, param.rust),
             }
-            TrivialReason::BoxTarget => write!(f, "in a Box<...>"),
-            TrivialReason::VecElement => write!(f, "a Vec<...> element"),
-            TrivialReason::UnpinnedMutArg(efn) => write!(
-                f,
-                "a non-pinned mutable reference argument of {}",
-                efn.name.rust
-            ),
         }
     }
+
+    Description { name, reasons }
 }
diff --git a/tests/ui/by_value_not_supported.stderr b/tests/ui/by_value_not_supported.stderr
index 4bcce1b..7288c93 100644
--- a/tests/ui/by_value_not_supported.stderr
+++ b/tests/ui/by_value_not_supported.stderr
@@ -16,19 +16,7 @@ error: using C++ string by value is not supported
 6 |         s: CxxString,
   |         ^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a field of `S`
-  --> $DIR/by_value_not_supported.rs:10:9
-   |
-10 |         type C;
-   |         ^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as an argument of `f`
-  --> $DIR/by_value_not_supported.rs:10:9
-   |
-10 |         type C;
-   |         ^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a return value of `f`
+error: needs a cxx::ExternType impl in order to be used as a field of `S`, argument of `f` or return value of `f`
   --> $DIR/by_value_not_supported.rs:10:9
    |
 10 |         type C;
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 2de4264..53e651e 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -16,19 +16,7 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<..
 9 |         fn v(v: &mut CxxVector<u8>);
   |                 ^^^^^^^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of f
- --> $DIR/pin_mut_opaque.rs:4:9
-  |
-4 |         type Opaque;
-  |         ^^^^^^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of g
- --> $DIR/pin_mut_opaque.rs:4:9
-  |
-4 |         type Opaque;
-  |         ^^^^^^^^^^^
-
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of h
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of `f`, `g`, `h`
  --> $DIR/pin_mut_opaque.rs:4:9
   |
 4 |         type Opaque;

From 133a9b978b1afa0286fcf5464a0fd5fc4b8b31a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:30:47 +0000
Subject: [PATCH 1757/2232] Recognize extern function return value as trivial reason


---

diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index 85184d8..d74bd66 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -11,7 +11,7 @@ pub enum TrivialReason<'a> {
     FunctionReturn(&'a ExternFn),
     BoxTarget,
     VecElement,
-    UnpinnedMutArg(&'a ExternFn),
+    UnpinnedMut(&'a ExternFn),
 }
 
 pub fn required_trivial_reasons<'a>(
@@ -48,7 +48,7 @@ pub fn required_trivial_reasons<'a>(
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                 if let Some(receiver) = &efn.receiver {
                     if receiver.mutable && !receiver.pinned {
-                        let reason = TrivialReason::UnpinnedMutArg(efn);
+                        let reason = TrivialReason::UnpinnedMut(efn);
                         insist_extern_types_are_trivial(&receiver.ty, reason);
                     }
                 }
@@ -61,7 +61,7 @@ pub fn required_trivial_reasons<'a>(
                         Type::Ref(ty) => {
                             if ty.mutable && !ty.pinned {
                                 if let Type::Ident(ident) = &ty.inner {
-                                    let reason = TrivialReason::UnpinnedMutArg(efn);
+                                    let reason = TrivialReason::UnpinnedMut(efn);
                                     insist_extern_types_are_trivial(ident, reason);
                                 }
                             }
@@ -70,9 +70,20 @@ pub fn required_trivial_reasons<'a>(
                     }
                 }
                 if let Some(ret) = &efn.ret {
-                    if let Type::Ident(ident) = &ret {
-                        let reason = TrivialReason::FunctionReturn(efn);
-                        insist_extern_types_are_trivial(ident, reason);
+                    match ret {
+                        Type::Ident(ident) => {
+                            let reason = TrivialReason::FunctionReturn(efn);
+                            insist_extern_types_are_trivial(ident, reason);
+                        }
+                        Type::Ref(ty) => {
+                            if ty.mutable && !ty.pinned {
+                                if let Type::Ident(ident) = &ty.inner {
+                                    let reason = TrivialReason::UnpinnedMut(efn);
+                                    insist_extern_types_are_trivial(ident, reason);
+                                }
+                            }
+                        }
+                        _ => {}
                     }
                 }
             }
@@ -132,7 +143,7 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
                     }
                     TrivialReason::BoxTarget => box_target = true,
                     TrivialReason::VecElement => vec_element = true,
-                    TrivialReason::UnpinnedMutArg(efn) => {
+                    TrivialReason::UnpinnedMut(efn) => {
                         unpinned_mut.insert(&efn.name.rust);
                     }
                 }
@@ -177,7 +188,7 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
             if !unpinned_mut.is_empty() {
                 clauses.push(Clause::Set {
                     article: "a",
-                    desc: "non-pinned mutable reference argument of",
+                    desc: "non-pinned mutable reference in signature of",
                     set: &unpinned_mut,
                 });
             }
diff --git a/tests/ui/pin_mut_opaque.stderr b/tests/ui/pin_mut_opaque.stderr
index 53e651e..95af3cd 100644
--- a/tests/ui/pin_mut_opaque.stderr
+++ b/tests/ui/pin_mut_opaque.stderr
@@ -16,7 +16,7 @@ error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<..
 9 |         fn v(v: &mut CxxVector<u8>);
   |                 ^^^^^^^^^^^^^^^^^^
 
-error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference argument of `f`, `g`, `h`
+error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference in signature of `f`, `g`, `h`
  --> $DIR/pin_mut_opaque.rs:4:9
   |
 4 |         type Opaque;

From 233c88bc8f288c18ff8a5b4b4bf753cf04828cd2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:32:28 +0000
Subject: [PATCH 1758/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 0a9f4bb..2527453 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -57,7 +57,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.7/src/**"]),
+    srcs = glob(["vendor/quote-1.0.8/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.54/src/**"]),
+    srcs = glob(["vendor/syn-1.0.55/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 1861ad9..0c9b02c 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -63,7 +63,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.7/src/**"]),
+    srcs = glob(["vendor/quote-1.0.8/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.54/src/**"]),
+    srcs = glob(["vendor/syn-1.0.55/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ba0ffaa..ed6f8a3 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -205,9 +205,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
+checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
 dependencies = [
  "proc-macro2",
 ]
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.54"
+version = "1.0.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
+checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
 dependencies = [
  "proc-macro2",
  "quote",

From c5ef01034984212b28fa3d7a9cff0bdcb771cca3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:34:59 +0000
Subject: [PATCH 1759/2232] Release 1.0.20


---

diff --git a/Cargo.toml b/Cargo.toml
index f725c26..0ad7835 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.19" # remember to update html_root_url
+version = "1.0.20" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.19", path = "macro" }
+cxxbridge-macro = { version = "=1.0.20", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.19", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.20", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.19", path = "gen/build" }
+cxx-build = { version = "=1.0.20", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index fbd28f1..2ef7780 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.19"
+version = "1.0.20"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index e83d30c..5ae0106 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.19"
+version = "1.0.20"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 7711f92..4614e3f 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.19"
+version = "1.0.20"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index d219e9b..32c0d4b 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.19"
+version = "0.7.20"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index a75c092..f31470f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.19"
+version = "1.0.20"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 2cc2766..5b64109 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.19")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.20")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ed6f8a3..8215bb7 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.19"
+version = "1.0.20"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.19"
+version = "1.0.20"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.19"
+version = "0.7.20"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.19"
+version = "1.0.20"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.19"
+version = "1.0.20"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.19"
+version = "1.0.20"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5965894ca8f2b2fa68818ef83d76ca3f81674960 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 21:58:45 +0000
Subject: [PATCH 1760/2232] Remove includes duplicated between cxx.h and cxx.cc


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 6863129..8040e2c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,13 +1,8 @@
 #include "../include/cxx.h"
-#include <algorithm>
 #include <cassert>
 #include <cstring>
-#include <exception>
 #include <iostream>
 #include <memory>
-#include <stdexcept>
-#include <type_traits>
-#include <vector>
 
 extern "C" {
 void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,

From d4fff5d951b32ec08d3b9e9a6528b1ad6caeda64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 22:04:11 +0000
Subject: [PATCH 1761/2232] Mark Vec front/back noexcept


---

diff --git a/include/cxx.h b/include/cxx.h
index fc63095..e1d7fa0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -262,13 +262,13 @@ public:
 
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
-  const T &front() const;
-  const T &back() const;
+  const T &front() const noexcept;
+  const T &back() const noexcept;
 
   T &operator[](std::size_t n) noexcept;
   T &at(std::size_t n);
-  T &front();
-  T &back();
+  T &front() noexcept;
+  T &back() noexcept;
 
   void reserve(std::size_t new_cap);
   void push_back(const T &value);
@@ -751,12 +751,12 @@ const T &Vec<T>::at(std::size_t n) const {
 }
 
 template <typename T>
-const T &Vec<T>::front() const {
+const T &Vec<T>::front() const noexcept {
   return (*this)[0];
 }
 
 template <typename T>
-const T &Vec<T>::back() const {
+const T &Vec<T>::back() const noexcept {
   return (*this)[this->size() - 1];
 }
 
@@ -775,12 +775,12 @@ T &Vec<T>::at(std::size_t n) {
 }
 
 template <typename T>
-T &Vec<T>::front() {
+T &Vec<T>::front() noexcept {
   return (*this)[0];
 }
 
 template <typename T>
-T &Vec<T>::back() {
+T &Vec<T>::back() noexcept {
   return (*this)[this->size() - 1];
 }
 

From fa5a4a6b5b1407aa608d7776a07f4ac1ae4fb170 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 22:08:08 +0000
Subject: [PATCH 1762/2232] Add debug assertions to some Vec indexing


---

diff --git a/include/cxx.h b/include/cxx.h
index e1d7fa0..79b9f54 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -1,6 +1,7 @@
 #pragma once
 #include <algorithm>
 #include <array>
+#include <cassert>
 #include <cstddef>
 #include <cstdint>
 #include <exception>
@@ -728,7 +729,7 @@ Vec<T> &Vec<T>::operator=(const Vec &other) {
 
 template <typename T>
 bool Vec<T>::empty() const noexcept {
-  return size() == 0;
+  return this->size() == 0;
 }
 
 template <typename T>
@@ -738,6 +739,7 @@ T *Vec<T>::data() noexcept {
 
 template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
+  assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
   return *reinterpret_cast<const T *>(data + n * this->stride());
 }
@@ -752,16 +754,19 @@ const T &Vec<T>::at(std::size_t n) const {
 
 template <typename T>
 const T &Vec<T>::front() const noexcept {
+  assert(!this->empty());
   return (*this)[0];
 }
 
 template <typename T>
 const T &Vec<T>::back() const noexcept {
+  assert(!this->empty());
   return (*this)[this->size() - 1];
 }
 
 template <typename T>
 T &Vec<T>::operator[](std::size_t n) noexcept {
+  assert(n < this->size());
   auto data = reinterpret_cast<char *>(this->data());
   return *reinterpret_cast<T *>(data + n * this->stride());
 }
@@ -776,11 +781,13 @@ T &Vec<T>::at(std::size_t n) {
 
 template <typename T>
 T &Vec<T>::front() noexcept {
+  assert(!this->empty());
   return (*this)[0];
 }
 
 template <typename T>
 T &Vec<T>::back() noexcept {
+  assert(!this->empty());
   return (*this)[this->size() - 1];
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 8040e2c..1958118 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -1,5 +1,4 @@
 #include "../include/cxx.h"
-#include <cassert>
 #include <cstring>
 #include <iostream>
 #include <memory>

From 2d99b00fcc2fedebe241394ecb83d66a71662432 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 22:34:35 +0000
Subject: [PATCH 1763/2232] Inline some niche RustName methods


---

diff --git a/syntax/check.rs b/syntax/check.rs
index d0b0ba0..2ac800b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -356,7 +356,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if let Some(receiver) = &efn.receiver {
         let ref span = span_for_receiver_error(receiver);
 
-        if receiver.ty.is_self() {
+        if receiver.ty.rust == "Self" {
             let mutability = match receiver.mutable {
                 true => "mut ",
                 false => "",
diff --git a/syntax/names.rs b/syntax/names.rs
index 2cc91f9..523850e 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,7 +1,6 @@
 use crate::syntax::{Namespace, Pair, RustName, 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
@@ -57,16 +56,6 @@ impl RustName {
         unsafe { &*(ident as *const Ident as *const Self) }
     }
 
-    pub fn make_self(span: Span) -> Self {
-        Self {
-            rust: Token![Self](span).into(),
-        }
-    }
-
-    pub fn is_self(&self) -> bool {
-        self.rust == "Self"
-    }
-
     pub fn span(&self) -> Span {
         self.rust.span()
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index c571132..4b3e435 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -288,8 +288,8 @@ fn parse_foreign_mod(
         for item in &mut items {
             if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                 if let Some(receiver) = &mut efn.receiver {
-                    if receiver.ty.is_self() {
-                        receiver.ty = RustName::new(single_type.rust.clone());
+                    if receiver.ty.rust == "Self" {
+                        receiver.ty.rust = single_type.rust.clone();
                     }
                 }
             }
@@ -432,7 +432,7 @@ fn parse_extern_fn(
                         lifetime: lifetime.clone(),
                         mutable: arg.mutability.is_some(),
                         var: arg.self_token,
-                        ty: RustName::make_self(arg.self_token.span),
+                        ty: RustName::new(Ident::new("Self", arg.self_token.span)),
                         shorthand: true,
                         pin_tokens: None,
                         mutability: arg.mutability,

From dee9fa3853d4b073ad7defe77834ce197a941a4a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 22:40:50 +0000
Subject: [PATCH 1764/2232] Simplify Pair to fully qualified


---

diff --git a/syntax/names.rs b/syntax/names.rs
index 523850e..586c017 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -32,19 +32,17 @@ impl Pair {
     }
 
     pub fn to_fully_qualified(&self) -> String {
-        format!("::{}", self.join("::"))
+        let mut fully_qualified = String::new();
+        for segment in self.iter_all_segments() {
+            fully_qualified += "::";
+            fully_qualified += &segment.to_string();
+        }
+        fully_qualified
     }
 
     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 RustName {

From 20cc2d35bdd480e1bd881ba50b48094c8e0386cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:01:07 +0000
Subject: [PATCH 1765/2232] Expose Pair construction only from differing idents


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 1f4fc5d..c6c7921 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -125,12 +125,13 @@ mod tests {
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
         let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
+        let ident = Ident::new(ident, Span::call_site());
         Api::CxxType(ExternType {
             lang: Lang::Rust,
             doc: Doc::new(),
             derives: Vec::new(),
             type_token: Token![type](Span::call_site()),
-            name: Pair::new(ns, Ident::new(ident, Span::call_site())),
+            name: Pair::new(ns, ident.clone(), ident),
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/syntax/names.rs b/syntax/names.rs
index 586c017..4aed656 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -3,27 +3,11 @@ use proc_macro2::{Ident, Span};
 use std::iter;
 
 impl Pair {
-    // Use this constructor when the item can't have a different name in Rust
-    // and C++.
-    pub fn new(namespace: Namespace, ident: Ident) -> Self {
+    pub fn new(namespace: Namespace, cxx: Ident, rust: Ident) -> Self {
         Self {
             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++.
-    pub fn new_from_differing_names(
-        namespace: Namespace,
-        cxx_ident: Ident,
-        rust_ident: Ident,
-    ) -> Self {
-        Self {
-            namespace,
-            cxx: cxx_ident,
-            rust: rust_ident,
+            cxx,
+            rust,
         }
     }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 4b3e435..e6cfd04 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -106,7 +106,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         doc,
         derives,
         struct_token: item.struct_token,
-        name: Pair::new(namespace, item.ident),
+        name: Pair::new(namespace, item.ident.clone(), item.ident),
         brace_token: named_fields.brace_token,
         fields,
     }))
@@ -192,7 +192,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         doc,
         derives,
         enum_token,
-        name: Pair::new(namespace, item.ident),
+        name: Pair::new(namespace, item.ident.clone(), item.ident),
         brace_token,
         variants,
         repr,
@@ -351,7 +351,7 @@ fn parse_extern_type(
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident),
+        name: Pair::new(namespace, ident.clone(), ident),
         colon_token: None,
         bounds: Vec::new(),
         semi_token,
@@ -483,7 +483,7 @@ fn parse_extern_fn(
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let name = Pair::new_from_differing_names(
+    let name = Pair::new(
         namespace,
         cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
         rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
@@ -586,7 +586,7 @@ fn parse_type_alias(
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident),
+        name: Pair::new(namespace, ident.clone(), ident),
         eq_token,
         ty,
         semi_token,
@@ -658,7 +658,7 @@ fn parse_extern_type_bounded(
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident),
+        name: Pair::new(namespace, ident.clone(), ident),
         colon_token: Some(colon_token),
         bounds,
         semi_token,

From 7cd9fec04c276f01125fccb328e6079fa17e24b0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:03:23 +0000
Subject: [PATCH 1766/2232] Touch up Pair and RustName construction for consistency


---

diff --git a/syntax/names.rs b/syntax/names.rs
index 4aed656..09169cb 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -4,7 +4,7 @@ use std::iter;
 
 impl Pair {
     pub fn new(namespace: Namespace, cxx: Ident, rust: Ident) -> Self {
-        Self {
+        Pair {
             namespace,
             cxx,
             rust,
@@ -30,12 +30,12 @@ impl Pair {
 }
 
 impl RustName {
-    pub fn new(ident: Ident) -> Self {
-        Self { rust: ident }
+    pub fn new(rust: Ident) -> Self {
+        RustName { rust }
     }
 
-    pub fn from_ref(ident: &Ident) -> &Self {
-        unsafe { &*(ident as *const Ident as *const Self) }
+    pub fn from_ref(rust: &Ident) -> &Self {
+        unsafe { &*(rust as *const Ident as *const Self) }
     }
 
     pub fn span(&self) -> Span {

From bc954d94e0afde1dedc6413e2d87132ef33f4b7c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:17:12 +0000
Subject: [PATCH 1767/2232] Defer generics errors until after attribute errors


All attribute errors are nonfatal so we might as well report them all
even if an input contains unsupported generics.

---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index e6cfd04..8110ce8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -55,18 +55,6 @@ pub fn parse_items(
 }
 
 fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
-    let generics = &item.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
-        let struct_token = item.struct_token;
-        let ident = &item.ident;
-        let where_clause = &generics.where_clause;
-        let span = quote!(#struct_token #ident #generics #where_clause);
-        return Err(Error::new_spanned(
-            span,
-            "struct with generic parameters is not supported yet",
-        ));
-    }
-
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
@@ -81,6 +69,18 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         },
     );
 
+    let generics = &item.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        let struct_token = item.struct_token;
+        let ident = &item.ident;
+        let where_clause = &generics.where_clause;
+        let span = quote!(#struct_token #ident #generics #where_clause);
+        return Err(Error::new_spanned(
+            span,
+            "struct with generic parameters is not supported yet",
+        ));
+    }
+
     let named_fields = match item.fields {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
@@ -113,18 +113,6 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
 }
 
 fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
-    let generics = &item.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
-        let enum_token = item.enum_token;
-        let ident = &item.ident;
-        let where_clause = &generics.where_clause;
-        let span = quote!(#enum_token #ident #generics #where_clause);
-        return Err(Error::new_spanned(
-            span,
-            "enums with generic parameters are not allowed",
-        ));
-    }
-
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut repr = None;
@@ -141,6 +129,18 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         },
     );
 
+    let generics = &item.generics;
+    if !generics.params.is_empty() || generics.where_clause.is_some() {
+        let enum_token = item.enum_token;
+        let ident = &item.ident;
+        let where_clause = &generics.where_clause;
+        let span = quote!(#enum_token #ident #generics #where_clause);
+        return Err(Error::new_spanned(
+            span,
+            "enums with generic parameters are not allowed",
+        ));
+    }
+
     let mut variants = Vec::new();
     let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
@@ -366,6 +366,22 @@ fn parse_extern_fn(
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
+    let mut doc = Doc::new();
+    let mut cxx_name = None;
+    let mut rust_name = None;
+    let mut namespace = namespace.clone();
+    attrs::parse(
+        cx,
+        &foreign_fn.attrs,
+        attrs::Parser {
+            doc: Some(&mut doc),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
+            namespace: Some(&mut namespace),
+            ..Default::default()
+        },
+    );
+
     let generics = &foreign_fn.sig.generics;
     if generics.where_clause.is_some()
         || generics.params.iter().any(|param| match param {
@@ -403,22 +419,6 @@ fn parse_extern_fn(
         ));
     }
 
-    let mut doc = Doc::new();
-    let mut cxx_name = None;
-    let mut rust_name = None;
-    let mut namespace = namespace.clone();
-    attrs::parse(
-        cx,
-        &foreign_fn.attrs,
-        attrs::Parser {
-            doc: Some(&mut doc),
-            cxx_name: Some(&mut cxx_name),
-            rust_name: Some(&mut rust_name),
-            namespace: Some(&mut namespace),
-            ..Default::default()
-        },
-    );
-
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {

From ddbcb524b9398b353ab6d7bc9e4e68dab6b1643b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:38:44 +0000
Subject: [PATCH 1768/2232] Parser minor cleanup


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8110ce8..2a42f99 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -102,12 +102,16 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         fields.push(Var { ident, ty });
     }
 
+    let struct_token = item.struct_token;
+    let name = Pair::new(namespace, item.ident.clone(), item.ident);
+    let brace_token = named_fields.brace_token;
+
     Ok(Api::Struct(Struct {
         doc,
         derives,
-        struct_token: item.struct_token,
-        name: Pair::new(namespace, item.ident.clone(), item.ident),
-        brace_token: named_fields.brace_token,
+        struct_token,
+        name,
+        brace_token,
         fields,
     }))
 }
@@ -185,14 +189,15 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
-    let ident = Ident::new(repr.as_ref(), Span::call_site());
-    let repr_type = Type::Ident(RustName::new(ident));
+    let name = Pair::new(namespace, item.ident.clone(), item.ident);
+    let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
+    let repr_type = Type::Ident(RustName::new(repr_ident));
 
     Ok(Api::Enum(Enum {
         doc,
         derives,
         enum_token,
-        name: Pair::new(namespace, item.ident.clone(), item.ident),
+        name,
         brace_token,
         variants,
         repr,
@@ -309,6 +314,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
             ));
         }
     };
+
     match name.value().as_str() {
         "C++" => Ok(Lang::Cxx),
         "Rust" => Ok(Lang::Rust),
@@ -339,21 +345,25 @@ fn parse_extern_type(
             ..Default::default()
         },
     );
+
     let type_token = foreign_type.type_token;
     let ident = foreign_type.ident.clone();
+    let name = Pair::new(namespace, ident.clone(), ident);
+    let colon_token = None;
+    let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
-    let api_type = match lang {
+
+    (match lang {
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
-    };
-    api_type(ExternType {
+    })(ExternType {
         lang,
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident.clone(), ident),
-        colon_token: None,
-        bounds: Vec::new(),
+        name,
+        colon_token,
+        bounds,
         semi_token,
         trusted,
     })
@@ -394,24 +404,28 @@ fn parse_extern_fn(
             "extern function with generic parameters is not supported yet",
         ));
     }
+
     if let Some(variadic) = &foreign_fn.sig.variadic {
         return Err(Error::new_spanned(
             variadic,
             "variadic function is not supported yet",
         ));
     }
+
     if foreign_fn.sig.asyncness.is_some() {
         return Err(Error::new_spanned(
             foreign_fn,
             "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
         ));
     }
+
     if foreign_fn.sig.constness.is_some() {
         return Err(Error::new_spanned(
             foreign_fn,
             "const extern function is not supported",
         ));
     }
+
     if let Some(abi) = &foreign_fn.sig.abi {
         return Err(Error::new_spanned(
             abi,
@@ -491,12 +505,11 @@ fn parse_extern_fn(
     let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
-    let api_function = match lang {
+
+    Ok(match lang {
         Lang::Cxx => Api::CxxFunction,
         Lang::Rust => Api::RustFunction,
-    };
-
-    Ok(api_function(ExternFn {
+    }(ExternFn {
         lang,
         doc,
         name,
@@ -582,11 +595,13 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
+    let name = Pair::new(namespace, ident.clone(), ident);
+
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident.clone(), ident),
+        name,
         eq_token,
         ty,
         semi_token,
@@ -648,18 +663,19 @@ fn parse_extern_type_bounded(
         },
     );
 
-    let api_type = match lang {
+    let name = Pair::new(namespace, ident.clone(), ident);
+    let colon_token = Some(colon_token);
+
+    Ok(match lang {
         Lang::Cxx => Api::CxxType,
         Lang::Rust => Api::RustType,
-    };
-
-    Ok(api_type(ExternType {
+    }(ExternType {
         lang,
         doc,
         derives,
         type_token,
-        name: Pair::new(namespace, ident.clone(), ident),
-        colon_token: Some(colon_token),
+        name,
+        colon_token,
         bounds,
         semi_token,
         trusted,
@@ -705,11 +721,16 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         }
     }
 
+    let impl_token = imp.impl_token;
+    let negative = negative_token.is_some();
+    let ty = parse_type(&self_ty)?;
+    let brace_token = imp.brace_token;
+
     Ok(Api::Impl(Impl {
-        impl_token: imp.impl_token,
-        negative: negative_token.is_some(),
-        ty: parse_type(&self_ty)?,
-        brace_token: imp.brace_token,
+        impl_token,
+        negative,
+        ty,
+        brace_token,
         negative_token,
     }))
 }
@@ -770,20 +791,29 @@ fn parse_type(ty: &RustType) -> Result<Type> {
 }
 
 fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
+    let ampersand = ty.and_token;
+    let lifetime = ty.lifetime.clone();
+    let mutable = ty.mutability.is_some();
+    let mutability = ty.mutability;
+
     if let RustType::Slice(slice) = ty.elem.as_ref() {
         let inner = parse_type(&slice.elem)?;
+        let bracket = slice.bracket_token;
         return Ok(Type::SliceRef(Box::new(SliceRef {
-            ampersand: ty.and_token,
-            lifetime: ty.lifetime.clone(),
-            mutable: ty.mutability.is_some(),
-            bracket: slice.bracket_token,
+            ampersand,
+            lifetime,
+            mutable,
+            bracket,
             inner,
-            mutability: ty.mutability,
+            mutability,
         })));
     }
 
     let inner = parse_type(&ty.elem)?;
-    let which = match &inner {
+    let pinned = false;
+    let pin_tokens = None;
+
+    Ok(match &inner {
         Type::Ident(ident) if ident.rust == "str" => {
             if ty.mutability.is_some() {
                 return Err(Error::new_spanned(ty, "unsupported type"));
@@ -792,15 +822,14 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
             }
         }
         _ => Type::Ref,
-    };
-    Ok(which(Box::new(Ref {
-        pinned: false,
-        ampersand: ty.and_token,
-        lifetime: ty.lifetime.clone(),
-        mutable: ty.mutability.is_some(),
+    }(Box::new(Ref {
+        pinned,
+        ampersand,
+        lifetime,
+        mutable,
         inner,
-        pin_tokens: None,
-        mutability: ty.mutability,
+        pin_tokens,
+        mutability,
     })))
 }
 
@@ -878,6 +907,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
             PathArguments::Parenthesized(_) => {}
         }
     }
+
     Err(Error::new_spanned(ty, "unsupported type"))
 }
 
@@ -923,12 +953,14 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             "function pointer with lifetime parameters is not supported yet",
         ));
     }
+
     if ty.variadic.is_some() {
         return Err(Error::new_spanned(
             ty,
             "variadic function pointer is not supported yet",
         ));
     }
+
     let args = ty
         .inputs
         .iter()
@@ -942,18 +974,26 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             Ok(Var { ident, ty })
         })
         .collect::<Result<_>>()?;
+
     let mut throws_tokens = None;
     let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
+
+    let unsafety = ty.unsafety;
+    let fn_token = ty.fn_token;
+    let generics = Generics::default();
+    let receiver = None;
+    let paren_token = ty.paren_token;
+
     Ok(Type::Fn(Box::new(Signature {
-        unsafety: ty.unsafety,
-        fn_token: ty.fn_token,
-        generics: Generics::default(),
-        receiver: None,
+        unsafety,
+        fn_token,
+        generics,
+        receiver,
         args,
         ret,
         throws,
-        paren_token: ty.paren_token,
+        paren_token,
         throws_tokens,
     })))
 }
@@ -966,6 +1006,7 @@ fn parse_return_type(
         ReturnType::Default => return Ok(None),
         ReturnType::Type(_, ret) => ret.as_ref(),
     };
+
     if let RustType::Path(ty) = ret {
         let path = &ty.path;
         if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
@@ -982,6 +1023,7 @@ fn parse_return_type(
             }
         }
     }
+
     match parse_type(ret)? {
         Type::Void(_) => Ok(None),
         ty => Ok(Some(ty)),

From 6a990f8035b3e90804e31bf13ab5fa07b63eec78 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:43:08 +0000
Subject: [PATCH 1769/2232] Factor out a Pair constructor for common parser use case


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2a42f99..b229d8b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -497,11 +497,7 @@ fn parse_extern_fn(
     let throws = throws_tokens.is_some();
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
-    let name = Pair::new(
-        namespace,
-        cxx_name.unwrap_or(foreign_fn.sig.ident.clone()),
-        rust_name.unwrap_or(foreign_fn.sig.ident.clone()),
-    );
+    let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
     let semi_token = foreign_fn.semi_token;
@@ -1029,3 +1025,12 @@ fn parse_return_type(
         ty => Ok(Some(ty)),
     }
 }
+
+fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
+    let default = || default.clone();
+    Pair::new(
+        namespace,
+        cxx.unwrap_or_else(default),
+        rust.unwrap_or_else(default),
+    )
+}

From a2dfcbfde6d030ca0a9cea9af561b8684723b4bb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:46:24 +0000
Subject: [PATCH 1770/2232] Match argument order between attr parser and Pair::new


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 967d9fb..7dab263 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -11,9 +11,9 @@ pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,
     pub derives: Option<&'a mut Vec<Derive>>,
     pub repr: Option<&'a mut Option<Atom>>,
+    pub namespace: Option<&'a mut Namespace>,
     pub cxx_name: Option<&'a mut Option<Ident>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
-    pub namespace: Option<&'a mut Namespace>,
 }
 
 pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
@@ -48,6 +48,16 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("namespace") {
+            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
+                Ok(attr) => {
+                    if let Some(namespace) = &mut parser.namespace {
+                        **namespace = attr;
+                        continue;
+                    }
+                }
+                Err(err) => return cx.push(err),
+            }
         } else if attr.path.is_ident("cxx_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
                 Ok(attr) => {
@@ -68,16 +78,6 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                 }
                 Err(err) => return cx.push(err),
             }
-        } else if attr.path.is_ident("namespace") {
-            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
-                Ok(attr) => {
-                    if let Some(namespace) = &mut parser.namespace {
-                        **namespace = attr;
-                        continue;
-                    }
-                }
-                Err(err) => return cx.push(err),
-            }
         }
         return cx.error(attr, "unsupported attribute");
     }
@@ -122,6 +122,12 @@ fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
     ))
 }
 
+fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
+    input.parse::<Token![=]>()?;
+    let namespace = input.parse::<Namespace>()?;
+    Ok(namespace)
+}
+
 fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
     input.parse::<Token![=]>()?;
     if input.peek(LitStr) {
@@ -131,9 +137,3 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
         input.parse()
     }
 }
-
-fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
-    input.parse::<Token![=]>()?;
-    let namespace = input.parse::<Namespace>()?;
-    Ok(namespace)
-}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b229d8b..20f79ec 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -377,17 +377,17 @@ fn parse_extern_fn(
     namespace: &Namespace,
 ) -> Result<Api> {
     let mut doc = Doc::new();
+    let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    let mut namespace = namespace.clone();
     attrs::parse(
         cx,
         &foreign_fn.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
+            namespace: Some(&mut namespace),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
-            namespace: Some(&mut namespace),
             ..Default::default()
         },
     );

From 885be13744580bc931d84daad18b935835233d95 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:53:53 +0000
Subject: [PATCH 1771/2232] Parse cxx_name/rust_name attrs on all syntax tree nodes holding Pair


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 20f79ec..9c766ff 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -58,6 +58,8 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
+    let mut cxx_name = None;
+    let mut rust_name = None;
     attrs::parse(
         cx,
         &item.attrs,
@@ -65,6 +67,8 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
             doc: Some(&mut doc),
             derives: Some(&mut derives),
             namespace: Some(&mut namespace),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
             ..Default::default()
         },
     );
@@ -103,7 +107,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     }
 
     let struct_token = item.struct_token;
-    let name = Pair::new(namespace, item.ident.clone(), item.ident);
+    let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let brace_token = named_fields.brace_token;
 
     Ok(Api::Struct(Struct {
@@ -121,6 +125,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut derives = Vec::new();
     let mut repr = None;
     let mut namespace = namespace.clone();
+    let mut cxx_name = None;
+    let mut rust_name = None;
     attrs::parse(
         cx,
         &item.attrs,
@@ -129,6 +135,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
             derives: Some(&mut derives),
             repr: Some(&mut repr),
             namespace: Some(&mut namespace),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
             ..Default::default()
         },
     );
@@ -189,7 +197,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
-    let name = Pair::new(namespace, item.ident.clone(), item.ident);
+    let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
     let repr_type = Type::Ident(RustName::new(repr_ident));
 
@@ -335,6 +343,8 @@ fn parse_extern_type(
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
+    let mut cxx_name = None;
+    let mut rust_name = None;
     attrs::parse(
         cx,
         &foreign_type.attrs,
@@ -342,13 +352,14 @@ fn parse_extern_type(
             doc: Some(&mut doc),
             derives: Some(&mut derives),
             namespace: Some(&mut namespace),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
             ..Default::default()
         },
     );
 
     let type_token = foreign_type.type_token;
-    let ident = foreign_type.ident.clone();
-    let name = Pair::new(namespace, ident.clone(), ident);
+    let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let colon_token = None;
     let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
@@ -574,6 +585,8 @@ fn parse_type_alias(
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
+    let mut cxx_name = None;
+    let mut rust_name = None;
     attrs::parse(
         cx,
         &attrs,
@@ -581,6 +594,8 @@ fn parse_type_alias(
             doc: Some(&mut doc),
             derives: Some(&mut derives),
             namespace: Some(&mut namespace),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
             ..Default::default()
         },
     );
@@ -591,7 +606,7 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
-    let name = Pair::new(namespace, ident.clone(), ident);
+    let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
         doc,
@@ -648,6 +663,8 @@ fn parse_extern_type_bounded(
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
+    let mut cxx_name = None;
+    let mut rust_name = None;
     attrs::parse(
         cx,
         &attrs,
@@ -655,11 +672,13 @@ fn parse_extern_type_bounded(
             doc: Some(&mut doc),
             derives: Some(&mut derives),
             namespace: Some(&mut namespace),
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
             ..Default::default()
         },
     );
 
-    let name = Pair::new(namespace, ident.clone(), ident);
+    let name = pair(namespace, &ident, cxx_name, rust_name);
     let colon_token = Some(colon_token);
 
     Ok(match lang {

From c2a4c78a13ab53df4bb5718ca549ecde4e1fe116 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 21 2020 23:55:31 +0000
Subject: [PATCH 1772/2232] Inline Pair construction


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index c6c7921..abc9670 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -131,7 +131,11 @@ mod tests {
             doc: Doc::new(),
             derives: Vec::new(),
             type_token: Token![type](Span::call_site()),
-            name: Pair::new(ns, ident.clone(), ident),
+            name: Pair {
+                namespace: ns,
+                cxx: ident.clone(),
+                rust: ident,
+            },
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/syntax/names.rs b/syntax/names.rs
index 09169cb..ec93c3d 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,16 +1,8 @@
-use crate::syntax::{Namespace, Pair, RustName, Symbol, Types};
+use crate::syntax::{Pair, RustName, Symbol, Types};
 use proc_macro2::{Ident, Span};
 use std::iter;
 
 impl Pair {
-    pub fn new(namespace: Namespace, cxx: Ident, rust: Ident) -> Self {
-        Pair {
-            namespace,
-            cxx,
-            rust,
-        }
-    }
-
     pub fn to_symbol(&self) -> Symbol {
         Symbol::from_idents(self.iter_all_segments())
     }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 9c766ff..d79ba32 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1047,9 +1047,9 @@ fn parse_return_type(
 
 fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
     let default = || default.clone();
-    Pair::new(
+    Pair {
         namespace,
-        cxx.unwrap_or_else(default),
-        rust.unwrap_or_else(default),
-    )
+        cxx: cxx.unwrap_or_else(default),
+        rust: rust.unwrap_or_else(default),
+    }
 }

From 2680923a7e1731051ad9bed0a57adeb1d054055c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:07:14 +0000
Subject: [PATCH 1773/2232] Factor out variant parse logic


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d79ba32..e8bef90 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -16,6 +16,7 @@ use syn::{
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
+    Variant as RustVariant,
 };
 
 pub mod kw {
@@ -156,31 +157,10 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut variants = Vec::new();
     let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
-        match variant.fields {
-            Fields::Unit => {}
-            _ => {
-                cx.error(variant, "enums with data are not supported yet");
-                break;
-            }
+        match parse_variant(variant, &mut discriminants) {
+            Ok(variant) => variants.push(variant),
+            Err(err) => cx.push(err),
         }
-        let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
-        let try_discriminant = match &expr {
-            Some(lit) => discriminants.insert(lit),
-            None => discriminants.insert_next(),
-        };
-        let discriminant = match try_discriminant {
-            Ok(discriminant) => discriminant,
-            Err(err) => {
-                cx.error(variant, err);
-                break;
-            }
-        };
-        let expr = variant.discriminant.map(|(_, expr)| expr);
-        variants.push(Variant {
-            ident: variant.ident,
-            discriminant,
-            expr,
-        });
     }
 
     let enum_token = item.enum_token;
@@ -214,6 +194,33 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     }))
 }
 
+fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> Result<Variant> {
+    match variant.fields {
+        Fields::Unit => {}
+        _ => {
+            let msg = "enums with data are not supported yet";
+            return Err(Error::new_spanned(variant, msg));
+        }
+    }
+
+    let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
+    let try_discriminant = match &expr {
+        Some(lit) => discriminants.insert(lit),
+        None => discriminants.insert_next(),
+    };
+    let discriminant = match try_discriminant {
+        Ok(discriminant) => discriminant,
+        Err(err) => return Err(Error::new_spanned(variant, err)),
+    };
+    let expr = variant.discriminant.map(|(_, expr)| expr);
+
+    Ok(Variant {
+        ident: variant.ident,
+        discriminant,
+        expr,
+    })
+}
+
 fn parse_foreign_mod(
     cx: &mut Errors,
     foreign_mod: ItemForeignMod,

From d25033c28e7ef3b370a50cdad407f1fd7d3afe11 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:24:19 +0000
Subject: [PATCH 1774/2232] Work around clippy needless_update lint on attrs::Parser


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 7dab263..18e92e2 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -14,6 +14,11 @@ pub struct Parser<'a> {
     pub namespace: Option<&'a mut Namespace>,
     pub cxx_name: Option<&'a mut Option<Ident>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
+
+    // Suppress clippy needless_update lint ("struct update has no effect, all
+    // the fields in the struct have already been specified") when preemptively
+    // writing `..Default::default()`.
+    pub(crate) _more: (),
 }
 
 pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {

From b11c9ef640005db08b81e329ba751110e45baaae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:26:22 +0000
Subject: [PATCH 1775/2232] Show intended usage example on attrs::Parser


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 18e92e2..2bc03ea 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -6,6 +6,24 @@ use proc_macro2::Ident;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
+// Intended usage:
+//
+//     let mut doc = Doc::new();
+//     let mut cxx_name = None;
+//     let mut rust_name = None;
+//     /* ... */
+//     attrs::parse(
+//         cx,
+//         &item.attrs,
+//         attrs::Parser {
+//             doc: Some(&mut doc),
+//             cxx_name: Some(&mut cxx_name),
+//             rust_name: Some(&mut rust_name),
+//             /* ... */
+//             ..Default::default()
+//         },
+//     );
+//
 #[derive(Default)]
 pub struct Parser<'a> {
     pub doc: Option<&'a mut Doc>,

From e6f6214c002b6ce94142002f2d6b043b83cabf7d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:26:41 +0000
Subject: [PATCH 1776/2232] Store enum variant name as Pair


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 315fb35..7da60ac 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -342,7 +342,7 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
-        writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
+        writeln!(out, "  {} = {},", variant.name.cxx, variant.discriminant);
     }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
@@ -365,7 +365,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.name.cxx, variant.ident, variant.discriminant,
+            enm.name.cxx, variant.name.cxx, variant.discriminant,
         );
     }
 }
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 5e9b8a9..5b8f259 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -230,7 +230,7 @@ fn enum_clone(enm: &Enum, span: Span) -> TokenStream {
 fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
     let variants = enm.variants.iter().map(|variant| {
-        let variant = &variant.ident;
+        let variant = &variant.name.rust;
         let name = variant.to_string();
         quote_spanned! {span=>
             #ident::#variant => formatter.write_str(#name),
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 433eca6..40c1161 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -268,7 +268,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
-        let variant_ident = &variant.ident;
+        let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
diff --git a/syntax/ident.rs b/syntax/ident.rs
index aaf7832..47aae14 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -32,7 +32,7 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             Api::Enum(enm) => {
                 check_ident(cx, &enm.name);
                 for variant in &enm.variants {
-                    check(cx, &variant.ident);
+                    check(cx, &variant.name.rust);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4cedc28..7f8fd9a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -159,7 +159,7 @@ pub struct Receiver {
 }
 
 pub struct Variant {
-    pub ident: Ident,
+    pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e8bef90..8429d80 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -212,10 +212,12 @@ fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> R
         Ok(discriminant) => discriminant,
         Err(err) => return Err(Error::new_spanned(variant, err)),
     };
+
+    let name = pair(Namespace::ROOT, &variant.ident, None, None);
     let expr = variant.discriminant.map(|(_, expr)| expr);
 
     Ok(Variant {
-        ident: variant.ident,
+        name,
         discriminant,
         expr,
     })

From 6bf9ef4749dc530c4cdcea18f9433de46fd16c72 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:26:41 +0000
Subject: [PATCH 1777/2232] Parse cxx_name and rust_name attributes on enum variants


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8429d80..f72253a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -157,7 +157,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut variants = Vec::new();
     let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
-        match parse_variant(variant, &mut discriminants) {
+        match parse_variant(cx, variant, &mut discriminants) {
             Ok(variant) => variants.push(variant),
             Err(err) => cx.push(err),
         }
@@ -194,7 +194,23 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     }))
 }
 
-fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> Result<Variant> {
+fn parse_variant(
+    cx: &mut Errors,
+    variant: RustVariant,
+    discriminants: &mut DiscriminantSet,
+) -> Result<Variant> {
+    let mut cxx_name = None;
+    let mut rust_name = None;
+    attrs::parse(
+        cx,
+        &variant.attrs,
+        attrs::Parser {
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
+            ..Default::default()
+        },
+    );
+
     match variant.fields {
         Fields::Unit => {}
         _ => {
@@ -213,7 +229,7 @@ fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> R
         Err(err) => return Err(Error::new_spanned(variant, err)),
     };
 
-    let name = pair(Namespace::ROOT, &variant.ident, None, None);
+    let name = pair(Namespace::ROOT, &variant.ident, cxx_name, rust_name);
     let expr = variant.discriminant.map(|(_, expr)| expr);
 
     Ok(Variant {

From f2217180911948fbcb2a41bc6b9f22552a5ce2c0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:47:26 +0000
Subject: [PATCH 1778/2232] Add some use of enum variant rename in tests


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2c065d9..7504704 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -30,7 +30,8 @@ pub mod ffi {
     enum Enum {
         AVal,
         BVal = 2020,
-        CVal,
+        #[cxx_name = "CVal"]
+        LastVal,
     }
 
     #[namespace = "A"]
@@ -197,7 +198,9 @@ pub mod ffi {
     #[repr(u32)]
     #[derive(Hash)]
     enum COwnedEnum {
+        #[cxx_name = "CVAL1"]
         CVal1,
+        #[cxx_name = "CVAL2"]
         CVal2,
     }
 
@@ -473,7 +476,7 @@ fn r_return_enum(n: u32) -> ffi::Enum {
     } else if n <= 2020 {
         ffi::Enum::BVal
     } else {
-        ffi::Enum::CVal
+        ffi::Enum::LastVal
     }
 }
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fba176c..51ab51d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -73,8 +73,8 @@ struct E {
 };
 
 enum COwnedEnum {
-  CVal1,
-  CVal2,
+  CVAL1,
+  CVAL2,
 };
 
 size_t c_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index c825e24..60bf1bd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -76,7 +76,7 @@ fn test_c_return() {
         _ => assert!(false),
     }
     match ffi::c_return_enum(2021) {
-        enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
+        enm @ ffi::Enum::LastVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_ns_enum(0) {
@@ -236,7 +236,7 @@ fn test_c_ns_method_calls() {
 fn test_enum_representations() {
     assert_eq!(0, ffi::Enum::AVal.repr);
     assert_eq!(2020, ffi::Enum::BVal.repr);
-    assert_eq!(2021, ffi::Enum::CVal.repr);
+    assert_eq!(2021, ffi::Enum::LastVal.repr);
 }
 
 #[test]

From abf03e77035811658be696396693bf0fc8d00cf2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 00:58:22 +0000
Subject: [PATCH 1779/2232] Merge pull request #588 from dtolnay/variant


Support cxx_name/rust_name attributes on enum variants
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 315fb35..7da60ac 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -342,7 +342,7 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
-        writeln!(out, "  {} = {},", variant.ident, variant.discriminant);
+        writeln!(out, "  {} = {},", variant.name.cxx, variant.discriminant);
     }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
@@ -365,7 +365,7 @@ fn check_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
         writeln!(
             out,
             ">({}::{}) == {}, \"disagrees with the value in #[cxx::bridge]\");",
-            enm.name.cxx, variant.ident, variant.discriminant,
+            enm.name.cxx, variant.name.cxx, variant.discriminant,
         );
     }
 }
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 5e9b8a9..5b8f259 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -230,7 +230,7 @@ fn enum_clone(enm: &Enum, span: Span) -> TokenStream {
 fn enum_debug(enm: &Enum, span: Span) -> TokenStream {
     let ident = &enm.name.rust;
     let variants = enm.variants.iter().map(|variant| {
-        let variant = &variant.ident;
+        let variant = &variant.name.rust;
         let name = variant.to_string();
         quote_spanned! {span=>
             #ident::#variant => formatter.write_str(#name),
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 433eca6..40c1161 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -268,7 +268,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
-        let variant_ident = &variant.ident;
+        let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
             pub const #variant_ident: Self = #ident { repr: #discriminant };
diff --git a/syntax/ident.rs b/syntax/ident.rs
index aaf7832..47aae14 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -32,7 +32,7 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             Api::Enum(enm) => {
                 check_ident(cx, &enm.name);
                 for variant in &enm.variants {
-                    check(cx, &variant.ident);
+                    check(cx, &variant.name.rust);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4cedc28..7f8fd9a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -159,7 +159,7 @@ pub struct Receiver {
 }
 
 pub struct Variant {
-    pub ident: Ident,
+    pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index e8bef90..f72253a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -157,7 +157,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut variants = Vec::new();
     let mut discriminants = DiscriminantSet::new(repr);
     for variant in item.variants {
-        match parse_variant(variant, &mut discriminants) {
+        match parse_variant(cx, variant, &mut discriminants) {
             Ok(variant) => variants.push(variant),
             Err(err) => cx.push(err),
         }
@@ -194,7 +194,23 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     }))
 }
 
-fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> Result<Variant> {
+fn parse_variant(
+    cx: &mut Errors,
+    variant: RustVariant,
+    discriminants: &mut DiscriminantSet,
+) -> Result<Variant> {
+    let mut cxx_name = None;
+    let mut rust_name = None;
+    attrs::parse(
+        cx,
+        &variant.attrs,
+        attrs::Parser {
+            cxx_name: Some(&mut cxx_name),
+            rust_name: Some(&mut rust_name),
+            ..Default::default()
+        },
+    );
+
     match variant.fields {
         Fields::Unit => {}
         _ => {
@@ -212,10 +228,12 @@ fn parse_variant(variant: RustVariant, discriminants: &mut DiscriminantSet) -> R
         Ok(discriminant) => discriminant,
         Err(err) => return Err(Error::new_spanned(variant, err)),
     };
+
+    let name = pair(Namespace::ROOT, &variant.ident, cxx_name, rust_name);
     let expr = variant.discriminant.map(|(_, expr)| expr);
 
     Ok(Variant {
-        ident: variant.ident,
+        name,
         discriminant,
         expr,
     })
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2c065d9..7504704 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -30,7 +30,8 @@ pub mod ffi {
     enum Enum {
         AVal,
         BVal = 2020,
-        CVal,
+        #[cxx_name = "CVal"]
+        LastVal,
     }
 
     #[namespace = "A"]
@@ -197,7 +198,9 @@ pub mod ffi {
     #[repr(u32)]
     #[derive(Hash)]
     enum COwnedEnum {
+        #[cxx_name = "CVAL1"]
         CVal1,
+        #[cxx_name = "CVAL2"]
         CVal2,
     }
 
@@ -473,7 +476,7 @@ fn r_return_enum(n: u32) -> ffi::Enum {
     } else if n <= 2020 {
         ffi::Enum::BVal
     } else {
-        ffi::Enum::CVal
+        ffi::Enum::LastVal
     }
 }
 
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index fba176c..51ab51d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -73,8 +73,8 @@ struct E {
 };
 
 enum COwnedEnum {
-  CVal1,
-  CVal2,
+  CVAL1,
+  CVAL2,
 };
 
 size_t c_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index c825e24..60bf1bd 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -76,7 +76,7 @@ fn test_c_return() {
         _ => assert!(false),
     }
     match ffi::c_return_enum(2021) {
-        enm @ ffi::Enum::CVal => assert_eq!(2021, enm.repr),
+        enm @ ffi::Enum::LastVal => assert_eq!(2021, enm.repr),
         _ => assert!(false),
     }
     match ffi::c_return_ns_enum(0) {
@@ -236,7 +236,7 @@ fn test_c_ns_method_calls() {
 fn test_enum_representations() {
     assert_eq!(0, ffi::Enum::AVal.repr);
     assert_eq!(2020, ffi::Enum::BVal.repr);
-    assert_eq!(2021, ffi::Enum::CVal.repr);
+    assert_eq!(2021, ffi::Enum::LastVal.repr);
 }
 
 #[test]

From 767e00d195d0d10bce1aa3378beb34f885560875 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 01:23:33 +0000
Subject: [PATCH 1780/2232] Add mutable indexing for CxxVector


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7da60ac..f7587ce 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1737,10 +1737,10 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, ::std::size_t pos) noexcept {{",
+        "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
         inner, instance, inner,
     );
-    writeln!(out, "  return &s[pos];");
+    writeln!(out, "  return &(*s)[pos];");
     writeln!(out, "}}");
 
     out.include.memory = true;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 40c1161..15562ac 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1229,10 +1229,10 @@ fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Type
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> *const Self {
+            unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
+                    fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
                 }
                 __get_unchecked(v, pos)
             }
diff --git a/src/cxx.cc b/src/cxx.cc
index 1958118..b171583 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -408,9 +408,9 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(           \
-      const std::vector<CXX_TYPE> &s, std::size_t pos) noexcept {              \
-    return &s[pos];                                                            \
+  CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(                 \
+      std::vector<CXX_TYPE> *s, std::size_t pos) noexcept {                    \
+    return &(*s)[pos];                                                         \
   }                                                                            \
   void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d4bd711..c8b9460 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -9,6 +9,7 @@ use core::fmt::{self, Debug, Display};
 use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
+use core::pin::Pin;
 use core::ptr;
 use core::slice;
 
@@ -61,6 +62,16 @@ where
         }
     }
 
+    /// Returns a pinned mutable reference to an element at the given position,
+    /// or `None` if out of bounds.
+    pub fn get_mut(&mut self, pos: usize) -> Option<Pin<&mut T>> {
+        if pos < self.len() {
+            Some(unsafe { self.get_unchecked_mut(pos) })
+        } else {
+            None
+        }
+    }
+
     /// Returns a reference to an element without doing bounds checking.
     ///
     /// This is generally not recommended, use with caution! Calling this method
@@ -68,11 +79,29 @@ where
     /// reference is not used.
     ///
     /// Matches the behavior of C++
-    /// [std::vector\<T\>::operator\[\]][operator_at].
+    /// [std::vector\<T\>::operator\[\] const][operator_at].
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
-        &*T::__get_unchecked(self, pos)
+        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
+        let ptr = T::__get_unchecked(this, pos) as *const T;
+        &*ptr
+    }
+
+    /// Returns a pinned mutable reference to an element without doing bounds
+    /// checking.
+    ///
+    /// This is generally not recommended, use with caution! Calling this method
+    /// with an out-of-bounds index is undefined behavior even if the resulting
+    /// reference is not used.
+    ///
+    /// Matches the behavior of C++
+    /// [std::vector\<T\>::operator\[\]][operator_at].
+    ///
+    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
+    pub unsafe fn get_unchecked_mut(&mut self, pos: usize) -> Pin<&mut T> {
+        let ptr = T::__get_unchecked(self, pos);
+        Pin::new_unchecked(&mut *ptr)
     }
 
     /// Returns a slice to the underlying contiguous array of elements.
@@ -90,7 +119,8 @@ where
             // which upholds the invariants.
             &[]
         } else {
-            let ptr = unsafe { T::__get_unchecked(self, 0) };
+            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
+            let ptr = unsafe { T::__get_unchecked(this, 0) };
             unsafe { slice::from_raw_parts(ptr, len) }
         }
     }
@@ -186,7 +216,7 @@ where
 pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
-    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> *const Self;
+    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -209,11 +239,11 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
+            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                 extern "C" {
                     attr! {
                         #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
-                        fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
+                        fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
                     }
                 }
                 __get_unchecked(v, pos)

From cbf0964a7c5cec25cd15739bf0d764e057882f26 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 01:32:20 +0000
Subject: [PATCH 1781/2232] Merge pull request #589 from dtolnay/vecgetmut


Add mutable indexing for CxxVector
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7da60ac..f7587ce 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1737,10 +1737,10 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
     writeln!(
         out,
-        "const {} *cxxbridge1$std$vector${}$get_unchecked(const ::std::vector<{}> &s, ::std::size_t pos) noexcept {{",
+        "{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
         inner, instance, inner,
     );
-    writeln!(out, "  return &s[pos];");
+    writeln!(out, "  return &(*s)[pos];");
     writeln!(out, "}}");
 
     out.include.memory = true;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 40c1161..15562ac 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1229,10 +1229,10 @@ fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Type
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> *const Self {
+            unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: &::cxx::CxxVector<#elem>, _: usize) -> *const #elem;
+                    fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
                 }
                 __get_unchecked(v, pos)
             }
diff --git a/src/cxx.cc b/src/cxx.cc
index 1958118..b171583 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -408,9 +408,9 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       const std::vector<CXX_TYPE> &s) noexcept {                               \
     return s.size();                                                           \
   }                                                                            \
-  const CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(           \
-      const std::vector<CXX_TYPE> &s, std::size_t pos) noexcept {              \
-    return &s[pos];                                                            \
+  CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked(                 \
+      std::vector<CXX_TYPE> *s, std::size_t pos) noexcept {                    \
+    return &(*s)[pos];                                                         \
   }                                                                            \
   void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null(                    \
       std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d4bd711..c8b9460 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -9,6 +9,7 @@ use core::fmt::{self, Debug, Display};
 use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
+use core::pin::Pin;
 use core::ptr;
 use core::slice;
 
@@ -61,6 +62,16 @@ where
         }
     }
 
+    /// Returns a pinned mutable reference to an element at the given position,
+    /// or `None` if out of bounds.
+    pub fn get_mut(&mut self, pos: usize) -> Option<Pin<&mut T>> {
+        if pos < self.len() {
+            Some(unsafe { self.get_unchecked_mut(pos) })
+        } else {
+            None
+        }
+    }
+
     /// Returns a reference to an element without doing bounds checking.
     ///
     /// This is generally not recommended, use with caution! Calling this method
@@ -68,11 +79,29 @@ where
     /// reference is not used.
     ///
     /// Matches the behavior of C++
-    /// [std::vector\<T\>::operator\[\]][operator_at].
+    /// [std::vector\<T\>::operator\[\] const][operator_at].
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
     pub unsafe fn get_unchecked(&self, pos: usize) -> &T {
-        &*T::__get_unchecked(self, pos)
+        let this = self as *const CxxVector<T> as *mut CxxVector<T>;
+        let ptr = T::__get_unchecked(this, pos) as *const T;
+        &*ptr
+    }
+
+    /// Returns a pinned mutable reference to an element without doing bounds
+    /// checking.
+    ///
+    /// This is generally not recommended, use with caution! Calling this method
+    /// with an out-of-bounds index is undefined behavior even if the resulting
+    /// reference is not used.
+    ///
+    /// Matches the behavior of C++
+    /// [std::vector\<T\>::operator\[\]][operator_at].
+    ///
+    /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
+    pub unsafe fn get_unchecked_mut(&mut self, pos: usize) -> Pin<&mut T> {
+        let ptr = T::__get_unchecked(self, pos);
+        Pin::new_unchecked(&mut *ptr)
     }
 
     /// Returns a slice to the underlying contiguous array of elements.
@@ -90,7 +119,8 @@ where
             // which upholds the invariants.
             &[]
         } else {
-            let ptr = unsafe { T::__get_unchecked(self, 0) };
+            let this = self as *const CxxVector<T> as *mut CxxVector<T>;
+            let ptr = unsafe { T::__get_unchecked(this, 0) };
             unsafe { slice::from_raw_parts(ptr, len) }
         }
     }
@@ -186,7 +216,7 @@ where
 pub unsafe trait VectorElement: Sized {
     const __NAME: &'static dyn Display;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
-    unsafe fn __get_unchecked(v: &CxxVector<Self>, pos: usize) -> *const Self;
+    unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
     fn __unique_ptr_null() -> *mut c_void;
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
@@ -209,11 +239,11 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
-            unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> *const $ty {
+            unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                 extern "C" {
                     attr! {
                         #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")]
-                        fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
+                        fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty;
                     }
                 }
                 __get_unchecked(v, pos)

From 0d52717355a8ee1c530b8d20801faf6f0a333ed7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 01:35:24 +0000
Subject: [PATCH 1782/2232] Simplify CxxVector iterator next method


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c8b9460..191b643 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -158,9 +158,9 @@ where
     type Item = &'a T;
 
     fn next(&mut self) -> Option<Self::Item> {
-        let next = self.v.get(self.index);
-        self.index += next.is_some() as usize;
-        next
+        let next = self.v.get(self.index)?;
+        self.index += 1;
+        Some(next)
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {

From 26a5292598a29f08d3a62df5acd7fac614a19d97 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 01:39:18 +0000
Subject: [PATCH 1783/2232] Mutable iterator for CxxVector


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 191b643..4bfb7a2 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -129,6 +129,11 @@ where
     pub fn iter(&self) -> Iter<T> {
         Iter { v: self, index: 0 }
     }
+
+    /// Returns an iterator over elements of type `Pin<&mut T>`.
+    pub fn iter_mut(&mut self) -> IterMut<T> {
+        IterMut { v: self, index: 0 }
+    }
 }
 
 /// Iterator over elements of a `CxxVector` by shared reference.
@@ -180,6 +185,60 @@ where
 
 impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
 
+/// Iterator over elements of a `CxxVector` by pinned mutable reference.
+///
+/// The iterator element type is `Pin<&'a mut T>`.
+pub struct IterMut<'a, T> {
+    v: &'a mut CxxVector<T>,
+    index: usize,
+}
+
+impl<'a, T> IntoIterator for &'a mut CxxVector<T>
+where
+    T: VectorElement,
+{
+    type Item = Pin<&'a mut T>;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter_mut()
+    }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T>
+where
+    T: VectorElement,
+{
+    type Item = Pin<&'a mut T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let next = self.v.get_mut(self.index)?;
+        self.index += 1;
+        // Extend lifetime to allow simultaneous holding of nonoverlapping
+        // elements, analogous to slice::split_first_mut.
+        unsafe {
+            let ptr = Pin::into_inner_unchecked(next) as *mut T;
+            Some(Pin::new_unchecked(&mut *ptr))
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T>
+where
+    T: VectorElement,
+{
+    fn len(&self) -> usize {
+        self.v.len() - self.index
+    }
+}
+
+impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
+
 impl<T> Debug for CxxVector<T>
 where
     T: VectorElement + Debug,

From 8e5af76cf09d7fc5adf0c67f81dedbdfc5dca354 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 22 2020 01:45:59 +0000
Subject: [PATCH 1784/2232] Merge pull request #591 from dtolnay/vecitermut


Mutable iterator for CxxVector
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 191b643..4bfb7a2 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -129,6 +129,11 @@ where
     pub fn iter(&self) -> Iter<T> {
         Iter { v: self, index: 0 }
     }
+
+    /// Returns an iterator over elements of type `Pin<&mut T>`.
+    pub fn iter_mut(&mut self) -> IterMut<T> {
+        IterMut { v: self, index: 0 }
+    }
 }
 
 /// Iterator over elements of a `CxxVector` by shared reference.
@@ -180,6 +185,60 @@ where
 
 impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
 
+/// Iterator over elements of a `CxxVector` by pinned mutable reference.
+///
+/// The iterator element type is `Pin<&'a mut T>`.
+pub struct IterMut<'a, T> {
+    v: &'a mut CxxVector<T>,
+    index: usize,
+}
+
+impl<'a, T> IntoIterator for &'a mut CxxVector<T>
+where
+    T: VectorElement,
+{
+    type Item = Pin<&'a mut T>;
+    type IntoIter = IterMut<'a, T>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter_mut()
+    }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T>
+where
+    T: VectorElement,
+{
+    type Item = Pin<&'a mut T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let next = self.v.get_mut(self.index)?;
+        self.index += 1;
+        // Extend lifetime to allow simultaneous holding of nonoverlapping
+        // elements, analogous to slice::split_first_mut.
+        unsafe {
+            let ptr = Pin::into_inner_unchecked(next) as *mut T;
+            Some(Pin::new_unchecked(&mut *ptr))
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.len();
+        (len, Some(len))
+    }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T>
+where
+    T: VectorElement,
+{
+    fn len(&self) -> usize {
+        self.v.len() - self.index
+    }
+}
+
+impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {}
+
 impl<T> Debug for CxxVector<T>
 where
     T: VectorElement + Debug,

From 10956b541a0899f1a45e1cb191f9fa4babb7a45f Mon Sep 17 00:00:00 2001
From: Mike Fairhurst <mfairhurst@fb.com>
Date: Dec 22 2020 20:11:27 +0000
Subject: [PATCH 1785/2232] Support opaque Rust types in a rust::Slice


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 1de36e1..b79fc29 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -136,6 +136,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_DETAIL_SIZEOF");
 
     out.begin_block(Block::Namespace("detail"));
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index f7587ce..541c569 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1253,6 +1253,7 @@ impl<'a> ToMangled for UniquePtr<'a> {
 }
 
 fn write_generic_instantiations(out: &mut OutFile) {
+
     if out.header {
         return;
     }
@@ -1311,6 +1312,14 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_cxx_vector(out, inner);
                 }
             }
+        } else if let Type::Ident(name) = ty {
+            if Atom::from(&name.rust).is_none()
+                && (!out.types.aliases.contains_key(&name.rust)
+                    || out.types.explicit_impls.contains(ty))
+            {
+                out.next_section();
+                write_rust_sizeof_extern(out, name);
+            }
         }
     }
     out.end_block(Block::ExternC);
@@ -1336,6 +1345,13 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_rust_vec_impl(out, inner);
                 }
             }
+        } else if let Type::Ident(name) = ty {
+            if Atom::from(&name.rust).is_none()
+                && (!out.types.aliases.contains_key(&name.rust)
+                    || out.types.explicit_impls.contains(ty))
+            {
+                write_rust_sizeof_impl(out, name);
+            }
         }
     }
     out.end_block(Block::InlineNamespace("cxxbridge1"));
@@ -1366,6 +1382,36 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "#endif // CXXBRIDGE1_RUST_BOX_{}", instance);
 }
 
+fn write_rust_sizeof_extern(out: &mut OutFile, element: &RustName) {
+    let instance = element.to_mangled(out.types);
+
+    writeln!(out, "#ifndef CXX_BRIDGE_RUST_SIZEOF_{}", instance);
+    writeln!(out, "#define CXX_BRIDGE_RUST_SIZEOF_{}", instance);
+    writeln!(out, "::std::size_t cxxbridge1$rust_sizeof${}() noexcept;", instance);
+    writeln!(out, "#endif // CXX_BRIDGE_RUST_SIZEOF_{}", instance);
+
+}
+
+fn write_rust_sizeof_impl(out: &mut OutFile, element: &RustName) {
+    let instance = element.to_mangled(out.types);
+    let typename = element.to_typename(out.types);
+
+    writeln!(out, "#ifndef CXX_BRIDGE_RUST_SIZEOF_IMPL_{}", instance);
+    writeln!(out, "#define CXX_BRIDGE_RUST_SIZEOF_IMPL_{}", instance);
+    out.begin_block(Block::Namespace("detail"));
+    writeln!(out, "template<>");
+    writeln!(out, "::std::size_t rust_sizeof<{}>() {{", typename);
+    writeln!( out, "  return cxxbridge1$rust_sizeof${}();", instance);
+    writeln!(out, " }}");
+    writeln!(out, "template<>");
+    writeln!(out, "::std::size_t rust_sizeof<const {}>() {{", typename);
+    writeln!( out, "  return cxxbridge1$rust_sizeof${}();", instance);
+    writeln!(out, " }}");
+    out.end_block(Block::Namespace("detail"));
+    writeln!(out, "#endif // CXX_BRIDGE_RUST_SIZEOF_IMPL_{}", instance);
+
+}
+
 fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
@@ -1409,11 +1455,6 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
         "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
         instance, inner,
     );
-    writeln!(
-        out,
-        "::std::size_t cxxbridge1$rust_vec${}$stride() noexcept;",
-        instance,
-    );
     writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
 }
 
@@ -1513,11 +1554,6 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
         instance,
     );
     writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "::std::size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge1$rust_vec${}$stride();", instance);
-    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
diff --git a/include/cxx.h b/include/cxx.h
index 79b9f54..2ac4361 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -30,6 +30,14 @@ template <typename T>
 class impl;
 }
 
+#ifndef CXXBRIDGE1_DETAIL_SIZEOF
+#define CXXBRIDGE1_DETAIL_SIZEOF
+namespace detail {
+template <typename T>
+std::size_t rust_sizeof();
+} // namespace detail
+#endif // CXXBRIDGE1_DETAIL_SIZEOF
+
 #ifndef CXXBRIDGE1_RUST_STRING
 #define CXXBRIDGE1_RUST_STRING
 // https://cxx.rs/binding/string.html
@@ -156,6 +164,8 @@ public:
   T *data() const noexcept;
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
+  T &operator[](std::size_t n) noexcept;
+  T &at(std::size_t n);
 
   // Important in order for System V ABI to pass in registers.
   Slice(const Slice<T> &) noexcept = default;
@@ -167,6 +177,7 @@ public:
 
 private:
   friend impl<Slice>;
+  static std::size_t stride() noexcept;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   T *ptr;
@@ -192,6 +203,7 @@ public:
 private:
   friend class Slice;
   T *pos;
+  std::size_t stride;
 };
 #endif // CXXBRIDGE1_RUST_SLICE
 
@@ -525,15 +537,36 @@ T *Slice<T>::iterator::operator->() const noexcept {
 }
 
 template <typename T>
+T &Slice<T>::operator[](std::size_t n) noexcept {
+  auto data = const_cast<char*>(reinterpret_cast<const char *>(this->data()));
+  return *reinterpret_cast<T *>(data + n * this->stride());
+}
+
+template <typename T>
+T &Slice<T>::at(std::size_t n) {
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Slice index out of range");
+  }
+  return (*this)[n];
+}
+
+template <typename T>
+size_t Slice<T>::stride() noexcept {
+  return detail::rust_sizeof<T>();
+}
+
+template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
-  ++this->pos;
+  auto data = const_cast<char*>(reinterpret_cast<const char *>(this->pos));
+  this->pos = reinterpret_cast<T *>(data + this->stride);
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
   auto ret = iterator(*this);
-  ++this->pos;
+  auto data = const_cast<char*>(reinterpret_cast<const char *>(this->pos));
+  this->pos = reinterpret_cast<T *>(data + this->stride);
   return ret;
 }
 
@@ -551,6 +584,7 @@ template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
   it.pos = this->ptr;
+  it.stride = this->stride();
   return it;
 }
 
@@ -558,6 +592,7 @@ template <typename T>
 typename Slice<T>::iterator Slice<T>::end() const noexcept {
   iterator it = this->begin();
   it.pos += this->len;
+  it.stride = this->stride();
   return it;
 }
 #endif // CXXBRIDGE1_RUST_SLICE
@@ -753,6 +788,11 @@ const T &Vec<T>::at(std::size_t n) const {
 }
 
 template <typename T>
+size_t Vec<T>::stride() noexcept {
+  return detail::rust_sizeof<T>();
+}
+
+template <typename T>
 const T &Vec<T>::front() const noexcept {
   assert(!this->empty());
   return (*this)[0];
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 15562ac..84e055a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -109,6 +109,12 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                     expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
                 }
             }
+        } else if let Type::Ident(ident) = ty {
+            let explicit_impl = types.explicit_impls.get(ty);
+            if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust)) {
+                hidden.extend(expand_rust_sizeof(ident, types));
+            }
         }
     }
 
@@ -982,6 +988,20 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     }
 }
 
+fn expand_rust_sizeof(elem: &RustName, types: &Types) -> TokenStream {
+    let link_sizeof = format!("cxxbridge1$rust_sizeof${}", elem.to_symbol(types));
+    let local_sizeof = format_ident!("{}__sizeof", elem.rust);
+
+    let span = elem.span();
+    quote_spanned! {span=>
+        #[doc(hidden)]
+        #[export_name = #link_sizeof]
+        unsafe extern "C" fn #local_sizeof() -> usize {
+            ::std::mem::size_of::<#elem>()
+        }
+    }
+}
+
 fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_prefix = format!("cxxbridge1$rust_vec${}$", elem.to_symbol(types));
     let link_new = format!("{}new", link_prefix);
@@ -991,7 +1011,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_data = format!("{}data", link_prefix);
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
-    let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem.rust);
     let local_new = format_ident!("{}new", local_prefix);
@@ -1001,7 +1020,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let local_data = format_ident!("{}data", local_prefix);
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
-    let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = elem.span();
     quote_spanned! {span=>
@@ -1042,11 +1060,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
         unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
             (*this).set_len(len);
         }
-        #[doc(hidden)]
-        #[export_name = #link_stride]
-        unsafe extern "C" fn #local_stride() -> usize {
-            ::std::mem::size_of::<#elem>()
-        }
     }
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index b171583..700edbf 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -436,6 +436,16 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
     ptr->~unique_ptr();                                                        \
   }
 
+#define RUST_SIZEOF_OPS(RUST_TYPE, CXX_TYPE)                                   \
+  template <>                                                                  \
+  size_t rust_sizeof<CXX_TYPE>() {                                             \
+    return sizeof(CXX_TYPE);                                                   \
+  }                                                                            \
+  template <>                                                                  \
+  size_t rust_sizeof<const CXX_TYPE>() {                                       \
+    return sizeof(CXX_TYPE);                                                   \
+  }                                                                            \
+
 #define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
   void cxxbridge1$rust_vec$##RUST_TYPE##$new(                                  \
       rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
@@ -450,8 +460,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
       rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept;                     \
   void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,     \
-                                                 std::size_t len) noexcept;    \
-  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
+                                                 std::size_t len) noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
@@ -482,10 +491,6 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept {                      \
     cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len);                      \
   }                                                                            \
-  template <>                                                                  \
-  std::size_t Vec<CXX_TYPE>::stride() noexcept {                               \
-    return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
-  }
 
 #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE)                                    \
   static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), "");  \
@@ -534,7 +539,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   MACRO(isize, rust::isize)                                                    \
   MACRO(string, std::string)
 
-#define FOR_EACH_RUST_VEC(MACRO)                                               \
+#define FOR_EACH_RUST_BASE_TYPE(MACRO)                                         \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
@@ -548,12 +553,15 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 
 extern "C" {
 FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
-FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
 FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
+FOR_EACH_RUST_BASE_TYPE(RUST_VEC_EXTERNS)
 } // extern "C"
 
 namespace rust {
 inline namespace cxxbridge1 {
-FOR_EACH_RUST_VEC(RUST_VEC_OPS)
+FOR_EACH_RUST_BASE_TYPE(RUST_VEC_OPS)
+namespace detail {
+FOR_EACH_RUST_BASE_TYPE(RUST_SIZEOF_OPS)
+} // namespace detail
 } // namespace cxxbridge1
 } // namespace rust
diff --git a/src/symbols/rust_sizeof.rs b/src/symbols/rust_sizeof.rs
new file mode 100644
index 0000000..b1368a0
--- /dev/null
+++ b/src/symbols/rust_sizeof.rs
@@ -0,0 +1,41 @@
+use crate::rust_string::RustString;
+use alloc::vec::Vec;
+use core::mem;
+use std::os::raw::c_char;
+
+macro_rules! rust_stride_shims {
+    ($segment:expr, $ty:ty) => {
+        const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<Vec<$ty>>());
+        const_assert_eq!(mem::align_of::<usize>(), mem::align_of::<Vec<$ty>>());
+
+        const _: () = {
+            attr! {
+                #[export_name = concat!("cxxbridge1$rust_stride$", $segment)]
+                unsafe extern "C" fn __stride() -> usize {
+                    mem::size_of::<$ty>()
+                }
+            }
+        };
+    };
+}
+
+macro_rules! rust_stride_shims_for_primitive {
+    ($ty:ident) => {
+        rust_stride_shims!(stringify!($ty), $ty);
+    };
+}
+
+rust_stride_shims_for_primitive!(bool);
+rust_stride_shims_for_primitive!(u8);
+rust_stride_shims_for_primitive!(u16);
+rust_stride_shims_for_primitive!(u32);
+rust_stride_shims_for_primitive!(u64);
+rust_stride_shims_for_primitive!(i8);
+rust_stride_shims_for_primitive!(i16);
+rust_stride_shims_for_primitive!(i32);
+rust_stride_shims_for_primitive!(i64);
+rust_stride_shims_for_primitive!(f32);
+rust_stride_shims_for_primitive!(f64);
+
+rust_stride_shims!("char", c_char);
+rust_stride_shims!("string", RustString);
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 6aa0b76..60b9cfa 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -53,12 +53,6 @@ macro_rules! rust_vec_shims {
                     (*this).repr.set_len(len);
                 }
             }
-            attr! {
-                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$stride")]
-                unsafe extern "C" fn __stride() -> usize {
-                    mem::size_of::<$ty>()
-                }
-            }
         };
     };
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 2ac800b..f43c1e2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -210,6 +210,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRef(_) => false,
+        Type::Ident(ident) => !is_opaque_cxx(cx, &ident.rust),
         element => !is_unsized(cx, element),
     };
 
@@ -217,9 +218,7 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
         let mutable = if ty.mutable { "mut " } else { "" };
         let mut msg = format!("unsupported &{}[T] element type", mutable);
         if let Type::Ident(ident) = &ty.inner {
-            if cx.types.rust.contains(&ident.rust) {
-                msg += ": opaque Rust type is not supported yet";
-            } else if is_opaque_cxx(cx, &ident.rust) {
+            if is_opaque_cxx(cx, &ident.rust) {
                 msg += ": opaque C++ type is not supported yet";
             }
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7504704..da3a09f 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -120,6 +120,8 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
+        fn c_take_slice_not_usized(s: &[Second]);
+        fn c_take_slice_not_usized_mut(s: &mut [Second]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index cd367d8..bf29f66 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -274,7 +274,19 @@ void c_take_slice_char(rust::Slice<const char> s) {
 }
 
 void c_take_slice_shared(rust::Slice<const Shared> s) {
-  if (s.size() == 2 && s.data()->z == 2020 && (s.data() + 1)->z == 2021) {
+  if (s.size() == 2 && s[0].z == 2020 && s[1].z == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_slice_not_usized(rust::Slice<const second::Second> s) {
+  if (s.size() == 2 && s[0].i == 1 && s[0].e == tests::COwnedEnum::CVAL1 && s[1].i == 2 && s[1].e == COwnedEnum::CVAL2) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+void c_take_slice_not_usized_mut(rust::Slice<second::Second> s) {
+  if (s.size() == 2 && s[0].i == 1 && s[0].e == tests::COwnedEnum::CVAL1 && s[1].i == 2 && s[1].e == COwnedEnum::CVAL2) {
     cxx_test_suite_set_correct();
   }
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 51ab51d..722ba75 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -32,6 +32,10 @@ public:
 };
 } // namespace H
 
+namespace second {
+  struct Second;
+}
+
 namespace tests {
 
 struct R;
@@ -123,6 +127,8 @@ void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
+void c_take_slice_not_usized(rust::Slice<const ::second::Second> s);
+void c_take_slice_not_usized_mut(rust::Slice<::second::Second> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 60bf1bd..ab824e1 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -125,6 +125,14 @@ fn test_c_take() {
         ffi::Shared { z: 2020 },
         ffi::Shared { z: 2021 },
     ]));
+    check!(ffi::c_take_slice_not_usized(&[
+        ffi::Second { i: 1, e: ffi::COwnedEnum::CVal1 },
+        ffi::Second { i: 2, e: ffi::COwnedEnum::CVal2 },
+    ]));
+    check!(ffi::c_take_slice_not_usized_mut(&mut [
+        ffi::Second { i: 1, e: ffi::COwnedEnum::CVal1 },
+        ffi::Second { i: 2, e: ffi::COwnedEnum::CVal2 },
+    ]));
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From c528d671ffe5fc01be9b34d4ed91f39d0a3d5056 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 23 2020 19:19:36 +0000
Subject: [PATCH 1786/2232] Update std::string example code to use cxx_name attribute


---

diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md
index 0a643c2..8345eef 100644
--- a/book/src/binding/cxxstring.md
+++ b/book/src/binding/cxxstring.md
@@ -36,24 +36,26 @@ mod ffi {
     unsafe extern "C++" {
         include!("example/include/json.h");
 
-        type json;
-        type object;
-
-        fn isNull(self: &json) -> bool;
-        fn isNumber(self: &json) -> bool;
-        fn isString(self: &json) -> bool;
-        fn isArray(self: &json) -> bool;
-        fn isObject(self: &json) -> bool;
-
-        fn getNumber(self: &json) -> f64;
-        fn getString(self: &json) -> &CxxString;
-        fn getArray(self: &json) -> &CxxVector<json>;
-        fn getObject(self: &json) -> &object;
-
-        #[cxx_name = "at"]  // https://en.cppreference.com/w/cpp/container/map/at
-        fn get<'a>(self: &'a object, key: &CxxString) -> &'a json;
-
-        fn load_config() -> UniquePtr<json>;
+        #[cxx_name = "json"]
+        type Json;
+        #[cxx_name = "object"]
+        type Object;
+
+        fn isNull(self: &Json) -> bool;
+        fn isNumber(self: &Json) -> bool;
+        fn isString(self: &Json) -> bool;
+        fn isArray(self: &Json) -> bool;
+        fn isObject(self: &Json) -> bool;
+
+        fn getNumber(self: &Json) -> f64;
+        fn getString(self: &Json) -> &CxxString;
+        fn getArray(self: &Json) -> &CxxVector<Json>;
+        fn getObject(self: &Json) -> &Object;
+
+        #[cxx_name = "at"]
+        fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json;
+
+        fn load_config() -> UniquePtr<Json>;
     }
 }
 

From 458459f7d1f9abbd3f6e5b763a0380cd4ef0db7c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 23 2020 19:21:28 +0000
Subject: [PATCH 1787/2232] Document rename attribute on types in book


---

diff --git a/book/src/attributes.md b/book/src/attributes.md
index b41515a..9c33b77 100644
--- a/book/src/attributes.md
+++ b/book/src/attributes.md
@@ -48,9 +48,9 @@ The above would result in functions `::second_priority::f`,
 
 ## rust\_name, cxx\_name
 
-Sometimes you want the Rust name of a function to differ from its C++ name.
-Importantly, this enables binding multiple overloads of the same C++ function
-name using distinct Rust names.
+Sometimes you want the Rust name of a function or type to differ from its C++
+name. Importantly, this enables binding multiple overloads of the same C++
+function name using distinct Rust names.
 
 ```rust,noplayground
 #[cxx::bridge]
@@ -71,4 +71,5 @@ name that C++ should use.
 Either of the two attributes may be used on extern "Rust" as well as extern
 "C++" functions, according to which one you find clearer in context.
 
-Support for renaming type names and enum variants is not implemented yet.
+The same attribute works for renaming functions, opaque types, shared
+structs and enums, and enum variants.

From 158972019acf22e5e42ff0b50c80f15f716312a1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 23 2020 19:37:21 +0000
Subject: [PATCH 1788/2232] Release 1.0.21


---

diff --git a/Cargo.toml b/Cargo.toml
index 0ad7835..26289b9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.20" # remember to update html_root_url
+version = "1.0.21" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.20", path = "macro" }
+cxxbridge-macro = { version = "=1.0.21", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.20", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.21", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.20", path = "gen/build" }
+cxx-build = { version = "=1.0.21", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 2ef7780..4686d91 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.20"
+version = "1.0.21"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 5ae0106..57ea11f 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.20"
+version = "1.0.21"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 4614e3f..73bbd6b 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.20"
+version = "1.0.21"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 32c0d4b..688bb95 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.20"
+version = "0.7.21"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index f31470f..2f4ce21 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.20"
+version = "1.0.21"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 5b64109..ee6fea3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.20")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.21")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8215bb7..2fa8610 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.20"
+version = "1.0.21"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.20"
+version = "1.0.21"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.20"
+version = "0.7.21"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.20"
+version = "1.0.21"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.20"
+version = "1.0.21"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.20"
+version = "1.0.21"
 dependencies = [
  "cxx",
  "proc-macro2",

From 8d067de62e32ba5099d95a8cc4749bc6771041f9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 05:15:37 +0000
Subject: [PATCH 1789/2232] Set rust::Opaque as base class of all opaque Rust types


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index f7587ce..86fd491 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -106,10 +106,12 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 }
             }
             Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.name.rust) {
-                    out.next_section();
-                    write_struct_with_methods(out, ety, methods);
-                }
+                out.next_section();
+                let methods = methods_for_type
+                    .get(&ety.name.rust)
+                    .map(Vec::as_slice)
+                    .unwrap_or_default();
+                write_opaque_type(out, ety, methods);
             }
             _ => {}
         }
@@ -301,11 +303,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
 }
 
-fn write_struct_with_methods<'a>(
-    out: &mut OutFile<'a>,
-    ety: &'a ExternType,
-    methods: &[&ExternFn],
-) {
+fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[&ExternFn]) {
     out.set_namespace(&ety.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -314,17 +312,20 @@ fn write_struct_with_methods<'a>(
         writeln!(out, "//{}", line);
     }
     out.builtin.opaque = true;
-    writeln!(
+    write!(
         out,
         "struct {} final : public ::rust::Opaque {{",
         ety.name.cxx,
     );
     for method in methods {
-        write!(out, "  ");
+        write!(out, "\n  ");
         let sig = &method.sig;
         let local_name = method.name.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
-        writeln!(out, ";");
+        write!(out, ";");
+    }
+    if !methods.is_empty() {
+        writeln!(out);
     }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);

From cdda5d0836291ec296e06bed6b39144d50ee3ca0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 05:26:45 +0000
Subject: [PATCH 1790/2232] Merge pull request #594 from dtolnay/opaque


Set rust::Opaque as base class of all opaque Rust types
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index f7587ce..86fd491 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -106,10 +106,12 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
                 }
             }
             Api::RustType(ety) => {
-                if let Some(methods) = methods_for_type.get(&ety.name.rust) {
-                    out.next_section();
-                    write_struct_with_methods(out, ety, methods);
-                }
+                out.next_section();
+                let methods = methods_for_type
+                    .get(&ety.name.rust)
+                    .map(Vec::as_slice)
+                    .unwrap_or_default();
+                write_opaque_type(out, ety, methods);
             }
             _ => {}
         }
@@ -301,11 +303,7 @@ fn write_struct_using(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "using {} = {};", ident.cxx, ident.to_fully_qualified());
 }
 
-fn write_struct_with_methods<'a>(
-    out: &mut OutFile<'a>,
-    ety: &'a ExternType,
-    methods: &[&ExternFn],
-) {
+fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[&ExternFn]) {
     out.set_namespace(&ety.name.namespace);
     let guard = format!("CXXBRIDGE1_STRUCT_{}", ety.name.to_symbol());
     writeln!(out, "#ifndef {}", guard);
@@ -314,17 +312,20 @@ fn write_struct_with_methods<'a>(
         writeln!(out, "//{}", line);
     }
     out.builtin.opaque = true;
-    writeln!(
+    write!(
         out,
         "struct {} final : public ::rust::Opaque {{",
         ety.name.cxx,
     );
     for method in methods {
-        write!(out, "  ");
+        write!(out, "\n  ");
         let sig = &method.sig;
         let local_name = method.name.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
-        writeln!(out, ";");
+        write!(out, ";");
+    }
+    if !methods.is_empty() {
+        writeln!(out);
     }
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);

From d9317eb06b01bc767a9045cebf52d978e3fcad6b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 07:30:40 +0000
Subject: [PATCH 1791/2232] Fully qualify Sized and Unpin traits in generated code


This avoids problematic changes in meaning if the caller's bridge
contains a type called "Sized" or "Unpin".

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 15562ac..96cd15a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -329,12 +329,18 @@ fn expand_cxx_type_assert_pinned(ety: &ExternType) -> TokenStream {
                 fn infer() {}
             }
 
-            impl<T: ?Sized> __AmbiguousIfImpl<()> for T {}
+            impl<T> __AmbiguousIfImpl<()> for T
+            where
+                T: ?::std::marker::Sized
+            {}
 
             #[allow(dead_code)]
             struct __Invalid;
 
-            impl<T: ?Sized + Unpin> __AmbiguousIfImpl<__Invalid> for T {}
+            impl<T> __AmbiguousIfImpl<__Invalid> for T
+            where
+                T: ?::std::marker::Sized + ::std::marker::Unpin,
+            {}
 
             // If there is only one specialized trait impl, type inference with
             // `_` can be resolved and this can compile. Fails to compile if

From 0c9c3e6e3307866d94fb401380c063942e796b59 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 08:52:25 +0000
Subject: [PATCH 1792/2232] Use the same ordering of < <= > >= operators everywhere


---

diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 761cbd8..39c1da1 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -85,8 +85,8 @@ public:
 #   bool operator==(const iterator &) const noexcept;
 #   bool operator!=(const iterator &) const noexcept;
 #   bool operator<(const iterator &) const noexcept;
-#   bool operator>(const iterator &) const noexcept;
 #   bool operator<=(const iterator &) const noexcept;
+#   bool operator>(const iterator &) const noexcept;
 #   bool operator>=(const iterator &) const noexcept;
 # };
 #
@@ -116,8 +116,8 @@ public:
 #   bool operator==(const const_iterator &) const noexcept;
 #   bool operator!=(const const_iterator &) const noexcept;
 #   bool operator<(const const_iterator &) const noexcept;
-#   bool operator>(const const_iterator &) const noexcept;
 #   bool operator<=(const const_iterator &) const noexcept;
+#   bool operator>(const const_iterator &) const noexcept;
 #   bool operator>=(const const_iterator &) const noexcept;
 # };
 #
diff --git a/include/cxx.h b/include/cxx.h
index 79b9f54..cc9ece7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -327,8 +327,8 @@ public:
   bool operator==(const iterator &) const noexcept;
   bool operator!=(const iterator &) const noexcept;
   bool operator<(const iterator &) const noexcept;
-  bool operator>(const iterator &) const noexcept;
   bool operator<=(const iterator &) const noexcept;
+  bool operator>(const iterator &) const noexcept;
   bool operator>=(const iterator &) const noexcept;
 
 private:
@@ -911,23 +911,23 @@ bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
-bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
-  return this->pos > other.pos;
+bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
+  return this->pos < other.pos;
 }
 
 template <typename T>
-bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
-  return this->pos < other.pos;
+bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
+  return this->pos <= other.pos;
 }
 
 template <typename T>
-bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
-  return this->pos >= other.pos;
+bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
+  return this->pos > other.pos;
 }
 
 template <typename T>
-bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
-  return this->pos <= other.pos;
+bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
+  return this->pos >= other.pos;
 }
 
 template <typename T>

From 6ba262f630f8fed6753ab2ada337924215f593c6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 08:54:53 +0000
Subject: [PATCH 1793/2232] Emit private layout struct for all opaque types


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 86fd491..507649e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -311,22 +311,32 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
+
     out.builtin.opaque = true;
-    write!(
+    writeln!(
         out,
         "struct {} final : public ::rust::Opaque {{",
         ety.name.cxx,
     );
+
     for method in methods {
-        write!(out, "\n  ");
+        write!(out, "  ");
         let sig = &method.sig;
         let local_name = method.name.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
-        write!(out, ";");
+        writeln!(out, ";");
     }
+
     if !methods.is_empty() {
         writeln!(out);
     }
+
+    out.include.cstddef = true;
+    writeln!(out, "private:");
+    writeln!(out, "  struct layout {{");
+    writeln!(out, "    static ::std::size_t size() noexcept;");
+    writeln!(out, "    static ::std::size_t align() noexcept;");
+    writeln!(out, "  }};");
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }

From 358bc4b3838d7c1feec859a40b1385459d3b072b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 19:54:54 +0000
Subject: [PATCH 1794/2232] Connect opaque type layout accessors to Rust symbols


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 507649e..0083525 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -132,6 +132,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         for api in apis {
             match api {
                 Api::Struct(strct) => write_struct_operator_decls(out, strct),
+                Api::RustType(ety) => write_opaque_type_layout_decls(out, ety),
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
                 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
                 _ => {}
@@ -144,6 +145,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     for api in apis {
         match api {
             Api::Struct(strct) => write_struct_operators(out, strct),
+            Api::RustType(ety) => write_opaque_type_layout(out, ety),
             Api::RustFunction(efn) => {
                 out.next_section();
                 write_rust_function_shim(out, efn);
@@ -578,6 +580,47 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     }
 }
 
+fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
+    out.set_namespace(&ety.name.namespace);
+    out.begin_block(Block::ExternC);
+
+    let link_name = mangle::operator(&ety.name, "sizeof");
+    writeln!(out, "::std::size_t {}() noexcept;", link_name);
+
+    let link_name = mangle::operator(&ety.name, "alignof");
+    writeln!(out, "::std::size_t {}() noexcept;", link_name);
+
+    out.end_block(Block::ExternC);
+}
+
+fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
+    if out.header {
+        return;
+    }
+
+    out.set_namespace(&ety.name.namespace);
+
+    out.next_section();
+    let link_name = mangle::operator(&ety.name, "sizeof");
+    writeln!(
+        out,
+        "::std::size_t {}::layout::size() noexcept {{",
+        ety.name.cxx,
+    );
+    writeln!(out, "  return {}();", link_name);
+    writeln!(out, "}}");
+
+    out.next_section();
+    let link_name = mangle::operator(&ety.name, "alignof");
+    writeln!(
+        out,
+        "::std::size_t {}::layout::align() noexcept {{",
+        ety.name.cxx,
+    );
+    writeln!(out, "  return {}();", link_name);
+    writeln!(out, "}}");
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);

From 9643703a3f4ca52f51e6b34299181c203ae4300d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:04:01 +0000
Subject: [PATCH 1795/2232] Generate sizeof and alignof symbols


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 96cd15a..69c90eb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -55,7 +55,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(efn, types));
             }
-            Api::RustType(ety) => expanded.extend(expand_rust_type_impl(ety)),
+            Api::RustType(ety) => {
+                expanded.extend(expand_rust_type_impl(ety));
+                hidden.extend(expand_rust_type_layout(ety));
+            }
             Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
@@ -681,6 +684,30 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
+    let ident = &ety.name.rust;
+    let span = ident.span();
+
+    let link_sizeof = mangle::operator(&ety.name, "sizeof");
+    let link_alignof = mangle::operator(&ety.name, "alignof");
+
+    let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
+    let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
+
+    quote_spanned! {span=>
+        #[doc(hidden)]
+        #[export_name = #link_sizeof]
+        extern "C" fn #local_sizeof() -> usize {
+            ::std::mem::size_of::<#ident>()
+        }
+        #[doc(hidden)]
+        #[export_name = #link_alignof]
+        extern "C" fn #local_alignof() -> usize {
+            ::std::mem::align_of::<#ident>()
+        }
+    }
+}
+
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
     let local_name = match &efn.receiver {
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 9818e44..75773b6 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -9,3 +9,21 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   |
   = help: within `TypeR`, the trait `Sized` is not implemented for `str`
   = note: required because it appears within the type `TypeR`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
+    = note: required because it appears within the type `TypeR`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
+    = note: required because it appears within the type `TypeR`

From 6f257a85e70f0cb47f0c8b0b5a823dcc374f092e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:12:06 +0000
Subject: [PATCH 1796/2232] Merge pull request #595 from dtolnay/layout


Emit private layout struct for all opaque types
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 86fd491..0083525 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -132,6 +132,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         for api in apis {
             match api {
                 Api::Struct(strct) => write_struct_operator_decls(out, strct),
+                Api::RustType(ety) => write_opaque_type_layout_decls(out, ety),
                 Api::CxxFunction(efn) => write_cxx_function_shim(out, efn),
                 Api::RustFunction(efn) => write_rust_function_decl(out, efn),
                 _ => {}
@@ -144,6 +145,7 @@ fn write_functions<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     for api in apis {
         match api {
             Api::Struct(strct) => write_struct_operators(out, strct),
+            Api::RustType(ety) => write_opaque_type_layout(out, ety),
             Api::RustFunction(efn) => {
                 out.next_section();
                 write_rust_function_shim(out, efn);
@@ -311,22 +313,32 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
     for line in ety.doc.to_string().lines() {
         writeln!(out, "//{}", line);
     }
+
     out.builtin.opaque = true;
-    write!(
+    writeln!(
         out,
         "struct {} final : public ::rust::Opaque {{",
         ety.name.cxx,
     );
+
     for method in methods {
-        write!(out, "\n  ");
+        write!(out, "  ");
         let sig = &method.sig;
         let local_name = method.name.cxx.to_string();
         write_rust_function_shim_decl(out, &local_name, sig, false);
-        write!(out, ";");
+        writeln!(out, ";");
     }
+
     if !methods.is_empty() {
         writeln!(out);
     }
+
+    out.include.cstddef = true;
+    writeln!(out, "private:");
+    writeln!(out, "  struct layout {{");
+    writeln!(out, "    static ::std::size_t size() noexcept;");
+    writeln!(out, "    static ::std::size_t align() noexcept;");
+    writeln!(out, "  }};");
     writeln!(out, "}};");
     writeln!(out, "#endif // {}", guard);
 }
@@ -568,6 +580,47 @@ fn write_struct_operators<'a>(out: &mut OutFile<'a>, strct: &'a Struct) {
     }
 }
 
+fn write_opaque_type_layout_decls<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
+    out.set_namespace(&ety.name.namespace);
+    out.begin_block(Block::ExternC);
+
+    let link_name = mangle::operator(&ety.name, "sizeof");
+    writeln!(out, "::std::size_t {}() noexcept;", link_name);
+
+    let link_name = mangle::operator(&ety.name, "alignof");
+    writeln!(out, "::std::size_t {}() noexcept;", link_name);
+
+    out.end_block(Block::ExternC);
+}
+
+fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
+    if out.header {
+        return;
+    }
+
+    out.set_namespace(&ety.name.namespace);
+
+    out.next_section();
+    let link_name = mangle::operator(&ety.name, "sizeof");
+    writeln!(
+        out,
+        "::std::size_t {}::layout::size() noexcept {{",
+        ety.name.cxx,
+    );
+    writeln!(out, "  return {}();", link_name);
+    writeln!(out, "}}");
+
+    out.next_section();
+    let link_name = mangle::operator(&ety.name, "alignof");
+    writeln!(
+        out,
+        "::std::size_t {}::layout::align() noexcept {{",
+        ety.name.cxx,
+    );
+    writeln!(out, "  return {}();", link_name);
+    writeln!(out, "}}");
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 96cd15a..69c90eb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -55,7 +55,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
             Api::CxxFunction(efn) => {
                 expanded.extend(expand_cxx_function_shim(efn, types));
             }
-            Api::RustType(ety) => expanded.extend(expand_rust_type_impl(ety)),
+            Api::RustType(ety) => {
+                expanded.extend(expand_rust_type_impl(ety));
+                hidden.extend(expand_rust_type_layout(ety));
+            }
             Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
             Api::TypeAlias(alias) => {
                 expanded.extend(expand_type_alias(alias));
@@ -681,6 +684,30 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
+    let ident = &ety.name.rust;
+    let span = ident.span();
+
+    let link_sizeof = mangle::operator(&ety.name, "sizeof");
+    let link_alignof = mangle::operator(&ety.name, "alignof");
+
+    let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
+    let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
+
+    quote_spanned! {span=>
+        #[doc(hidden)]
+        #[export_name = #link_sizeof]
+        extern "C" fn #local_sizeof() -> usize {
+            ::std::mem::size_of::<#ident>()
+        }
+        #[doc(hidden)]
+        #[export_name = #link_alignof]
+        extern "C" fn #local_alignof() -> usize {
+            ::std::mem::align_of::<#ident>()
+        }
+    }
+}
+
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
     let local_name = match &efn.receiver {
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 9818e44..75773b6 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -9,3 +9,21 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   |
   = help: within `TypeR`, the trait `Sized` is not implemented for `str`
   = note: required because it appears within the type `TypeR`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
+    = note: required because it appears within the type `TypeR`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+   --> $DIR/opaque_not_sized.rs:4:14
+    |
+4   |         type TypeR;
+    |              ^^^^^ doesn't have a size known at compile-time
+    |
+    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
+    = note: required because it appears within the type `TypeR`

From 03267369cc22d3d7030d8d291f7b6ce5425bc040 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:12:17 +0000
Subject: [PATCH 1797/2232] Consolidate error on unsized extern Rust type


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 69c90eb..580ff76 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -691,19 +691,25 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     let link_sizeof = mangle::operator(&ety.name, "sizeof");
     let link_alignof = mangle::operator(&ety.name, "alignof");
 
+    let local_layout = format_ident!("__layout_{}", ety.name.rust);
     let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
     let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
 
     quote_spanned! {span=>
         #[doc(hidden)]
+        #[inline]
+        fn #local_layout() -> ::std::alloc::Layout {
+            ::std::alloc::Layout::new::<#ident>()
+        }
+        #[doc(hidden)]
         #[export_name = #link_sizeof]
         extern "C" fn #local_sizeof() -> usize {
-            ::std::mem::size_of::<#ident>()
+            #local_layout().size()
         }
         #[doc(hidden)]
         #[export_name = #link_alignof]
         extern "C" fn #local_alignof() -> usize {
-            ::std::mem::align_of::<#ident>()
+            #local_layout().align()
         }
     }
 }
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 75773b6..b400908 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -18,12 +18,3 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
     |
     = help: within `TypeR`, the trait `Sized` is not implemented for `str`
     = note: required because it appears within the type `TypeR`
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-   --> $DIR/opaque_not_sized.rs:4:14
-    |
-4   |         type TypeR;
-    |              ^^^^^ doesn't have a size known at compile-time
-    |
-    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
-    = note: required because it appears within the type `TypeR`

From 0aa9d205daa726639e0d9aa75cf47a6f30e0db63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:12:17 +0000
Subject: [PATCH 1798/2232] Further reduce the rustc diagnostic when an extern Rust type is unsized


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 580ff76..381bf5b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -669,47 +669,46 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 
     let ident = &ety.name.rust;
     let begin_span = Token![::](ety.type_token.span);
-    let sized = quote_spanned! {ety.semi_token.span=>
-        #begin_span std::marker::Sized
-    };
     let unpin = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Unpin
     };
     quote_spanned! {ident.span()=>
         let _ = {
-            fn __AssertSized<T: ?#sized + #sized>() {}
-            fn __AssertUnpin<T: #unpin>() {}
-            (__AssertSized::<#ident>, __AssertUnpin::<#ident>)
+            fn __AssertUnpin<T: ?::std::marker::Sized + #unpin>() {}
+            __AssertUnpin::<#ident>
         };
     }
 }
 
 fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
-    let span = ident.span();
+    let begin_span = Token![::](ety.type_token.span);
+    let sized = quote_spanned! {ety.semi_token.span=>
+        #begin_span std::marker::Sized
+    };
 
     let link_sizeof = mangle::operator(&ety.name, "sizeof");
     let link_alignof = mangle::operator(&ety.name, "alignof");
 
-    let local_layout = format_ident!("__layout_{}", ety.name.rust);
     let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
     let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
 
-    quote_spanned! {span=>
-        #[doc(hidden)]
-        #[inline]
-        fn #local_layout() -> ::std::alloc::Layout {
-            ::std::alloc::Layout::new::<#ident>()
-        }
-        #[doc(hidden)]
-        #[export_name = #link_sizeof]
-        extern "C" fn #local_sizeof() -> usize {
-            #local_layout().size()
-        }
-        #[doc(hidden)]
-        #[export_name = #link_alignof]
-        extern "C" fn #local_alignof() -> usize {
-            #local_layout().align()
+    quote_spanned! {ident.span()=>
+        {
+            #[doc(hidden)]
+            fn __AssertSized<T: ?#sized + #sized>() -> ::std::alloc::Layout {
+                ::std::alloc::Layout::new::<T>()
+            }
+            #[doc(hidden)]
+            #[export_name = #link_sizeof]
+            extern "C" fn #local_sizeof() -> usize {
+                __AssertSized::<#ident>().size()
+            }
+            #[doc(hidden)]
+            #[export_name = #link_alignof]
+            extern "C" fn #local_alignof() -> usize {
+                __AssertSized::<#ident>().align()
+            }
         }
     }
 }
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index b400908..9818e44 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -9,12 +9,3 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   |
   = help: within `TypeR`, the trait `Sized` is not implemented for `str`
   = note: required because it appears within the type `TypeR`
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-   --> $DIR/opaque_not_sized.rs:4:14
-    |
-4   |         type TypeR;
-    |              ^^^^^ doesn't have a size known at compile-time
-    |
-    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
-    = note: required because it appears within the type `TypeR`

From dd36736a99605edec460add73f5e29fd4b5929e6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:20:09 +0000
Subject: [PATCH 1799/2232] Merge pull request #596 from dtolnay/layout


Improve rustc diagnostic when an extern Rust type is unsized
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 69c90eb..381bf5b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -669,24 +669,23 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
 
     let ident = &ety.name.rust;
     let begin_span = Token![::](ety.type_token.span);
-    let sized = quote_spanned! {ety.semi_token.span=>
-        #begin_span std::marker::Sized
-    };
     let unpin = quote_spanned! {ety.semi_token.span=>
         #begin_span std::marker::Unpin
     };
     quote_spanned! {ident.span()=>
         let _ = {
-            fn __AssertSized<T: ?#sized + #sized>() {}
-            fn __AssertUnpin<T: #unpin>() {}
-            (__AssertSized::<#ident>, __AssertUnpin::<#ident>)
+            fn __AssertUnpin<T: ?::std::marker::Sized + #unpin>() {}
+            __AssertUnpin::<#ident>
         };
     }
 }
 
 fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
-    let span = ident.span();
+    let begin_span = Token![::](ety.type_token.span);
+    let sized = quote_spanned! {ety.semi_token.span=>
+        #begin_span std::marker::Sized
+    };
 
     let link_sizeof = mangle::operator(&ety.name, "sizeof");
     let link_alignof = mangle::operator(&ety.name, "alignof");
@@ -694,16 +693,22 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     let local_sizeof = format_ident!("__sizeof_{}", ety.name.rust);
     let local_alignof = format_ident!("__alignof_{}", ety.name.rust);
 
-    quote_spanned! {span=>
-        #[doc(hidden)]
-        #[export_name = #link_sizeof]
-        extern "C" fn #local_sizeof() -> usize {
-            ::std::mem::size_of::<#ident>()
-        }
-        #[doc(hidden)]
-        #[export_name = #link_alignof]
-        extern "C" fn #local_alignof() -> usize {
-            ::std::mem::align_of::<#ident>()
+    quote_spanned! {ident.span()=>
+        {
+            #[doc(hidden)]
+            fn __AssertSized<T: ?#sized + #sized>() -> ::std::alloc::Layout {
+                ::std::alloc::Layout::new::<T>()
+            }
+            #[doc(hidden)]
+            #[export_name = #link_sizeof]
+            extern "C" fn #local_sizeof() -> usize {
+                __AssertSized::<#ident>().size()
+            }
+            #[doc(hidden)]
+            #[export_name = #link_alignof]
+            extern "C" fn #local_alignof() -> usize {
+                __AssertSized::<#ident>().align()
+            }
         }
     }
 }
diff --git a/tests/ui/opaque_not_sized.stderr b/tests/ui/opaque_not_sized.stderr
index 75773b6..9818e44 100644
--- a/tests/ui/opaque_not_sized.stderr
+++ b/tests/ui/opaque_not_sized.stderr
@@ -9,21 +9,3 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   |
   = help: within `TypeR`, the trait `Sized` is not implemented for `str`
   = note: required because it appears within the type `TypeR`
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-   --> $DIR/opaque_not_sized.rs:4:14
-    |
-4   |         type TypeR;
-    |              ^^^^^ doesn't have a size known at compile-time
-    |
-    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
-    = note: required because it appears within the type `TypeR`
-
-error[E0277]: the size for values of type `str` cannot be known at compilation time
-   --> $DIR/opaque_not_sized.rs:4:14
-    |
-4   |         type TypeR;
-    |              ^^^^^ doesn't have a size known at compile-time
-    |
-    = help: within `TypeR`, the trait `Sized` is not implemented for `str`
-    = note: required because it appears within the type `TypeR`

From ee6ecfcf910e6fd4e0c21f85580e113f428e9c2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:20:25 +0000
Subject: [PATCH 1800/2232] Add rust::size_of, align_of accessors that work for opaque types


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index dbd019b..8ce89f8 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -13,6 +13,7 @@ pub struct Builtins<'a> {
     pub rust_fn: bool,
     pub rust_isize: bool,
     pub opaque: bool,
+    pub layout: bool,
     pub unsafe_bitcopy: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
@@ -102,6 +103,12 @@ pub(super) fn write(out: &mut OutFile) {
         include.type_traits = true;
     }
 
+    if builtin.layout {
+        include.type_traits = true;
+        include.cstddef = true;
+        builtin.is_complete = true;
+    }
+
     if builtin.is_complete {
         include.cstddef = true;
         include.type_traits = true;
@@ -125,10 +132,13 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::AnonymousNamespace);
     }
 
+    out.next_section();
     if builtin.rust_str && !builtin.rust_string {
-        out.next_section();
         writeln!(out, "class String;");
     }
+    if builtin.layout && !builtin.opaque {
+        writeln!(out, "class Opaque;");
+    }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
@@ -140,8 +150,9 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
     ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
+    ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
     out.begin_block(Block::Namespace("detail"));
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e20f54f..bae9cfe 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -333,8 +333,10 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
         writeln!(out);
     }
 
+    out.builtin.layout = true;
     out.include.cstddef = true;
     writeln!(out, "private:");
+    writeln!(out, "  friend ::rust::layout;");
     writeln!(out, "  struct layout {{");
     writeln!(out, "    static ::std::size_t size() noexcept;");
     writeln!(out, "    static ::std::size_t align() noexcept;");
diff --git a/include/cxx.h b/include/cxx.h
index 25a6252..566b482 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -401,6 +401,11 @@ public:
 };
 #endif // CXXBRIDGE1_RUST_OPAQUE
 
+template <typename T>
+std::size_t size_of();
+template <typename T>
+std::size_t align_of();
+
 // IsRelocatable<T> is used in assertions that a C++ type passed by value
 // between Rust and C++ is soundly relocatable by Rust.
 //
@@ -987,6 +992,62 @@ struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
 } // namespace detail
 #endif // CXXBRIDGE1_IS_COMPLETE
 
+#ifndef CXXBRIDGE1_LAYOUT
+#define CXXBRIDGE1_LAYOUT
+class layout {
+  template <typename T>
+  friend std::size_t size_of();
+  template <typename T>
+  friend std::size_t align_of();
+  template <typename T>
+  static typename std::enable_if<std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_size_of() {
+    return T::layout::size();
+  }
+  template <typename T>
+  static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_size_of() {
+    return sizeof(T);
+  }
+  template <typename T>
+  static
+      typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
+      size_of() {
+    return do_size_of<T>();
+  }
+  template <typename T>
+  static typename std::enable_if<std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_align_of() {
+    return T::layout::align();
+  }
+  template <typename T>
+  static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_align_of() {
+    return alignof(T);
+  }
+  template <typename T>
+  static
+      typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
+      align_of() {
+    return do_align_of<T>();
+  }
+};
+
+template <typename T>
+std::size_t size_of() {
+  return layout::size_of<T>();
+}
+
+template <typename T>
+std::size_t align_of() {
+  return layout::align_of<T>();
+}
+#endif // CXXBRIDGE1_LAYOUT
+
 #ifndef CXXBRIDGE1_RELOCATABLE
 #define CXXBRIDGE1_RELOCATABLE
 namespace detail {

From b6b6d2eb88bcf63037288e4361542f0d28279253 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:20:25 +0000
Subject: [PATCH 1801/2232] Add test of size_of, align_of


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index cd367d8..e508494 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -668,6 +668,11 @@ extern "C" const char *cxx_run_test() noexcept {
     }                                                                          \
   } while (false)
 
+  ASSERT(rust::size_of<R>() == sizeof(size_t));
+  ASSERT(rust::align_of<R>() == alignof(size_t));
+  ASSERT(rust::size_of<size_t>() == sizeof(size_t));
+  ASSERT(rust::align_of<size_t>() == alignof(size_t));
+
   ASSERT(r_return_primitive() == 2020);
   ASSERT(r_return_shared().z == 2020);
   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));

From 7506863fa450e8495c9849702784e5069543b843 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:20:25 +0000
Subject: [PATCH 1802/2232] Move is_complete type trait to header


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 1de36e1..dbd019b 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -102,6 +102,11 @@ pub(super) fn write(out: &mut OutFile) {
         include.type_traits = true;
     }
 
+    if builtin.is_complete {
+        include.cstddef = true;
+        include.type_traits = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     writeln!(out, "// #include \"rust/cxx.h\"");
@@ -136,6 +141,7 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+    ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
 
     out.begin_block(Block::Namespace("detail"));
 
@@ -277,20 +283,6 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "}};");
     }
 
-    if builtin.is_complete {
-        include.cstddef = true;
-        include.type_traits = true;
-        out.next_section();
-        writeln!(out, "template <typename T, typename = ::std::size_t>");
-        writeln!(out, "struct is_complete : std::false_type {{}};");
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(
-            out,
-            "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
-        );
-    }
-
     if builtin.deleter_if {
         out.next_section();
         writeln!(out, "template <bool> struct deleter_if {{");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 0083525..e20f54f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1622,7 +1622,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         };
         writeln!(
             out,
-            "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+            "static_assert(::rust::detail::is_complete<{}>::value, \"definition of {} is required\");",
             inner, definition,
         );
     }
@@ -1689,7 +1689,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         out.builtin.deleter_if = true;
         writeln!(
             out,
-            "  ::rust::deleter_if<::rust::is_complete<{}>::value>{{}}(ptr);",
+            "  ::rust::deleter_if<::rust::detail::is_complete<{}>::value>{{}}(ptr);",
             inner,
         );
     } else {
diff --git a/include/cxx.h b/include/cxx.h
index cc9ece7..25a6252 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -975,6 +975,18 @@ template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
 #endif // CXXBRIDGE1_RUST_VEC
 
+#ifndef CXXBRIDGE1_IS_COMPLETE
+#define CXXBRIDGE1_IS_COMPLETE
+namespace detail {
+namespace {
+template <typename T, typename = std::size_t>
+struct is_complete : std::false_type {};
+template <typename T>
+struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
+} // namespace
+} // namespace detail
+#endif // CXXBRIDGE1_IS_COMPLETE
+
 #ifndef CXXBRIDGE1_RELOCATABLE
 #define CXXBRIDGE1_RELOCATABLE
 namespace detail {

From 5dd996e980b14225472727d4b7dc13945255c815 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:32:13 +0000
Subject: [PATCH 1803/2232] Merge pull request #597 from dtolnay/layout


Add rust::size_of, align_of accessors that work for opaque types
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index dbd019b..8ce89f8 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -13,6 +13,7 @@ pub struct Builtins<'a> {
     pub rust_fn: bool,
     pub rust_isize: bool,
     pub opaque: bool,
+    pub layout: bool,
     pub unsafe_bitcopy: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
@@ -102,6 +103,12 @@ pub(super) fn write(out: &mut OutFile) {
         include.type_traits = true;
     }
 
+    if builtin.layout {
+        include.type_traits = true;
+        include.cstddef = true;
+        builtin.is_complete = true;
+    }
+
     if builtin.is_complete {
         include.cstddef = true;
         include.type_traits = true;
@@ -125,10 +132,13 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::AnonymousNamespace);
     }
 
+    out.next_section();
     if builtin.rust_str && !builtin.rust_string {
-        out.next_section();
         writeln!(out, "class String;");
     }
+    if builtin.layout && !builtin.opaque {
+        writeln!(out, "class Opaque;");
+    }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
@@ -140,8 +150,9 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
     ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
     ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
     ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
+    ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
+    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
     out.begin_block(Block::Namespace("detail"));
 
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e20f54f..bae9cfe 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -333,8 +333,10 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
         writeln!(out);
     }
 
+    out.builtin.layout = true;
     out.include.cstddef = true;
     writeln!(out, "private:");
+    writeln!(out, "  friend ::rust::layout;");
     writeln!(out, "  struct layout {{");
     writeln!(out, "    static ::std::size_t size() noexcept;");
     writeln!(out, "    static ::std::size_t align() noexcept;");
diff --git a/include/cxx.h b/include/cxx.h
index 25a6252..566b482 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -401,6 +401,11 @@ public:
 };
 #endif // CXXBRIDGE1_RUST_OPAQUE
 
+template <typename T>
+std::size_t size_of();
+template <typename T>
+std::size_t align_of();
+
 // IsRelocatable<T> is used in assertions that a C++ type passed by value
 // between Rust and C++ is soundly relocatable by Rust.
 //
@@ -987,6 +992,62 @@ struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
 } // namespace detail
 #endif // CXXBRIDGE1_IS_COMPLETE
 
+#ifndef CXXBRIDGE1_LAYOUT
+#define CXXBRIDGE1_LAYOUT
+class layout {
+  template <typename T>
+  friend std::size_t size_of();
+  template <typename T>
+  friend std::size_t align_of();
+  template <typename T>
+  static typename std::enable_if<std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_size_of() {
+    return T::layout::size();
+  }
+  template <typename T>
+  static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_size_of() {
+    return sizeof(T);
+  }
+  template <typename T>
+  static
+      typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
+      size_of() {
+    return do_size_of<T>();
+  }
+  template <typename T>
+  static typename std::enable_if<std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_align_of() {
+    return T::layout::align();
+  }
+  template <typename T>
+  static typename std::enable_if<!std::is_base_of<Opaque, T>::value,
+                                 std::size_t>::type
+  do_align_of() {
+    return alignof(T);
+  }
+  template <typename T>
+  static
+      typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type
+      align_of() {
+    return do_align_of<T>();
+  }
+};
+
+template <typename T>
+std::size_t size_of() {
+  return layout::size_of<T>();
+}
+
+template <typename T>
+std::size_t align_of() {
+  return layout::align_of<T>();
+}
+#endif // CXXBRIDGE1_LAYOUT
+
 #ifndef CXXBRIDGE1_RELOCATABLE
 #define CXXBRIDGE1_RELOCATABLE
 namespace detail {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index cd367d8..e508494 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -668,6 +668,11 @@ extern "C" const char *cxx_run_test() noexcept {
     }                                                                          \
   } while (false)
 
+  ASSERT(rust::size_of<R>() == sizeof(size_t));
+  ASSERT(rust::align_of<R>() == alignof(size_t));
+  ASSERT(rust::size_of<size_t>() == sizeof(size_t));
+  ASSERT(rust::align_of<size_t>() == alignof(size_t));
+
   ASSERT(r_return_primitive() == 2020);
   ASSERT(r_return_shared().z == 2020);
   ASSERT(cxx_test_suite_r_is_correct(&*r_return_box()));

From 78dd535756b296353e14ae63fce4663847c3e5e7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:32:22 +0000
Subject: [PATCH 1804/2232] Add checked and unchecked indexing to rust::Slice


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8ce89f8..d43038b 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
+        builtin.panic = true;
     }
 
     if builtin.rust_box {
diff --git a/include/cxx.h b/include/cxx.h
index 566b482..c1d452e 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -156,6 +156,12 @@ public:
   T *data() const noexcept;
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
+  bool empty() const noexcept;
+
+  T &operator[](std::size_t n) const noexcept;
+  T &at(std::size_t n) const;
+  T &front() const noexcept;
+  T &back() const noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Slice(const Slice<T> &) noexcept = default;
@@ -520,6 +526,37 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
+bool Slice<T>::empty() const noexcept {
+  return this->len == 0;
+}
+
+template <typename T>
+T &Slice<T>::operator[](std::size_t n) const noexcept {
+  assert(n < this->size());
+  return this->ptr[n];
+}
+
+template <typename T>
+T &Slice<T>::at(std::size_t n) const {
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Slice index out of range");
+  }
+  return (*this)[n];
+}
+
+template <typename T>
+T &Slice<T>::front() const noexcept {
+  assert(!this->empty());
+  return this->ptr[0];
+}
+
+template <typename T>
+T &Slice<T>::back() const noexcept {
+  assert(!this->empty());
+  return this->ptr[this->len - 1];
+}
+
+template <typename T>
 T &Slice<T>::iterator::operator*() const noexcept {
   return *this->pos;
 }

From b4512a4465caea229e7d94db1f456cf67209bdb7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:32:22 +0000
Subject: [PATCH 1805/2232] Test rust::Slice indexing


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index e508494..05ff4b8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -274,7 +274,8 @@ void c_take_slice_char(rust::Slice<const char> s) {
 }
 
 void c_take_slice_shared(rust::Slice<const Shared> s) {
-  if (s.size() == 2 && s.data()->z == 2020 && (s.data() + 1)->z == 2021) {
+  if (s.size() == 2 && s.data()->z == 2020 && s[1].z == 2021 &&
+      s.at(1).z == 2021 && s.front().z == 2020 && s.back().z == 2021) {
     cxx_test_suite_set_correct();
   }
 }

From 974bc9559d018d855ab8814bc3d923875f28affc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:32:22 +0000
Subject: [PATCH 1806/2232] Add Slice indexing to API on website


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fc2b4da..ef9450c 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -25,6 +25,12 @@ public:
   T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+  bool empty() const noexcept;
+
+  T &operator[](size_t n) const noexcept;
+  T &at(size_t n) const;
+  T &front() const noexcept;
+  T &back() const noexcept;
 
   class iterator;
   iterator begin() const noexcept;

From 73beb2696bb62fcde2370a36ed3b346fc7f1de8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:43:36 +0000
Subject: [PATCH 1807/2232] Merge pull request #598 from dtolnay/indexing


Add checked and unchecked indexing to rust::Slice
---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fc2b4da..ef9450c 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -25,6 +25,12 @@ public:
   T *data() const noexcept;
   size_t size() const noexcept;
   size_t length() const noexcept;
+  bool empty() const noexcept;
+
+  T &operator[](size_t n) const noexcept;
+  T &at(size_t n) const;
+  T &front() const noexcept;
+  T &back() const noexcept;
 
   class iterator;
   iterator begin() const noexcept;
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 8ce89f8..d43038b 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
+        builtin.panic = true;
     }
 
     if builtin.rust_box {
diff --git a/include/cxx.h b/include/cxx.h
index 566b482..c1d452e 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -156,6 +156,12 @@ public:
   T *data() const noexcept;
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
+  bool empty() const noexcept;
+
+  T &operator[](std::size_t n) const noexcept;
+  T &at(std::size_t n) const;
+  T &front() const noexcept;
+  T &back() const noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Slice(const Slice<T> &) noexcept = default;
@@ -520,6 +526,37 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
+bool Slice<T>::empty() const noexcept {
+  return this->len == 0;
+}
+
+template <typename T>
+T &Slice<T>::operator[](std::size_t n) const noexcept {
+  assert(n < this->size());
+  return this->ptr[n];
+}
+
+template <typename T>
+T &Slice<T>::at(std::size_t n) const {
+  if (n >= this->size()) {
+    panic<std::out_of_range>("rust::Slice index out of range");
+  }
+  return (*this)[n];
+}
+
+template <typename T>
+T &Slice<T>::front() const noexcept {
+  assert(!this->empty());
+  return this->ptr[0];
+}
+
+template <typename T>
+T &Slice<T>::back() const noexcept {
+  assert(!this->empty());
+  return this->ptr[this->len - 1];
+}
+
+template <typename T>
 T &Slice<T>::iterator::operator*() const noexcept {
   return *this->pos;
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index e508494..05ff4b8 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -274,7 +274,8 @@ void c_take_slice_char(rust::Slice<const char> s) {
 }
 
 void c_take_slice_shared(rust::Slice<const Shared> s) {
-  if (s.size() == 2 && s.data()->z == 2020 && (s.data() + 1)->z == 2021) {
+  if (s.size() == 2 && s.data()->z == 2020 && s[1].z == 2021 &&
+      s.at(1).z == 2021 && s.front().z == 2020 && s.back().z == 2021) {
     cxx_test_suite_set_correct();
   }
 }

From db388c909028976f562e13d50e087d0738908482 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:43:48 +0000
Subject: [PATCH 1808/2232] Update Slice iterator definition to follow canonical signatures


---

diff --git a/include/cxx.h b/include/cxx.h
index c1d452e..d1c87c8 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -188,8 +188,8 @@ public:
   using reference = typename std::add_lvalue_reference<T>::type;
   using iterator_category = std::forward_iterator_tag;
 
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
+  reference operator*() const noexcept;
+  pointer operator->() const noexcept;
   iterator &operator++() noexcept;
   iterator operator++(int) noexcept;
   bool operator==(const iterator &) const noexcept;
@@ -557,12 +557,14 @@ T &Slice<T>::back() const noexcept {
 }
 
 template <typename T>
-T &Slice<T>::iterator::operator*() const noexcept {
+typename Slice<T>::iterator::reference
+Slice<T>::iterator::operator*() const noexcept {
   return *this->pos;
 }
 
 template <typename T>
-T *Slice<T>::iterator::operator->() const noexcept {
+typename Slice<T>::iterator::pointer
+Slice<T>::iterator::operator->() const noexcept {
   return this->pos;
 }
 

From c30e4471347f3c366c29081dadb9038928040465 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:43:48 +0000
Subject: [PATCH 1809/2232] Expand Slice iterator to be random access iterator


---

diff --git a/include/cxx.h b/include/cxx.h
index d1c87c8..61a500f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -182,18 +182,33 @@ private:
 template <typename T>
 class Slice<T>::iterator final {
 public:
-  using difference_type = std::ptrdiff_t;
+  using iterator_category = std::random_access_iterator_tag;
   using value_type = T;
+  using difference_type = std::ptrdiff_t;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
-  using iterator_category = std::forward_iterator_tag;
 
   reference operator*() const noexcept;
   pointer operator->() const noexcept;
+  reference operator[](difference_type) const noexcept;
+
   iterator &operator++() noexcept;
   iterator operator++(int) noexcept;
+  iterator &operator--() noexcept;
+  iterator operator--(int) noexcept;
+
+  iterator &operator+=(difference_type) noexcept;
+  iterator &operator-=(difference_type) noexcept;
+  iterator operator+(difference_type) const noexcept;
+  iterator operator-(difference_type) const noexcept;
+  difference_type operator-(const iterator &) const noexcept;
+
   bool operator==(const iterator &) const noexcept;
   bool operator!=(const iterator &) const noexcept;
+  bool operator<(const iterator &) const noexcept;
+  bool operator<=(const iterator &) const noexcept;
+  bool operator>(const iterator &) const noexcept;
+  bool operator>=(const iterator &) const noexcept;
 
 private:
   friend class Slice;
@@ -569,6 +584,12 @@ Slice<T>::iterator::operator->() const noexcept {
 }
 
 template <typename T>
+typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return this->pos[n];
+}
+
+template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
   ++this->pos;
   return *this;
@@ -582,6 +603,51 @@ typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
 }
 
 template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {
+  --this->pos;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {
+  auto ret = iterator(*this);
+  --this->pos;
+  return ret;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator+=(
+    typename Slice<T>::iterator::difference_type n) noexcept {
+  this->pos += n;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator-=(
+    typename Slice<T>::iterator::difference_type n) noexcept {
+  this->pos -= n;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator+(
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return iterator(*this) += n;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator-(
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return iterator(*this) -= n;
+}
+
+template <typename T>
+typename Slice<T>::iterator::difference_type
+Slice<T>::iterator::operator-(const iterator &other) const noexcept {
+  return std::distance(other.pos, this->pos);
+}
+
+template <typename T>
 bool Slice<T>::iterator::operator==(const iterator &other) const noexcept {
   return this->pos == other.pos;
 }
@@ -592,6 +658,26 @@ bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
+bool Slice<T>::iterator::operator<(const iterator &other) const noexcept {
+  return this->pos < other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator<=(const iterator &other) const noexcept {
+  return this->pos <= other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator>(const iterator &other) const noexcept {
+  return this->pos > other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
+  return this->pos >= other.pos;
+}
+
+template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
   it.pos = this->ptr;

From e1ad7fab510e6c44e2282d32a0553331856b4e5b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:43:48 +0000
Subject: [PATCH 1810/2232] Document Slice iterator API


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index ef9450c..20ee98f 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -40,16 +40,32 @@ public:
 # template <typename T>
 # class Slice<T>::iterator final {
 # public:
+#   using iterator_category = std::random_access_iterator_tag;
 #   using value_type = T;
 #   using pointer = T *;
 #   using reference = T &;
 #
 #   T &operator*() const noexcept;
 #   T *operator->() const noexcept;
+#   T &operator[](ptrdiff_t) const noexcept;
+#
 #   iterator &operator++() noexcept;
 #   iterator operator++(int) noexcept;
+#   iterator &operator--() noexcept;
+#   iterator operator--(int) noexcept;
+#
+#   iterator &operator+=(ptrdiff_t) noexcept;
+#   iterator &operator-=(ptrdiff_t) noexcept;
+#   iterator operator+(ptrdiff_t) const noexcept;
+#   iterator operator-(ptrdiff_t) const noexcept;
+#   ptrdiff_t operator-(const iterator &) const noexcept;
+#
 #   bool operator==(const iterator &) const noexcept;
 #   bool operator!=(const iterator &) const noexcept;
+#   bool operator<(const iterator &) const noexcept;
+#   bool operator>(const iterator &) const noexcept;
+#   bool operator<=(const iterator &) const noexcept;
+#   bool operator>=(const iterator &) const noexcept;
 # };
 #
 # } // namespace rust

From 8f2180ce23b971c00ebfd94d188f5d31d2047200 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:43:48 +0000
Subject: [PATCH 1811/2232] Add test of sorting rust::Slice


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7504704..df5c279 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -120,6 +120,7 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
+        fn c_take_slice_shared_sort(s: &mut [Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 05ff4b8..2bb7d71 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -280,6 +280,15 @@ void c_take_slice_shared(rust::Slice<const Shared> s) {
   }
 }
 
+void c_take_slice_shared_sort(rust::Slice<Shared> s) {
+  // Exercise requirements of RandomAccessIterator.
+  // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
+  std::sort(s.begin(), s.end());
+  if (s[0].z == 0 && s[1].z == 2 && s[2].z == 4 && s[3].z == 7) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 51ab51d..50a8005 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -123,6 +123,7 @@ void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
+void c_take_slice_shared_sort(rust::Slice<Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 60bf1bd..0620a9c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -125,6 +125,17 @@ fn test_c_take() {
         ffi::Shared { z: 2020 },
         ffi::Shared { z: 2021 },
     ]));
+    let shared_sort_slice = &mut [
+        ffi::Shared { z: 2 },
+        ffi::Shared { z: 0 },
+        ffi::Shared { z: 7 },
+        ffi::Shared { z: 4 },
+    ];
+    check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
+    assert_eq!(shared_sort_slice[0].z, 0);
+    assert_eq!(shared_sort_slice[1].z, 2);
+    assert_eq!(shared_sort_slice[2].z, 4);
+    assert_eq!(shared_sort_slice[3].z, 7);
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From cc5f820b59154f6daae060ac62eef909e4752b76 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:51:52 +0000
Subject: [PATCH 1812/2232] Merge pull request #599 from dtolnay/slicerandom


Expand Slice iterator to be random access iterator
---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index ef9450c..20ee98f 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -40,16 +40,32 @@ public:
 # template <typename T>
 # class Slice<T>::iterator final {
 # public:
+#   using iterator_category = std::random_access_iterator_tag;
 #   using value_type = T;
 #   using pointer = T *;
 #   using reference = T &;
 #
 #   T &operator*() const noexcept;
 #   T *operator->() const noexcept;
+#   T &operator[](ptrdiff_t) const noexcept;
+#
 #   iterator &operator++() noexcept;
 #   iterator operator++(int) noexcept;
+#   iterator &operator--() noexcept;
+#   iterator operator--(int) noexcept;
+#
+#   iterator &operator+=(ptrdiff_t) noexcept;
+#   iterator &operator-=(ptrdiff_t) noexcept;
+#   iterator operator+(ptrdiff_t) const noexcept;
+#   iterator operator-(ptrdiff_t) const noexcept;
+#   ptrdiff_t operator-(const iterator &) const noexcept;
+#
 #   bool operator==(const iterator &) const noexcept;
 #   bool operator!=(const iterator &) const noexcept;
+#   bool operator<(const iterator &) const noexcept;
+#   bool operator>(const iterator &) const noexcept;
+#   bool operator<=(const iterator &) const noexcept;
+#   bool operator>=(const iterator &) const noexcept;
 # };
 #
 # } // namespace rust
diff --git a/include/cxx.h b/include/cxx.h
index c1d452e..61a500f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -182,18 +182,33 @@ private:
 template <typename T>
 class Slice<T>::iterator final {
 public:
-  using difference_type = std::ptrdiff_t;
+  using iterator_category = std::random_access_iterator_tag;
   using value_type = T;
+  using difference_type = std::ptrdiff_t;
   using pointer = typename std::add_pointer<T>::type;
   using reference = typename std::add_lvalue_reference<T>::type;
-  using iterator_category = std::forward_iterator_tag;
 
-  T &operator*() const noexcept;
-  T *operator->() const noexcept;
+  reference operator*() const noexcept;
+  pointer operator->() const noexcept;
+  reference operator[](difference_type) const noexcept;
+
   iterator &operator++() noexcept;
   iterator operator++(int) noexcept;
+  iterator &operator--() noexcept;
+  iterator operator--(int) noexcept;
+
+  iterator &operator+=(difference_type) noexcept;
+  iterator &operator-=(difference_type) noexcept;
+  iterator operator+(difference_type) const noexcept;
+  iterator operator-(difference_type) const noexcept;
+  difference_type operator-(const iterator &) const noexcept;
+
   bool operator==(const iterator &) const noexcept;
   bool operator!=(const iterator &) const noexcept;
+  bool operator<(const iterator &) const noexcept;
+  bool operator<=(const iterator &) const noexcept;
+  bool operator>(const iterator &) const noexcept;
+  bool operator>=(const iterator &) const noexcept;
 
 private:
   friend class Slice;
@@ -557,16 +572,24 @@ T &Slice<T>::back() const noexcept {
 }
 
 template <typename T>
-T &Slice<T>::iterator::operator*() const noexcept {
+typename Slice<T>::iterator::reference
+Slice<T>::iterator::operator*() const noexcept {
   return *this->pos;
 }
 
 template <typename T>
-T *Slice<T>::iterator::operator->() const noexcept {
+typename Slice<T>::iterator::pointer
+Slice<T>::iterator::operator->() const noexcept {
   return this->pos;
 }
 
 template <typename T>
+typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return this->pos[n];
+}
+
+template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
   ++this->pos;
   return *this;
@@ -580,6 +603,51 @@ typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
 }
 
 template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {
+  --this->pos;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {
+  auto ret = iterator(*this);
+  --this->pos;
+  return ret;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator+=(
+    typename Slice<T>::iterator::difference_type n) noexcept {
+  this->pos += n;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator &Slice<T>::iterator::operator-=(
+    typename Slice<T>::iterator::difference_type n) noexcept {
+  this->pos -= n;
+  return *this;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator+(
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return iterator(*this) += n;
+}
+
+template <typename T>
+typename Slice<T>::iterator Slice<T>::iterator::operator-(
+    typename Slice<T>::iterator::difference_type n) const noexcept {
+  return iterator(*this) -= n;
+}
+
+template <typename T>
+typename Slice<T>::iterator::difference_type
+Slice<T>::iterator::operator-(const iterator &other) const noexcept {
+  return std::distance(other.pos, this->pos);
+}
+
+template <typename T>
 bool Slice<T>::iterator::operator==(const iterator &other) const noexcept {
   return this->pos == other.pos;
 }
@@ -590,6 +658,26 @@ bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept {
 }
 
 template <typename T>
+bool Slice<T>::iterator::operator<(const iterator &other) const noexcept {
+  return this->pos < other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator<=(const iterator &other) const noexcept {
+  return this->pos <= other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator>(const iterator &other) const noexcept {
+  return this->pos > other.pos;
+}
+
+template <typename T>
+bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
+  return this->pos >= other.pos;
+}
+
+template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
   it.pos = this->ptr;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7504704..df5c279 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -120,6 +120,7 @@ pub mod ffi {
         fn c_take_str(s: &str);
         fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
+        fn c_take_slice_shared_sort(s: &mut [Shared]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 05ff4b8..2bb7d71 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -280,6 +280,15 @@ void c_take_slice_shared(rust::Slice<const Shared> s) {
   }
 }
 
+void c_take_slice_shared_sort(rust::Slice<Shared> s) {
+  // Exercise requirements of RandomAccessIterator.
+  // https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
+  std::sort(s.begin(), s.end());
+  if (s[0].z == 0 && s[1].z == 2 && s[2].z == 4 && s[3].z == 7) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 51ab51d..50a8005 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -123,6 +123,7 @@ void c_take_ref_ns_c(const ::H::H &h);
 void c_take_str(rust::Str s);
 void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
+void c_take_slice_shared_sort(rust::Slice<Shared> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 60bf1bd..0620a9c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -125,6 +125,17 @@ fn test_c_take() {
         ffi::Shared { z: 2020 },
         ffi::Shared { z: 2021 },
     ]));
+    let shared_sort_slice = &mut [
+        ffi::Shared { z: 2 },
+        ffi::Shared { z: 0 },
+        ffi::Shared { z: 7 },
+        ffi::Shared { z: 4 },
+    ];
+    check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
+    assert_eq!(shared_sort_slice[0].z, 0);
+    assert_eq!(shared_sort_slice[1].z, 2);
+    assert_eq!(shared_sort_slice[2].z, 4);
+    assert_eq!(shared_sort_slice[3].z, 7);
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From a1ddbf846f775df22bbf57865dad03e107e4160c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:52:02 +0000
Subject: [PATCH 1813/2232] Track stride as runtime value in Slice iterator


---

diff --git a/include/cxx.h b/include/cxx.h
index 61a500f..12b2d5c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -212,7 +212,8 @@ public:
 
 private:
   friend class Slice;
-  T *pos;
+  void *pos;
+  std::size_t stride;
 };
 #endif // CXXBRIDGE1_RUST_SLICE
 
@@ -574,77 +575,84 @@ T &Slice<T>::back() const noexcept {
 template <typename T>
 typename Slice<T>::iterator::reference
 Slice<T>::iterator::operator*() const noexcept {
-  return *this->pos;
+  return *static_cast<T *>(this->pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator::pointer
 Slice<T>::iterator::operator->() const noexcept {
-  return this->pos;
+  return static_cast<T *>(this->pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return this->pos[n];
+  auto pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *static_cast<T *>(pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
-  ++this->pos;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
   auto ret = iterator(*this);
-  ++this->pos;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {
-  --this->pos;
+  this->pos = static_cast<char *>(this->pos) - this->stride;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {
   auto ret = iterator(*this);
-  --this->pos;
+  this->pos = static_cast<char *>(this->pos) - this->stride;
   return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator+=(
     typename Slice<T>::iterator::difference_type n) noexcept {
-  this->pos += n;
+  this->pos = static_cast<char *>(this->pos) + this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator-=(
     typename Slice<T>::iterator::difference_type n) noexcept {
-  this->pos -= n;
+  this->pos = static_cast<char *>(this->pos) - this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator+(
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return iterator(*this) += n;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) + this->stride * n;
+  return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator-(
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return iterator(*this) -= n;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) - this->stride * n;
+  return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator::difference_type
 Slice<T>::iterator::operator-(const iterator &other) const noexcept {
-  return std::distance(other.pos, this->pos);
+  auto diff = std::distance(static_cast<char *>(other.pos),
+                            static_cast<char *>(this->pos));
+  return diff / this->stride;
 }
 
 template <typename T>
@@ -680,14 +688,15 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = this->ptr;
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->ptr);
+  it.stride = sizeof(T);
   return it;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::end() const noexcept {
   iterator it = this->begin();
-  it.pos += this->len;
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
   return it;
 }
 #endif // CXXBRIDGE1_RUST_SLICE

From fb1b6a7d0b8614ec29c6d9d1d3239a9c2feb2913 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:59:38 +0000
Subject: [PATCH 1814/2232] Merge pull request #600 from dtolnay/stride


Track stride as runtime value in Slice iterator
---

diff --git a/include/cxx.h b/include/cxx.h
index 61a500f..12b2d5c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -212,7 +212,8 @@ public:
 
 private:
   friend class Slice;
-  T *pos;
+  void *pos;
+  std::size_t stride;
 };
 #endif // CXXBRIDGE1_RUST_SLICE
 
@@ -574,77 +575,84 @@ T &Slice<T>::back() const noexcept {
 template <typename T>
 typename Slice<T>::iterator::reference
 Slice<T>::iterator::operator*() const noexcept {
-  return *this->pos;
+  return *static_cast<T *>(this->pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator::pointer
 Slice<T>::iterator::operator->() const noexcept {
-  return this->pos;
+  return static_cast<T *>(this->pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return this->pos[n];
+  auto pos = static_cast<char *>(this->pos) + this->stride * n;
+  return *static_cast<T *>(pos);
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept {
-  ++this->pos;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept {
   auto ret = iterator(*this);
-  ++this->pos;
+  this->pos = static_cast<char *>(this->pos) + this->stride;
   return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept {
-  --this->pos;
+  this->pos = static_cast<char *>(this->pos) - this->stride;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept {
   auto ret = iterator(*this);
-  --this->pos;
+  this->pos = static_cast<char *>(this->pos) - this->stride;
   return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator+=(
     typename Slice<T>::iterator::difference_type n) noexcept {
-  this->pos += n;
+  this->pos = static_cast<char *>(this->pos) + this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator &Slice<T>::iterator::operator-=(
     typename Slice<T>::iterator::difference_type n) noexcept {
-  this->pos -= n;
+  this->pos = static_cast<char *>(this->pos) - this->stride * n;
   return *this;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator+(
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return iterator(*this) += n;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) + this->stride * n;
+  return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::iterator::operator-(
     typename Slice<T>::iterator::difference_type n) const noexcept {
-  return iterator(*this) -= n;
+  auto ret = iterator(*this);
+  ret.pos = static_cast<char *>(this->pos) - this->stride * n;
+  return ret;
 }
 
 template <typename T>
 typename Slice<T>::iterator::difference_type
 Slice<T>::iterator::operator-(const iterator &other) const noexcept {
-  return std::distance(other.pos, this->pos);
+  auto diff = std::distance(static_cast<char *>(other.pos),
+                            static_cast<char *>(this->pos));
+  return diff / this->stride;
 }
 
 template <typename T>
@@ -680,14 +688,15 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = this->ptr;
+  it.pos = const_cast<typename std::remove_const<T>::type *>(this->ptr);
+  it.stride = sizeof(T);
   return it;
 }
 
 template <typename T>
 typename Slice<T>::iterator Slice<T>::end() const noexcept {
   iterator it = this->begin();
-  it.pos += this->len;
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
   return it;
 }
 #endif // CXXBRIDGE1_RUST_SLICE

From 6f92baa8ffa0f22343a2616a30adca20bee19530 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 20:59:47 +0000
Subject: [PATCH 1815/2232] Obtain Slice iterator stride in a way that works for opaque types


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index d43038b..409a5d1 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
+        builtin.layout = true;
         builtin.panic = true;
     }
 
@@ -141,6 +142,12 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "class Opaque;");
     }
 
+    if builtin.rust_slice {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "::std::size_t size_of();");
+    }
+
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
     ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
diff --git a/include/cxx.h b/include/cxx.h
index 12b2d5c..8ca1a12 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -689,7 +689,7 @@ template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->ptr);
-  it.stride = sizeof(T);
+  it.stride = size_of<T>();
   return it;
 }
 

From f8ea533150b3d82df03bdf2899d4ffa7ea374cd0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:07:37 +0000
Subject: [PATCH 1816/2232] Merge pull request #601 from dtolnay/slice


Obtain Slice iterator stride in a way that works for opaque types
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index d43038b..409a5d1 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;
+        builtin.layout = true;
         builtin.panic = true;
     }
 
@@ -141,6 +142,12 @@ pub(super) fn write(out: &mut OutFile) {
         writeln!(out, "class Opaque;");
     }
 
+    if builtin.rust_slice {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "::std::size_t size_of();");
+    }
+
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
     ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
     ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
diff --git a/include/cxx.h b/include/cxx.h
index 12b2d5c..8ca1a12 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -689,7 +689,7 @@ template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->ptr);
-  it.stride = sizeof(T);
+  it.stride = size_of<T>();
   return it;
 }
 

From eee622c4acd7f6c23ce2ca697eb61515929422d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:08:09 +0000
Subject: [PATCH 1817/2232] Obtain accurate alignment for empty slice of opaque Rust type


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 409a5d1..2e75666 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -146,6 +146,8 @@ pub(super) fn write(out: &mut OutFile) {
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "::std::size_t size_of();");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "::std::size_t align_of();");
     }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
diff --git a/include/cxx.h b/include/cxx.h
index 8ca1a12..d795918 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -521,7 +521,8 @@ inline std::size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(alignof(T))), len(0) {}
+Slice<T>::Slice() noexcept
+    : ptr(reinterpret_cast<T *>(align_of<T>())), len(0) {}
 
 template <typename T>
 Slice<T>::Slice(T *s, std::size_t count) noexcept : ptr(s), len(count) {}

From b97573b4e1b6f30887d9a044ff9daa889f023b1f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:19:37 +0000
Subject: [PATCH 1818/2232] Merge pull request #602 from dtolnay/slice


Obtain accurate alignment for empty slice of opaque Rust type
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 409a5d1..2e75666 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -146,6 +146,8 @@ pub(super) fn write(out: &mut OutFile) {
         out.next_section();
         writeln!(out, "template <typename T>");
         writeln!(out, "::std::size_t size_of();");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "::std::size_t align_of();");
     }
 
     ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
diff --git a/include/cxx.h b/include/cxx.h
index 8ca1a12..d795918 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -521,7 +521,8 @@ inline std::size_t Str::length() const noexcept { return this->len; }
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept : ptr(reinterpret_cast<T *>(alignof(T))), len(0) {}
+Slice<T>::Slice() noexcept
+    : ptr(reinterpret_cast<T *>(align_of<T>())), len(0) {}
 
 template <typename T>
 Slice<T>::Slice(T *s, std::size_t count) noexcept : ptr(s), len(count) {}

From 3adf3c81b6d41d7022f93d434ef03db7665dcaa9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:19:45 +0000
Subject: [PATCH 1819/2232] Allow passing slice of extern Rust type across FFI


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2ac800b..f43c1e2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -210,6 +210,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRef(_) => false,
+        Type::Ident(ident) => !is_opaque_cxx(cx, &ident.rust),
         element => !is_unsized(cx, element),
     };
 
@@ -217,9 +218,7 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
         let mutable = if ty.mutable { "mut " } else { "" };
         let mut msg = format!("unsupported &{}[T] element type", mutable);
         if let Type::Ident(ident) = &ty.inner {
-            if cx.types.rust.contains(&ident.rust) {
-                msg += ": opaque Rust type is not supported yet";
-            } else if is_opaque_cxx(cx, &ident.rust) {
+            if is_opaque_cxx(cx, &ident.rust) {
                 msg += ": opaque C++ type is not supported yet";
             }
         }

From fc935fb2b75c1e14566ebc65354ddbffac2892a8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:19:45 +0000
Subject: [PATCH 1820/2232] Add test of rust::Slice of opaque Rust type


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index df5c279..6814d00 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -121,6 +121,7 @@ pub mod ffi {
         fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
         fn c_take_slice_shared_sort(s: &mut [Shared]);
+        fn c_take_slice_r(s: &[R]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2bb7d71..f0bab82 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -289,6 +289,12 @@ void c_take_slice_shared_sort(rust::Slice<Shared> s) {
   }
 }
 
+void c_take_slice_r(rust::Slice<const R> s) {
+  if (s.size() == 2 && s[0].get() == 2020 && s[1].get() == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 50a8005..7dfaa3d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -124,6 +124,7 @@ void c_take_str(rust::Str s);
 void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_slice_shared_sort(rust::Slice<Shared> s);
+void c_take_slice_r(rust::Slice<const R> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 0620a9c..6178d89 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -132,6 +132,7 @@ fn test_c_take() {
         ffi::Shared { z: 4 },
     ];
     check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
+    check!(ffi::c_take_slice_r(&[R(2020), R(2021)]));
     assert_eq!(shared_sort_slice[0].z, 0);
     assert_eq!(shared_sort_slice[1].z, 2);
     assert_eq!(shared_sort_slice[2].z, 4);

From 5ce110e8075c32130c2f3fda9c500b8f956426e6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:19:45 +0000
Subject: [PATCH 1821/2232] Update Slice implementation to respect runtime size_of


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 2e75666..9b8d45e 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -279,12 +279,7 @@ pub(super) fn write(out: &mut OutFile) {
                 out,
                 "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
             );
-            writeln!(out, "    return repr::PtrLen{{");
-            writeln!(
-                out,
-                "        const_cast<typename ::std::remove_const<T>::type *>(slice.ptr),",
-            );
-            writeln!(out, "        slice.len}};");
+            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
             writeln!(out, "  }}");
         }
         writeln!(out, "}};");
diff --git a/include/cxx.h b/include/cxx.h
index d795918..a4901e1 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -175,7 +175,7 @@ private:
   friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
-  T *ptr;
+  void *ptr;
   std::size_t len;
 };
 
@@ -522,14 +522,15 @@ inline std::size_t Str::length() const noexcept { return this->len; }
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
 Slice<T>::Slice() noexcept
-    : ptr(reinterpret_cast<T *>(align_of<T>())), len(0) {}
+    : ptr(reinterpret_cast<void *>(align_of<T>())), len(0) {}
 
 template <typename T>
-Slice<T>::Slice(T *s, std::size_t count) noexcept : ptr(s), len(count) {}
+Slice<T>::Slice(T *s, std::size_t count) noexcept
+    : ptr(const_cast<typename std::remove_const<T>::type *>(s)), len(count) {}
 
 template <typename T>
 T *Slice<T>::data() const noexcept {
-  return this->ptr;
+  return reinterpret_cast<T *>(this->ptr);
 }
 
 template <typename T>
@@ -550,7 +551,8 @@ bool Slice<T>::empty() const noexcept {
 template <typename T>
 T &Slice<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
-  return this->ptr[n];
+  auto pos = static_cast<char *>(this->ptr) + size_of<T>() * n;
+  return *reinterpret_cast<T *>(pos);
 }
 
 template <typename T>
@@ -564,13 +566,13 @@ T &Slice<T>::at(std::size_t n) const {
 template <typename T>
 T &Slice<T>::front() const noexcept {
   assert(!this->empty());
-  return this->ptr[0];
+  return (*this)[0];
 }
 
 template <typename T>
 T &Slice<T>::back() const noexcept {
   assert(!this->empty());
-  return this->ptr[this->len - 1];
+  return (*this)[this->len - 1];
 }
 
 template <typename T>
@@ -689,7 +691,7 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = const_cast<typename std::remove_const<T>::type *>(this->ptr);
+  it.pos = this->ptr;
   it.stride = size_of<T>();
   return it;
 }

From d5e3ef8d73447545646d846408642c091aed2e25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:28:47 +0000
Subject: [PATCH 1822/2232] Merge pull request #603 from dtolnay/slice


Allow passing slice of extern Rust type across FFI
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2ac800b..f43c1e2 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -210,6 +210,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRef(_) => false,
+        Type::Ident(ident) => !is_opaque_cxx(cx, &ident.rust),
         element => !is_unsized(cx, element),
     };
 
@@ -217,9 +218,7 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
         let mutable = if ty.mutable { "mut " } else { "" };
         let mut msg = format!("unsupported &{}[T] element type", mutable);
         if let Type::Ident(ident) = &ty.inner {
-            if cx.types.rust.contains(&ident.rust) {
-                msg += ": opaque Rust type is not supported yet";
-            } else if is_opaque_cxx(cx, &ident.rust) {
+            if is_opaque_cxx(cx, &ident.rust) {
                 msg += ": opaque C++ type is not supported yet";
             }
         }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index df5c279..6814d00 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -121,6 +121,7 @@ pub mod ffi {
         fn c_take_slice_char(s: &[c_char]);
         fn c_take_slice_shared(s: &[Shared]);
         fn c_take_slice_shared_sort(s: &mut [Shared]);
+        fn c_take_slice_r(s: &[R]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 2bb7d71..f0bab82 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -289,6 +289,12 @@ void c_take_slice_shared_sort(rust::Slice<Shared> s) {
   }
 }
 
+void c_take_slice_r(rust::Slice<const R> s) {
+  if (s.size() == 2 && s[0].get() == 2020 && s[1].get() == 2021) {
+    cxx_test_suite_set_correct();
+  }
+}
+
 void c_take_rust_string(rust::String s) {
   if (std::string(s) == "2020") {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 50a8005..7dfaa3d 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -124,6 +124,7 @@ void c_take_str(rust::Str s);
 void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_slice_shared_sort(rust::Slice<Shared> s);
+void c_take_slice_r(rust::Slice<const R> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 0620a9c..6178d89 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -132,6 +132,7 @@ fn test_c_take() {
         ffi::Shared { z: 4 },
     ];
     check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
+    check!(ffi::c_take_slice_r(&[R(2020), R(2021)]));
     assert_eq!(shared_sort_slice[0].z, 0);
     assert_eq!(shared_sort_slice[1].z, 2);
     assert_eq!(shared_sort_slice[2].z, 4);

From e1df7ddba0f819b8fb4ce8f3cb9ddf9ad4d6e037 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:29:06 +0000
Subject: [PATCH 1823/2232] Eliminate Vec stride symbol in favor of size_of


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index bae9cfe..652ebf3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1465,11 +1465,6 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
         "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
         instance, inner,
     );
-    writeln!(
-        out,
-        "::std::size_t cxxbridge1$rust_vec${}$stride() noexcept;",
-        instance,
-    );
     writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
 }
 
@@ -1569,11 +1564,6 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
         instance,
     );
     writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "::std::size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge1$rust_vec${}$stride();", instance);
-    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
diff --git a/include/cxx.h b/include/cxx.h
index a4901e1..eadc313 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -313,7 +313,6 @@ public:
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
 private:
-  static std::size_t stride() noexcept;
   void reserve_total(std::size_t cap) noexcept;
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
@@ -883,7 +882,7 @@ template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
-  return *reinterpret_cast<const T *>(data + n * this->stride());
+  return *reinterpret_cast<const T *>(data + n * size_of<T>());
 }
 
 template <typename T>
@@ -910,7 +909,7 @@ template <typename T>
 T &Vec<T>::operator[](std::size_t n) noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<char *>(this->data());
-  return *reinterpret_cast<T *>(data + n * this->stride());
+  return *reinterpret_cast<T *>(data + n * size_of<T>());
 }
 
 template <typename T>
@@ -954,7 +953,7 @@ void Vec<T>::emplace_back(Args &&... args) {
   auto size = this->size();
   this->reserve_total(size + 1);
   ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
-                               size * this->stride()))
+                               size * size_of<T>()))
       T(std::forward<Args>(args)...);
   this->set_len(size + 1);
 }
@@ -1076,7 +1075,7 @@ template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = this->stride();
+  it.stride = size_of<T>();
   return it;
 }
 
@@ -1101,7 +1100,7 @@ template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = this->stride();
+  it.stride = size_of<T>();
   return it;
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 381bf5b..d892599 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1029,7 +1029,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_data = format!("{}data", link_prefix);
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
-    let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem.rust);
     let local_new = format_ident!("{}new", local_prefix);
@@ -1039,7 +1038,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let local_data = format_ident!("{}data", local_prefix);
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
-    let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = elem.span();
     quote_spanned! {span=>
@@ -1080,11 +1078,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
         unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
             (*this).set_len(len);
         }
-        #[doc(hidden)]
-        #[export_name = #link_stride]
-        unsafe extern "C" fn #local_stride() -> usize {
-            ::std::mem::size_of::<#elem>()
-        }
     }
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index b171583..e5853b9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -450,8 +450,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
       rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept;                     \
   void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,     \
-                                                 std::size_t len) noexcept;    \
-  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
+                                                 std::size_t len) noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
@@ -481,10 +480,6 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   template <>                                                                  \
   void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept {                      \
     cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len);                      \
-  }                                                                            \
-  template <>                                                                  \
-  std::size_t Vec<CXX_TYPE>::stride() noexcept {                               \
-    return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
 #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE)                                    \
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 6aa0b76..60b9cfa 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -53,12 +53,6 @@ macro_rules! rust_vec_shims {
                     (*this).repr.set_len(len);
                 }
             }
-            attr! {
-                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$stride")]
-                unsafe extern "C" fn __stride() -> usize {
-                    mem::size_of::<$ty>()
-                }
-            }
         };
     };
 }

From 4094affae0279bc0494e4c6cc6280463fbb9eb18 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:38:35 +0000
Subject: [PATCH 1824/2232] Merge pull request #604 from dtolnay/vecstride


Eliminate Vec stride symbol in favor of size_of
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index bae9cfe..652ebf3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1465,11 +1465,6 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
         "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
         instance, inner,
     );
-    writeln!(
-        out,
-        "::std::size_t cxxbridge1$rust_vec${}$stride() noexcept;",
-        instance,
-    );
     writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
 }
 
@@ -1569,11 +1564,6 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
         instance,
     );
     writeln!(out, "}}");
-
-    writeln!(out, "template <>");
-    writeln!(out, "::std::size_t Vec<{}>::stride() noexcept {{", inner);
-    writeln!(out, "  return cxxbridge1$rust_vec${}$stride();", instance);
-    writeln!(out, "}}");
 }
 
 fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
diff --git a/include/cxx.h b/include/cxx.h
index a4901e1..eadc313 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -313,7 +313,6 @@ public:
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
 private:
-  static std::size_t stride() noexcept;
   void reserve_total(std::size_t cap) noexcept;
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
@@ -883,7 +882,7 @@ template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
-  return *reinterpret_cast<const T *>(data + n * this->stride());
+  return *reinterpret_cast<const T *>(data + n * size_of<T>());
 }
 
 template <typename T>
@@ -910,7 +909,7 @@ template <typename T>
 T &Vec<T>::operator[](std::size_t n) noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<char *>(this->data());
-  return *reinterpret_cast<T *>(data + n * this->stride());
+  return *reinterpret_cast<T *>(data + n * size_of<T>());
 }
 
 template <typename T>
@@ -954,7 +953,7 @@ void Vec<T>::emplace_back(Args &&... args) {
   auto size = this->size();
   this->reserve_total(size + 1);
   ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
-                               size * this->stride()))
+                               size * size_of<T>()))
       T(std::forward<Args>(args)...);
   this->set_len(size + 1);
 }
@@ -1076,7 +1075,7 @@ template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
   iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = this->stride();
+  it.stride = size_of<T>();
   return it;
 }
 
@@ -1101,7 +1100,7 @@ template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
   const_iterator it;
   it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = this->stride();
+  it.stride = size_of<T>();
   return it;
 }
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 381bf5b..d892599 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1029,7 +1029,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let link_data = format!("{}data", link_prefix);
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
-    let link_stride = format!("{}stride", link_prefix);
 
     let local_prefix = format_ident!("{}__vec_", elem.rust);
     let local_new = format_ident!("{}new", local_prefix);
@@ -1039,7 +1038,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     let local_data = format_ident!("{}data", local_prefix);
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
-    let local_stride = format_ident!("{}stride", local_prefix);
 
     let span = elem.span();
     quote_spanned! {span=>
@@ -1080,11 +1078,6 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
         unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
             (*this).set_len(len);
         }
-        #[doc(hidden)]
-        #[export_name = #link_stride]
-        unsafe extern "C" fn #local_stride() -> usize {
-            ::std::mem::size_of::<#elem>()
-        }
     }
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index b171583..e5853b9 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -450,8 +450,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(                        \
       rust::Vec<CXX_TYPE> *ptr, std::size_t cap) noexcept;                     \
   void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr,     \
-                                                 std::size_t len) noexcept;    \
-  std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$stride() noexcept;
+                                                 std::size_t len) noexcept;
 
 #define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
   template <>                                                                  \
@@ -481,10 +480,6 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   template <>                                                                  \
   void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept {                      \
     cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len);                      \
-  }                                                                            \
-  template <>                                                                  \
-  std::size_t Vec<CXX_TYPE>::stride() noexcept {                               \
-    return cxxbridge1$rust_vec$##RUST_TYPE##$stride();                         \
   }
 
 #define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE)                                    \
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 6aa0b76..60b9cfa 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -53,12 +53,6 @@ macro_rules! rust_vec_shims {
                     (*this).repr.set_len(len);
                 }
             }
-            attr! {
-                #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$stride")]
-                unsafe extern "C" fn __stride() -> usize {
-                    mem::size_of::<$ty>()
-                }
-            }
         };
     };
 }

From 725bf505b40ce2bc728b21a2d625f0bac336e25e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:38:44 +0000
Subject: [PATCH 1825/2232] Reuse Slice<T>'s iterator for Vec iteration too


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 9b8d45e..b5c6e4d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -59,6 +59,20 @@ pub(super) fn write(out: &mut OutFile) {
         builtin.friend_impl = true;
     }
 
+    if builtin.rust_vec {
+        include.algorithm = true;
+        include.array = true;
+        include.cstddef = true;
+        include.initializer_list = true;
+        include.iterator = true;
+        include.new = true;
+        include.type_traits = true;
+        include.utility = true;
+        builtin.panic = true;
+        builtin.rust_slice = true;
+        builtin.unsafe_bitcopy = true;
+    }
+
     if builtin.rust_slice {
         include.cstddef = true;
         include.iterator = true;
@@ -74,19 +88,6 @@ pub(super) fn write(out: &mut OutFile) {
         include.utility = true;
     }
 
-    if builtin.rust_vec {
-        include.algorithm = true;
-        include.array = true;
-        include.cstddef = true;
-        include.initializer_list = true;
-        include.iterator = true;
-        include.new = true;
-        include.type_traits = true;
-        include.utility = true;
-        builtin.panic = true;
-        builtin.unsafe_bitcopy = true;
-    }
-
     if builtin.rust_fn {
         include.utility = true;
     }
diff --git a/include/cxx.h b/include/cxx.h
index eadc313..95f9a06 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -299,11 +299,11 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
-  class iterator;
+  using iterator = typename Slice<T>::iterator;
   iterator begin() noexcept;
   iterator end() noexcept;
 
-  using const_iterator = typename Vec<const T>::iterator;
+  using const_iterator = typename Slice<const T>::iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
@@ -320,44 +320,6 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
 };
-
-template <typename T>
-class Vec<T>::iterator final {
-public:
-  using iterator_category = std::random_access_iterator_tag;
-  using value_type = T;
-  using difference_type = std::ptrdiff_t;
-  using pointer = typename std::add_pointer<T>::type;
-  using reference = typename std::add_lvalue_reference<T>::type;
-
-  reference operator*() const noexcept;
-  pointer operator->() const noexcept;
-  reference operator[](difference_type) const noexcept;
-
-  iterator &operator++() noexcept;
-  iterator operator++(int) noexcept;
-  iterator &operator--() noexcept;
-  iterator operator--(int) noexcept;
-
-  iterator &operator+=(difference_type) noexcept;
-  iterator &operator-=(difference_type) noexcept;
-  iterator operator+(difference_type) const noexcept;
-  iterator operator-(difference_type) const noexcept;
-  difference_type operator-(const iterator &) const noexcept;
-
-  bool operator==(const iterator &) const noexcept;
-  bool operator!=(const iterator &) const noexcept;
-  bool operator<(const iterator &) const noexcept;
-  bool operator<=(const iterator &) const noexcept;
-  bool operator>(const iterator &) const noexcept;
-  bool operator>=(const iterator &) const noexcept;
-
-private:
-  friend class Vec;
-  friend class Vec<typename std::remove_const<T>::type>;
-  void *pos;
-  std::size_t stride;
-};
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN
@@ -959,131 +921,13 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
-typename Vec<T>::iterator::reference
-Vec<T>::iterator::operator*() const noexcept {
-  return *static_cast<T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator::pointer
-Vec<T>::iterator::operator->() const noexcept {
-  return static_cast<T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto pos = static_cast<char *>(this->pos) + this->stride * n;
-  return *static_cast<T *>(pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
-  this->pos = static_cast<char *>(this->pos) + this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
-  auto ret = iterator(*this);
-  this->pos = static_cast<char *>(this->pos) + this->stride;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator--() noexcept {
-  this->pos = static_cast<char *>(this->pos) - this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
-  auto ret = iterator(*this);
-  this->pos = static_cast<char *>(this->pos) - this->stride;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator+=(
-    typename Vec<T>::iterator::difference_type n) noexcept {
-  this->pos = static_cast<char *>(this->pos) + this->stride * n;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator-=(
-    typename Vec<T>::iterator::difference_type n) noexcept {
-  this->pos = static_cast<char *>(this->pos) - this->stride * n;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator+(
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto ret = iterator(*this);
-  ret.pos = static_cast<char *>(this->pos) + this->stride * n;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator-(
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto ret = iterator(*this);
-  ret.pos = static_cast<char *>(this->pos) - this->stride * n;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator::difference_type
-Vec<T>::iterator::operator-(const iterator &other) const noexcept {
-  auto diff = std::distance(static_cast<char *>(other.pos),
-                            static_cast<char *>(this->pos));
-  return diff / this->stride;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
-  return this->pos == other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
-  return this->pos != other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
-  return this->pos < other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
-  return this->pos <= other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
-  return this->pos > other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
-  return this->pos >= other.pos;
-}
-
-template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
-  iterator it;
-  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = size_of<T>();
-  return it;
+  return Slice<T>(this->data(), this->size()).begin();
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::end() noexcept {
-  iterator it = this->begin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
-  return it;
+  return Slice<T>(this->data(), this->size()).end();
 }
 
 template <typename T>
@@ -1098,17 +942,12 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
-  const_iterator it;
-  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = size_of<T>();
-  return it;
+  return Slice<const T>(this->data(), this->size()).begin();
 }
 
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
-  const_iterator it = this->cbegin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
-  return it;
+  return Slice<const T>(this->data(), this->size()).end();
 }
 
 // Internal API only intended for the cxxbridge code generator.

From b592fe509fd111b1fd273eabd30bd6965213c562 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 21:47:48 +0000
Subject: [PATCH 1826/2232] Merge pull request #605 from dtolnay/iterator


Reuse Slice<T>'s iterator for Vec iteration too
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 9b8d45e..b5c6e4d 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -59,6 +59,20 @@ pub(super) fn write(out: &mut OutFile) {
         builtin.friend_impl = true;
     }
 
+    if builtin.rust_vec {
+        include.algorithm = true;
+        include.array = true;
+        include.cstddef = true;
+        include.initializer_list = true;
+        include.iterator = true;
+        include.new = true;
+        include.type_traits = true;
+        include.utility = true;
+        builtin.panic = true;
+        builtin.rust_slice = true;
+        builtin.unsafe_bitcopy = true;
+    }
+
     if builtin.rust_slice {
         include.cstddef = true;
         include.iterator = true;
@@ -74,19 +88,6 @@ pub(super) fn write(out: &mut OutFile) {
         include.utility = true;
     }
 
-    if builtin.rust_vec {
-        include.algorithm = true;
-        include.array = true;
-        include.cstddef = true;
-        include.initializer_list = true;
-        include.iterator = true;
-        include.new = true;
-        include.type_traits = true;
-        include.utility = true;
-        builtin.panic = true;
-        builtin.unsafe_bitcopy = true;
-    }
-
     if builtin.rust_fn {
         include.utility = true;
     }
diff --git a/include/cxx.h b/include/cxx.h
index eadc313..95f9a06 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -299,11 +299,11 @@ public:
   template <typename... Args>
   void emplace_back(Args &&... args);
 
-  class iterator;
+  using iterator = typename Slice<T>::iterator;
   iterator begin() noexcept;
   iterator end() noexcept;
 
-  using const_iterator = typename Vec<const T>::iterator;
+  using const_iterator = typename Slice<const T>::iterator;
   const_iterator begin() const noexcept;
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
@@ -320,44 +320,6 @@ private:
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
 };
-
-template <typename T>
-class Vec<T>::iterator final {
-public:
-  using iterator_category = std::random_access_iterator_tag;
-  using value_type = T;
-  using difference_type = std::ptrdiff_t;
-  using pointer = typename std::add_pointer<T>::type;
-  using reference = typename std::add_lvalue_reference<T>::type;
-
-  reference operator*() const noexcept;
-  pointer operator->() const noexcept;
-  reference operator[](difference_type) const noexcept;
-
-  iterator &operator++() noexcept;
-  iterator operator++(int) noexcept;
-  iterator &operator--() noexcept;
-  iterator operator--(int) noexcept;
-
-  iterator &operator+=(difference_type) noexcept;
-  iterator &operator-=(difference_type) noexcept;
-  iterator operator+(difference_type) const noexcept;
-  iterator operator-(difference_type) const noexcept;
-  difference_type operator-(const iterator &) const noexcept;
-
-  bool operator==(const iterator &) const noexcept;
-  bool operator!=(const iterator &) const noexcept;
-  bool operator<(const iterator &) const noexcept;
-  bool operator<=(const iterator &) const noexcept;
-  bool operator>(const iterator &) const noexcept;
-  bool operator>=(const iterator &) const noexcept;
-
-private:
-  friend class Vec;
-  friend class Vec<typename std::remove_const<T>::type>;
-  void *pos;
-  std::size_t stride;
-};
 #endif // CXXBRIDGE1_RUST_VEC
 
 #ifndef CXXBRIDGE1_RUST_FN
@@ -959,131 +921,13 @@ void Vec<T>::emplace_back(Args &&... args) {
 }
 
 template <typename T>
-typename Vec<T>::iterator::reference
-Vec<T>::iterator::operator*() const noexcept {
-  return *static_cast<T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator::pointer
-Vec<T>::iterator::operator->() const noexcept {
-  return static_cast<T *>(this->pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator::reference Vec<T>::iterator::operator[](
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto pos = static_cast<char *>(this->pos) + this->stride * n;
-  return *static_cast<T *>(pos);
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator++() noexcept {
-  this->pos = static_cast<char *>(this->pos) + this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator++(int) noexcept {
-  auto ret = iterator(*this);
-  this->pos = static_cast<char *>(this->pos) + this->stride;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator--() noexcept {
-  this->pos = static_cast<char *>(this->pos) - this->stride;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator--(int) noexcept {
-  auto ret = iterator(*this);
-  this->pos = static_cast<char *>(this->pos) - this->stride;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator+=(
-    typename Vec<T>::iterator::difference_type n) noexcept {
-  this->pos = static_cast<char *>(this->pos) + this->stride * n;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator &Vec<T>::iterator::operator-=(
-    typename Vec<T>::iterator::difference_type n) noexcept {
-  this->pos = static_cast<char *>(this->pos) - this->stride * n;
-  return *this;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator+(
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto ret = iterator(*this);
-  ret.pos = static_cast<char *>(this->pos) + this->stride * n;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator Vec<T>::iterator::operator-(
-    typename Vec<T>::iterator::difference_type n) const noexcept {
-  auto ret = iterator(*this);
-  ret.pos = static_cast<char *>(this->pos) - this->stride * n;
-  return ret;
-}
-
-template <typename T>
-typename Vec<T>::iterator::difference_type
-Vec<T>::iterator::operator-(const iterator &other) const noexcept {
-  auto diff = std::distance(static_cast<char *>(other.pos),
-                            static_cast<char *>(this->pos));
-  return diff / this->stride;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator==(const iterator &other) const noexcept {
-  return this->pos == other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator!=(const iterator &other) const noexcept {
-  return this->pos != other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator<(const iterator &other) const noexcept {
-  return this->pos < other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator<=(const iterator &other) const noexcept {
-  return this->pos <= other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator>(const iterator &other) const noexcept {
-  return this->pos > other.pos;
-}
-
-template <typename T>
-bool Vec<T>::iterator::operator>=(const iterator &other) const noexcept {
-  return this->pos >= other.pos;
-}
-
-template <typename T>
 typename Vec<T>::iterator Vec<T>::begin() noexcept {
-  iterator it;
-  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = size_of<T>();
-  return it;
+  return Slice<T>(this->data(), this->size()).begin();
 }
 
 template <typename T>
 typename Vec<T>::iterator Vec<T>::end() noexcept {
-  iterator it = this->begin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
-  return it;
+  return Slice<T>(this->data(), this->size()).end();
 }
 
 template <typename T>
@@ -1098,17 +942,12 @@ typename Vec<T>::const_iterator Vec<T>::end() const noexcept {
 
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept {
-  const_iterator it;
-  it.pos = const_cast<typename std::remove_const<T>::type *>(this->data());
-  it.stride = size_of<T>();
-  return it;
+  return Slice<const T>(this->data(), this->size()).begin();
 }
 
 template <typename T>
 typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
-  const_iterator it = this->cbegin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
-  return it;
+  return Slice<const T>(this->data(), this->size()).end();
 }
 
 // Internal API only intended for the cxxbridge code generator.

From 088a37433a12c3c8374534707998b35c8e4fe7ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 22:32:48 +0000
Subject: [PATCH 1828/2232] Show source of is_const_v and random_access_iterator_tag in Slice doc


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 20ee98f..c565fb0 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -9,6 +9,9 @@
 ```cpp,hidelines
 // rust/cxx.h
 #
+# #include <iterator>
+# #include <type_traits>
+#
 # namespace rust {
 
 template <typename T>

From 03d73e141068a59ff42b70cabb9f8e41559ed6af Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 23:03:51 +0000
Subject: [PATCH 1829/2232] Document derive support in shared types page of website


---

diff --git a/book/src/shared.md b/book/src/shared.md
index 09465fe..b919cde 100644
--- a/book/src/shared.md
+++ b/book/src/shared.md
@@ -179,3 +179,47 @@ correctly match the existing C++ enum definition.
 Extern enums support all the same features as ordinary shared enums (explicit
 discriminants, repr). Again, CXX will static assert that all of those things you
 wrote are correct.
+
+## Derives
+
+The following standard traits are supported in `derive(...)` within the CXX
+bridge module.
+
+- `Clone`
+- `Copy`
+- `Debug`
+- `Default`
+- `Eq`
+- `Hash`
+- `Ord`
+- `PartialEq`
+- `PartialOrd`
+
+Note that shared enums automatically always come with impls of `Copy`, `Clone`,
+`Eq`, and `PartialEq`, so you're free to omit those derives on an enum.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    #[derive(Clone, Debug, Hash)]
+    struct ExampleStruct {
+        x: u32,
+        s: String,
+    }
+
+    #[derive(Hash, Ord, PartialOrd)]
+    enum ExampleEnum {
+        Yes,
+        No,
+    }
+}
+```
+
+The derives naturally apply to *both* the Rust data type *and* the corresponding
+C++ data type:
+
+- `Hash` gives you a specialization of [`template <> struct std::hash<T>`][hash] in C++
+- `PartialEq` produces `operator==` and `operator!=`
+- `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=`
+
+[hash]: https://en.cppreference.com/w/cpp/utility/hash

From e0d2227b6f51af42fe382600b88e88fe153d1b25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 27 2020 23:10:08 +0000
Subject: [PATCH 1830/2232] Merge pull request #606 from dtolnay/derive


Document derive support in shared types page of website
---

diff --git a/book/src/shared.md b/book/src/shared.md
index 09465fe..b919cde 100644
--- a/book/src/shared.md
+++ b/book/src/shared.md
@@ -179,3 +179,47 @@ correctly match the existing C++ enum definition.
 Extern enums support all the same features as ordinary shared enums (explicit
 discriminants, repr). Again, CXX will static assert that all of those things you
 wrote are correct.
+
+## Derives
+
+The following standard traits are supported in `derive(...)` within the CXX
+bridge module.
+
+- `Clone`
+- `Copy`
+- `Debug`
+- `Default`
+- `Eq`
+- `Hash`
+- `Ord`
+- `PartialEq`
+- `PartialOrd`
+
+Note that shared enums automatically always come with impls of `Copy`, `Clone`,
+`Eq`, and `PartialEq`, so you're free to omit those derives on an enum.
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    #[derive(Clone, Debug, Hash)]
+    struct ExampleStruct {
+        x: u32,
+        s: String,
+    }
+
+    #[derive(Hash, Ord, PartialOrd)]
+    enum ExampleEnum {
+        Yes,
+        No,
+    }
+}
+```
+
+The derives naturally apply to *both* the Rust data type *and* the corresponding
+C++ data type:
+
+- `Hash` gives you a specialization of [`template <> struct std::hash<T>`][hash] in C++
+- `PartialEq` produces `operator==` and `operator!=`
+- `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=`
+
+[hash]: https://en.cppreference.com/w/cpp/utility/hash

From e47a4d94d0a2de1ef82ea8fc616ccab687e5016a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 03:35:24 +0000
Subject: [PATCH 1831/2232] Rename Box value_type to element_type


This matches the member type naming on unique_ptr.
https://en.cppreference.com/w/cpp/memory/unique_ptr#Member_types
It appears value_type is for a member type of a container or iterator
while element_type is for the target of a smart pointer.

---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 7456ada..91ccda4 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -13,7 +13,7 @@
 template <typename T>
 class Box final {
 public:
-  using value_type = T;
+  using element_type = T;
   using const_pointer =
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
diff --git a/include/cxx.h b/include/cxx.h
index 95f9a06..b7deb71 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -222,7 +222,7 @@ private:
 template <typename T>
 class Box final {
 public:
-  using value_type = T;
+  using element_type = T;
   using const_pointer =
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
@@ -252,6 +252,9 @@ public:
 
   T *into_raw() noexcept;
 
+  // Deprecated.
+  using value_type = element_type;
+
 private:
   class uninit;
   class allocation;

From f62458f075614a42701a2242f5bbe2a005b00f66 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 03:38:43 +0000
Subject: [PATCH 1832/2232] Define member type Slice<T>::value_type = T


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index c565fb0..fe1691e 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -17,6 +17,8 @@
 template <typename T>
 class Slice final {
 public:
+  using value_type = T;
+
   Slice() noexcept;
   Slice(const Slice<T> &) noexcept;
   Slice(T *, size_t count) noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index b7deb71..1212de2 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -147,6 +147,8 @@ template <typename T>
 class Slice final
     : private detail::copy_assignable_if<std::is_const<T>::value> {
 public:
+  using value_type = T;
+
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 

From fe67bf4b6ac0e2fd57d11f55a45800d75783ff27 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 03:39:13 +0000
Subject: [PATCH 1833/2232] Add test with qsort on a mut slice of opaque Rust types


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 6814d00..c41433f 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -122,6 +122,7 @@ pub mod ffi {
         fn c_take_slice_shared(s: &[Shared]);
         fn c_take_slice_shared_sort(s: &mut [Shared]);
         fn c_take_slice_r(s: &[R]);
+        fn c_take_slice_r_sort(s: &mut [R]);
         fn c_take_rust_string(s: String);
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f0bab82..0ecedb1 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -1,5 +1,6 @@
 #include "tests/ffi/tests.h"
 #include "tests/ffi/lib.rs.h"
+#include <cstdlib>
 #include <cstring>
 #include <iterator>
 #include <memory>
@@ -290,7 +291,21 @@ void c_take_slice_shared_sort(rust::Slice<Shared> s) {
 }
 
 void c_take_slice_r(rust::Slice<const R> s) {
-  if (s.size() == 2 && s[0].get() == 2020 && s[1].get() == 2021) {
+  if (s.size() == 3 && s[0].get() == 2020 && s[1].get() == 2050) {
+    cxx_test_suite_set_correct();
+  }
+}
+
+bool operator<(const R &a, const R &b) noexcept { return a.get() < b.get(); }
+
+void c_take_slice_r_sort(rust::Slice<R> s) {
+  std::qsort(s.data(), s.size(), rust::size_of<decltype(s)::value_type>(),
+             [](const void *fst, const void *snd) {
+               auto &a = *static_cast<const R *>(fst);
+               auto &b = *static_cast<const R *>(snd);
+               return a < b ? -1 : b < a ? 1 : 0;
+             });
+  if (s[0].get() == 2020 && s[1].get() == 2021 && s[2].get() == 2050) {
     cxx_test_suite_set_correct();
   }
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 7dfaa3d..1f83ce5 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -125,6 +125,7 @@ void c_take_slice_char(rust::Slice<const char> s);
 void c_take_slice_shared(rust::Slice<const Shared> s);
 void c_take_slice_shared_sort(rust::Slice<Shared> s);
 void c_take_slice_r(rust::Slice<const R> s);
+void c_take_slice_r_sort(rust::Slice<R> s);
 void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
diff --git a/tests/test.rs b/tests/test.rs
index 6178d89..4427c7c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -132,11 +132,16 @@ fn test_c_take() {
         ffi::Shared { z: 4 },
     ];
     check!(ffi::c_take_slice_shared_sort(shared_sort_slice));
-    check!(ffi::c_take_slice_r(&[R(2020), R(2021)]));
     assert_eq!(shared_sort_slice[0].z, 0);
     assert_eq!(shared_sort_slice[1].z, 2);
     assert_eq!(shared_sort_slice[2].z, 4);
     assert_eq!(shared_sort_slice[3].z, 7);
+    let r_sort_slice = &mut [R(2020), R(2050), R(2021)];
+    check!(ffi::c_take_slice_r(r_sort_slice));
+    check!(ffi::c_take_slice_r_sort(r_sort_slice));
+    assert_eq!(r_sort_slice[0].0, 2020);
+    assert_eq!(r_sort_slice[1].0, 2021);
+    assert_eq!(r_sort_slice[2].0, 2050);
     check!(ffi::c_take_rust_string("2020".to_owned()));
     check!(ffi::c_take_unique_ptr_string(
         ffi::c_return_unique_ptr_string()

From c4a3ede5196ee036f5d3d44e22a232ef06fd72ae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 05:45:41 +0000
Subject: [PATCH 1834/2232] Move let_cxx_string's $value evaluation outside of unsafe block


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index a2bd72b..10abbce 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -73,7 +73,9 @@ macro_rules! let_cxx_string {
     ($var:ident = $value:expr $(,)?) => {
         let mut $var = $crate::private::StackString::new();
         #[allow(unused_mut, unused_unsafe)]
-        let mut $var = unsafe { $var.init($value) };
+        let mut $var = match $value {
+            let_cxx_string => unsafe { $var.init(let_cxx_string) },
+        };
     };
 }
 

From f7af2655c734a9ab75e17dce24c400321d2d8960 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 06:23:45 +0000
Subject: [PATCH 1835/2232] Clean up some unneeded guards on Box and Vec externs


These blocks contain extern function declarations only, not definitions.
It's okay for declarations to be repeated so the guard serves no
purpose.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 652ebf3..ab463ea 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1402,8 +1402,6 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     let inner = ident.to_fully_qualified();
     let instance = ident.to_symbol();
 
-    writeln!(out, "#ifndef CXXBRIDGE1_RUST_BOX_{}", instance);
-    writeln!(out, "#define CXXBRIDGE1_RUST_BOX_{}", instance);
     writeln!(
         out,
         "{} *cxxbridge1$box${}$alloc() noexcept;",
@@ -1419,7 +1417,6 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
         "void cxxbridge1$box${}$drop(::rust::Box<{}> *ptr) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE1_RUST_BOX_{}", instance);
 }
 
 fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
@@ -1428,8 +1425,6 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
 
     out.include.cstddef = true;
 
-    writeln!(out, "#ifndef CXXBRIDGE1_RUST_VEC_{}", instance);
-    writeln!(out, "#define CXXBRIDGE1_RUST_VEC_{}", instance);
     writeln!(
         out,
         "void cxxbridge1$rust_vec${}$new(const ::rust::Vec<{}> *ptr) noexcept;",
@@ -1465,7 +1460,6 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
         "void cxxbridge1$rust_vec${}$set_len(::rust::Vec<{}> *ptr, ::std::size_t len) noexcept;",
         instance, inner,
     );
-    writeln!(out, "#endif // CXXBRIDGE1_RUST_VEC_{}", instance);
 }
 
 fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {

From 8729da81aef380e0cac6bba0eb8ea4712bbde9bc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 06:34:12 +0000
Subject: [PATCH 1836/2232] Clean up guards from C++ standard library type shims


These shims are only emitted into the cc file, not any headers, so there
is no way they would end up more than once in the compiled code.

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ab463ea..981628c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1562,14 +1562,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
 
 fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
     let ty = UniquePtr::Ident(ident);
-    let instance = ty.to_mangled(out.types);
-
-    writeln!(out, "#ifndef CXXBRIDGE1_UNIQUE_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE1_UNIQUE_PTR_{}", instance);
-
     write_unique_ptr_common(out, ty);
-
-    writeln!(out, "#endif // CXXBRIDGE1_UNIQUE_PTR_{}", instance);
 }
 
 // Shared by UniquePtr<T> and UniquePtr<CxxVector<T>>.
@@ -1689,8 +1682,6 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     let inner = resolved.to_fully_qualified();
     let instance = ident.to_symbol(out.types);
 
-    writeln!(out, "#ifndef CXXBRIDGE1_SHARED_PTR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE1_SHARED_PTR_{}", instance);
     out.include.new = true;
     out.include.utility = true;
 
@@ -1756,8 +1747,6 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     );
     writeln!(out, "  self->~shared_ptr();");
     writeln!(out, "}}");
-
-    writeln!(out, "#endif // CXXBRIDGE1_SHARED_PTR_{}", instance);
 }
 
 fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
@@ -1766,8 +1755,6 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
 
     out.include.cstddef = true;
 
-    writeln!(out, "#ifndef CXXBRIDGE1_VECTOR_{}", instance);
-    writeln!(out, "#define CXXBRIDGE1_VECTOR_{}", instance);
     writeln!(
         out,
         "::std::size_t cxxbridge1$std$vector${}$size(const ::std::vector<{}> &s) noexcept {{",
@@ -1785,6 +1772,4 @@ fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
 
     out.include.memory = true;
     write_unique_ptr_common(out, UniquePtr::CxxVector(element));
-
-    writeln!(out, "#endif // CXXBRIDGE1_VECTOR_{}", instance);
 }

From 78a5f8d1233118c798e0c1823dd90bb9aedd6901 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 19:40:38 +0000
Subject: [PATCH 1837/2232] Restyle Box::value_type deprecation to be preserved in generated code


---

diff --git a/include/cxx.h b/include/cxx.h
index 1212de2..38261b7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -254,8 +254,7 @@ public:
 
   T *into_raw() noexcept;
 
-  // Deprecated.
-  using value_type = element_type;
+  /* Deprecated */ using value_type = element_type;
 
 private:
   class uninit;

From 5a61bda9c1105c76553281c13ce6232485f7910d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 19:42:02 +0000
Subject: [PATCH 1838/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 2527453..e92cd5f 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.55/src/**"]),
+    srcs = glob(["vendor/syn-1.0.56/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 0c9b02c..88304c6 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.55/src/**"]),
+    srcs = glob(["vendor/syn-1.0.56/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2fa8610..e750b7e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -163,9 +163,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
 
 [[package]]
 name = "lazy_static"
@@ -252,9 +252,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.60"
+version = "1.0.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779"
+checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
 dependencies = [
  "itoa",
  "ryu",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.55"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
+checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72"
 dependencies = [
  "proc-macro2",
  "quote",

From 7f056cdf462c259eee6d06aa2451b3fa476487f1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 19:42:43 +0000
Subject: [PATCH 1839/2232] Release 1.0.22


---

diff --git a/Cargo.toml b/Cargo.toml
index 26289b9..44e9b14 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.21" # remember to update html_root_url
+version = "1.0.22" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.21", path = "macro" }
+cxxbridge-macro = { version = "=1.0.22", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.21", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.22", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.21", path = "gen/build" }
+cxx-build = { version = "=1.0.22", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 4686d91..658e42a 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.21"
+version = "1.0.22"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 57ea11f..1fc38fc 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.21"
+version = "1.0.22"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 73bbd6b..a0ce73c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.21"
+version = "1.0.22"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 688bb95..22fdcfb 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.21"
+version = "0.7.22"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 2f4ce21..0edd8c6 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.21"
+version = "1.0.22"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index ee6fea3..33bd881 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.21")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.22")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index e750b7e..f918cb1 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.21"
+version = "1.0.22"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.21"
+version = "1.0.22"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.21"
+version = "0.7.22"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.21"
+version = "1.0.22"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.21"
+version = "1.0.22"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.21"
+version = "1.0.22"
 dependencies = [
  "cxx",
  "proc-macro2",

From 91b22332fc131d135b973cd7a311f33418adb9f4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 22:39:53 +0000
Subject: [PATCH 1840/2232] Add weak_ptr to planned bindings list


Tracked in #607.

---

diff --git a/README.md b/README.md
index f6a18eb..d21eebe 100644
--- a/README.md
+++ b/README.md
@@ -351,6 +351,7 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index b6e0e30..ec7e2d2 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -52,4 +52,5 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
diff --git a/src/lib.rs b/src/lib.rs
index 33bd881..ff723c3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,6 +360,7 @@
 //! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
+//! <tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 //! </table>
 
 #![no_std]

From 40f4b5630c1fbb0358b424cb51c20c9c5f9cf966 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 28 2020 23:04:54 +0000
Subject: [PATCH 1841/2232] Fix capitalization typo in SharedPtr rustdoc


---

diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index f355d9c..2f75e23 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -7,7 +7,7 @@ use core::marker::PhantomData;
 use core::mem::MaybeUninit;
 use core::ops::Deref;
 
-/// BInding to C++ `std::shared_ptr<T>`.
+/// Binding to C++ `std::shared_ptr<T>`.
 #[repr(C)]
 pub struct SharedPtr<T>
 where

From 378cd6e5cabcf9a5496284b0a4d6bf7b8372e11a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 01:24:28 +0000
Subject: [PATCH 1842/2232] Update SharedPtr target type check


These types were implemented in #563.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index f43c1e2..52ee693 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -139,12 +139,10 @@ fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
         }
 
         match Atom::from(&ident.rust) {
-            None => return,
-            Some(CxxString) => {
-                cx.error(ptr, "std::shared_ptr<std::string> is not supported yet");
-                return;
-            }
-            _ => {}
+            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(CxxString) => return,
+            Some(Bool) | Some(Char) | Some(RustString) => {}
         }
     } else if let Type::CxxVector(_) = &ptr.inner {
         cx.error(ptr, "std::shared_ptr<std::vector> is not supported yet");

From cd1430c5ef65932a24c7fd2fd478db16a8cb19e1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 01:25:37 +0000
Subject: [PATCH 1843/2232] Add SharedPtr<bool>


---

diff --git a/src/cxx.cc b/src/cxx.cc
index e5853b9..b15dcaa 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -537,6 +537,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
 
 #define FOR_EACH_SHARED_PTR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
+  MACRO(bool, bool)                                                            \
   MACRO(usize, std::size_t)                                                    \
   MACRO(isize, rust::isize)                                                    \
   MACRO(string, std::string)
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 2f75e23..9269e5a 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -214,6 +214,7 @@ macro_rules! impl_shared_ptr_target_for_primitive {
     };
 }
 
+impl_shared_ptr_target_for_primitive!(bool);
 impl_shared_ptr_target_for_primitive!(u8);
 impl_shared_ptr_target_for_primitive!(u16);
 impl_shared_ptr_target_for_primitive!(u32);
diff --git a/syntax/check.rs b/syntax/check.rs
index 52ee693..ded5c53 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -139,10 +139,10 @@ fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
         }
 
         match Atom::from(&ident.rust) {
-            None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
-            | Some(CxxString) => return,
-            Some(Bool) | Some(Char) | Some(RustString) => {}
+            None | Some(Bool) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+            | Some(F64) | Some(CxxString) => return,
+            Some(Char) | Some(RustString) => {}
         }
     } else if let Type::CxxVector(_) = &ptr.inner {
         cx.error(ptr, "std::shared_ptr<std::vector> is not supported yet");

From 215e77fbec91468f294ea372f7c5524ed890de65 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 01:41:20 +0000
Subject: [PATCH 1844/2232] Add Rust std::weak_ptr binding


---

diff --git a/README.md b/README.md
index d21eebe..f6a18eb 100644
--- a/README.md
+++ b/README.md
@@ -351,7 +351,6 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index ec7e2d2..b6e0e30 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -52,5 +52,4 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 981628c..327dee4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -208,7 +208,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
             Type::UniquePtr(_) => out.include.memory = true,
-            Type::SharedPtr(_) => out.include.memory = true,
+            Type::SharedPtr(_) | Type::WeakPtr(_) => out.include.memory = true,
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
@@ -1172,6 +1172,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::WeakPtr(ptr) => {
+            write!(out, "::std::weak_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
@@ -1251,6 +1256,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::SharedPtr(_)
+        | Type::WeakPtr(_)
         | Type::Str(_)
         | Type::CxxVector(_)
         | Type::RustVec(_)
@@ -1357,6 +1363,16 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_shared_ptr(out, inner);
                 }
             }
+        } else if let Type::WeakPtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_weak_ptr(out, inner);
+                }
+            }
         } else if let Type::CxxVector(vector) = ty {
             if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
@@ -1749,6 +1765,47 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
 }
 
+fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
+    let resolved = out.types.resolve(ident);
+    let inner = resolved.to_fully_qualified();
+    let instance = ident.to_symbol(out.types);
+
+    out.include.new = true;
+    out.include.utility = true;
+
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::weak_ptr<{}>) == 2 * sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$clone(const ::std::weak_ptr<{}>& self, ::std::weak_ptr<{}> *ptr) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  self->~weak_ptr();");
+    writeln!(out, "}}");
+}
+
 fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d892599..f13fca4 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -101,6 +101,14 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                     expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
                 }
             }
+        } else if let Type::WeakPtr(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
+                    expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1229,6 +1237,46 @@ fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
     }
 }
 
+fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge1$weak_ptr${}$", ident.to_symbol(types));
+    let link_null = format!("{}null", prefix);
+    let link_clone = format!("{}clone", prefix);
+    let link_drop = format!("{}drop", prefix);
+
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::WeakPtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            unsafe fn __null(new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_null]
+                    fn __null(new: *mut ::std::ffi::c_void);
+                }
+                __null(new);
+            }
+            unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_clone]
+                    fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void);
+                }
+                __clone(this, new);
+            }
+            unsafe fn __drop(this: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_drop]
+                    fn __drop(this: *mut ::std::ffi::c_void);
+                }
+                __drop(this);
+            }
+        }
+    }
+}
+
 fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let _ = explicit_impl;
     let name = elem.rust.to_string();
diff --git a/src/cxx.cc b/src/cxx.cc
index b15dcaa..e573b44 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -508,6 +508,21 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop(                           \
       const std::shared_ptr<CXX_TYPE> *self) noexcept {                        \
     self->~shared_ptr();                                                       \
+  }                                                                            \
+  static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), "");    \
+  static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), "");      \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null(                             \
+      std::weak_ptr<CXX_TYPE> *ptr) noexcept {                                 \
+    new (ptr) std::weak_ptr<CXX_TYPE>();                                       \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone(                            \
+      const std::weak_ptr<CXX_TYPE> &self,                                     \
+      std::weak_ptr<CXX_TYPE> *ptr) noexcept {                                 \
+    new (ptr) std::weak_ptr<CXX_TYPE>(self);                                   \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop(                             \
+      const std::weak_ptr<CXX_TYPE> *self) noexcept {                          \
+    self->~weak_ptr();                                                         \
   }
 
 // Usize and isize are the same type as one of the below.
diff --git a/src/lib.rs b/src/lib.rs
index ff723c3..76453ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,7 +360,6 @@
 //! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 //! </table>
 
 #![no_std]
@@ -411,6 +410,7 @@ mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
 pub mod vector;
+mod weak_ptr;
 
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
@@ -419,6 +419,7 @@ pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
 #[doc(inline)]
 pub use crate::vector::CxxVector;
+pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
@@ -457,6 +458,7 @@ pub mod private {
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorElement;
+    pub use crate::weak_ptr::WeakPtrTarget;
 }
 
 mod actually_private {
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
new file mode 100644
index 0000000..d73ee8f
--- /dev/null
+++ b/src/weak_ptr.rs
@@ -0,0 +1,130 @@
+use crate::string::CxxString;
+use core::ffi::c_void;
+use core::fmt::Display;
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+
+/// Binding to C++ `std::weak_ptr<T>`.
+#[repr(C)]
+pub struct WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    repr: [*mut c_void; 2],
+    ty: PhantomData<T>,
+}
+
+impl<T> WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    /// Makes a new WeakPtr wrapping a null pointer.
+    ///
+    /// Matches the behavior of default-constructing a std::weak\_ptr.
+    pub fn null() -> Self {
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__null(new);
+            weak_ptr.assume_init()
+        }
+    }
+}
+
+unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+
+impl<T> Clone for WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    fn clone(&self) -> Self {
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        let this = self as *const Self as *mut c_void;
+        unsafe {
+            T::__clone(this, new);
+            weak_ptr.assume_init()
+        }
+    }
+}
+
+impl<T> Drop for WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    fn drop(&mut self) {
+        let this = self as *mut Self as *mut c_void;
+        unsafe { T::__drop(this) }
+    }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+pub unsafe trait WeakPtrTarget {
+    #[doc(hidden)]
+    const __NAME: &'static dyn Display;
+    #[doc(hidden)]
+    unsafe fn __null(new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __clone(this: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __drop(this: *mut c_void);
+}
+
+macro_rules! impl_weak_ptr_target {
+    ($segment:expr, $name:expr, $ty:ty) => {
+        unsafe impl WeakPtrTarget for $ty {
+            const __NAME: &'static dyn Display = &$name;
+            unsafe fn __null(new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
+                        fn __null(new: *mut c_void);
+                    }
+                }
+                __null(new);
+            }
+            unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
+                        fn __clone(this: *const c_void, new: *mut c_void);
+                    }
+                }
+                __clone(this, new);
+            }
+            unsafe fn __drop(this: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
+                        fn __drop(this: *mut c_void);
+                    }
+                }
+                __drop(this);
+            }
+        }
+    };
+}
+
+macro_rules! impl_weak_ptr_target_for_primitive {
+    ($ty:ident) => {
+        impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
+impl_weak_ptr_target_for_primitive!(bool);
+impl_weak_ptr_target_for_primitive!(u8);
+impl_weak_ptr_target_for_primitive!(u16);
+impl_weak_ptr_target_for_primitive!(u32);
+impl_weak_ptr_target_for_primitive!(u64);
+impl_weak_ptr_target_for_primitive!(usize);
+impl_weak_ptr_target_for_primitive!(i8);
+impl_weak_ptr_target_for_primitive!(i16);
+impl_weak_ptr_target_for_primitive!(i32);
+impl_weak_ptr_target_for_primitive!(i64);
+impl_weak_ptr_target_for_primitive!(isize);
+impl_weak_ptr_target_for_primitive!(f32);
+impl_weak_ptr_target_for_primitive!(f64);
+
+impl_weak_ptr_target!("string", "CxxString", CxxString);
diff --git a/syntax/check.rs b/syntax/check.rs
index ded5c53..39ea04e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -32,6 +32,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
+            Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
@@ -152,6 +153,27 @@ fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported shared_ptr target type");
 }
 
+fn check_type_weak_ptr(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(&ident.rust) {
+            cx.error(ptr, "weak_ptr of a Rust type is not supported yet");
+            return;
+        }
+
+        match Atom::from(&ident.rust) {
+            None | Some(Bool) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+            | Some(F64) | Some(CxxString) => return,
+            Some(Char) | Some(RustString) => {}
+        }
+    } else if let Type::CxxVector(_) = &ptr.inner {
+        cx.error(ptr, "std::weak_ptr<std::vector> is not supported yet");
+        return;
+    }
+
+    cx.error(ptr, "unsupported weak_ptr target type");
+}
+
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
@@ -434,6 +456,7 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         | Type::RustVec(ty)
         | Type::UniquePtr(ty)
         | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
         | Type::CxxVector(ty) => {
             if let Type::Ident(inner) = &ty.inner {
                 if Atom::from(&inner.rust).is_none() {
@@ -506,6 +529,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"
         || ident == "SharedPtr"
+        || ident == "WeakPtr"
         || ident == "Vec"
         || ident == "CxxVector"
         || ident == "str"
@@ -527,6 +551,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         | Type::RustVec(_)
         | Type::UniquePtr(_)
         | Type::SharedPtr(_)
+        | Type::WeakPtr(_)
         | Type::Ref(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
@@ -599,6 +624,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::SharedPtr(_) => "shared_ptr".to_owned(),
+        Type::WeakPtr(_) => "weak_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 9b154f6..d70e7cc 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -46,6 +46,7 @@ impl Hash for Type {
             Type::RustBox(t) => t.hash(state),
             Type::UniquePtr(t) => t.hash(state),
             Type::SharedPtr(t) => t.hash(state),
+            Type::WeakPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
@@ -67,6 +68,7 @@ impl PartialEq for Type {
             (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
+            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
diff --git a/syntax/improper.rs b/syntax/improper.rs
index c0f6983..d672e7d 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -28,7 +28,9 @@ impl<'a> Types<'a> {
             | Type::Fn(_)
             | Type::Void(_)
             | Type::SliceRef(_) => Definite(true),
-            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::CxxVector(_) => {
+                Definite(false)
+            }
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 7f8fd9a..111cec3 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -170,6 +170,7 @@ pub enum Type {
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
     SharedPtr(Box<Ty1>),
+    WeakPtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f72253a..1ae4c2d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -901,6 +901,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "WeakPtr" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::WeakPtr(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
diff --git a/syntax/pod.rs b/syntax/pod.rs
index d808a99..e1c4831 100644
--- a/syntax/pod.rs
+++ b/syntax/pod.rs
@@ -26,6 +26,7 @@ impl<'a> Types<'a> {
             | Type::RustVec(_)
             | Type::UniquePtr(_)
             | Type::SharedPtr(_)
+            | Type::WeakPtr(_)
             | Type::CxxVector(_)
             | Type::Void(_) => false,
             Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index ae2d1d9..8348704 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -23,6 +23,7 @@ impl ToTokens for Type {
             Type::RustBox(ty)
             | Type::UniquePtr(ty)
             | Type::SharedPtr(ty)
+            | Type::WeakPtr(ty)
             | Type::CxxVector(ty)
             | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
@@ -46,7 +47,7 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
-        if let "UniquePtr" | "SharedPtr" | "CxxVector" = name.as_str() {
+        if let "UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
             tokens.extend(quote_spanned!(span=> ::std::vec::));
diff --git a/syntax/types.rs b/syntax/types.rs
index 1056854..f7682bc 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -45,6 +45,7 @@ impl<'a> Types<'a> {
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
                 | Type::SharedPtr(ty)
+                | Type::WeakPtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),

From 85b6bc4a39a68c5b064807e89f1933d898e0f5b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:06:17 +0000
Subject: [PATCH 1845/2232] Add downgrade conversion from SharedPtr to WeakPtr


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 327dee4..359eb22 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1799,6 +1799,13 @@ fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
     writeln!(
         out,
+        "void cxxbridge1$weak_ptr${}$downgrade(const ::std::shared_ptr<{}>& shared, ::std::weak_ptr<{}> *weak) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
         "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
         instance, inner,
     );
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f13fca4..690dbf9 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1242,6 +1242,7 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
     let prefix = format!("cxxbridge1$weak_ptr${}$", ident.to_symbol(types));
     let link_null = format!("{}null", prefix);
     let link_clone = format!("{}clone", prefix);
+    let link_downgrade = format!("{}downgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
     let begin_span =
@@ -1266,6 +1267,13 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
                 }
                 __clone(this, new);
             }
+            unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_downgrade]
+                    fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void);
+                }
+                __downgrade(shared, weak);
+            }
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
diff --git a/src/cxx.cc b/src/cxx.cc
index e573b44..2e1cc15 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -520,6 +520,11 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       std::weak_ptr<CXX_TYPE> *ptr) noexcept {                                 \
     new (ptr) std::weak_ptr<CXX_TYPE>(self);                                   \
   }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade(                        \
+      const std::shared_ptr<CXX_TYPE> &shared,                                 \
+      std::weak_ptr<CXX_TYPE> *weak) noexcept {                                \
+    new (weak) std::weak_ptr<CXX_TYPE>(shared);                                \
+  }                                                                            \
   void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop(                             \
       const std::weak_ptr<CXX_TYPE> *self) noexcept {                          \
     self->~weak_ptr();                                                         \
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 9269e5a..18f600f 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,5 +1,6 @@
 use crate::kind::Trivial;
 use crate::string::CxxString;
+use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -61,6 +62,24 @@ where
         let this = self as *const Self as *const c_void;
         unsafe { T::__get(this).as_ref() }
     }
+
+    /// Constructs new WeakPtr as a non-owning reference to the object managed
+    /// by `self`. If `self` manages no object, the WeakPtr manages no object
+    /// too.
+    ///
+    /// Matches the behavior of [std::weak_ptr\<T\>::weak_ptr(const std::shared_ptr\<T\> \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr).
+    pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T>
+    where
+        T: WeakPtrTarget,
+    {
+        let this = self as *const Self as *const c_void;
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__downgrade(this, new);
+            weak_ptr.assume_init()
+        }
+    }
 }
 
 unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index d73ee8f..9038f4e 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -5,6 +5,11 @@ use core::marker::PhantomData;
 use core::mem::MaybeUninit;
 
 /// Binding to C++ `std::weak_ptr<T>`.
+///
+/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a
+/// SharedPtr.
+///
+/// [downgrading]: crate::SharedPtr::downgrade
 #[repr(C)]
 pub struct WeakPtr<T>
 where
@@ -69,6 +74,8 @@ pub unsafe trait WeakPtrTarget {
     #[doc(hidden)]
     unsafe fn __clone(this: *const c_void, new: *mut c_void);
     #[doc(hidden)]
+    unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
     unsafe fn __drop(this: *mut c_void);
 }
 
@@ -94,6 +101,15 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __clone(this, new);
             }
+            unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
+                        fn __downgrade(shared: *const c_void, weak: *mut c_void);
+                    }
+                }
+                __downgrade(shared, weak);
+            }
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {

From 7a48785a8ebb3fad0f4d13e7d2db3157e0c60762 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:09:55 +0000
Subject: [PATCH 1846/2232] Add upgrade conversion from WeakPtr to SharedPtr


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 359eb22..4e802da 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1806,6 +1806,17 @@ fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
     writeln!(
         out,
+        "void cxxbridge1$weak_ptr${}$upgrade(const ::std::weak_ptr<{}>& weak, ::std::shared_ptr<{}> *shared) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(
+        out,
+        "  ::new (shared) ::std::shared_ptr<{}>(weak.lock());",
+        inner,
+    );
+    writeln!(out, "}}");
+    writeln!(
+        out,
         "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
         instance, inner,
     );
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 690dbf9..e53e5b6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1243,6 +1243,7 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
     let link_null = format!("{}null", prefix);
     let link_clone = format!("{}clone", prefix);
     let link_downgrade = format!("{}downgrade", prefix);
+    let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
     let begin_span =
@@ -1274,6 +1275,13 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
                 }
                 __downgrade(shared, weak);
             }
+            unsafe fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_upgrade]
+                    fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void);
+                }
+                __upgrade(weak, shared);
+            }
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
diff --git a/src/cxx.cc b/src/cxx.cc
index 2e1cc15..6b71656 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -525,6 +525,11 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
       std::weak_ptr<CXX_TYPE> *weak) noexcept {                                \
     new (weak) std::weak_ptr<CXX_TYPE>(shared);                                \
   }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade(                          \
+      const std::weak_ptr<CXX_TYPE> &weak,                                     \
+      std::shared_ptr<CXX_TYPE> *shared) noexcept {                            \
+    new (shared) std::shared_ptr<CXX_TYPE>(weak.lock());                       \
+  }                                                                            \
   void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop(                             \
       const std::weak_ptr<CXX_TYPE> *self) noexcept {                          \
     self->~weak_ptr();                                                         \
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index 9038f4e..3875a78 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -1,3 +1,4 @@
+use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
 use crate::string::CxxString;
 use core::ffi::c_void;
 use core::fmt::Display;
@@ -34,6 +35,23 @@ where
             weak_ptr.assume_init()
         }
     }
+
+    /// Upgrades a non-owning reference into an owning reference if possible,
+    /// otherwise to a null reference.
+    ///
+    /// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock).
+    pub fn upgrade(&self) -> SharedPtr<T>
+    where
+        T: SharedPtrTarget,
+    {
+        let this = self as *const Self as *const c_void;
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__upgrade(this, new);
+            shared_ptr.assume_init()
+        }
+    }
 }
 
 unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
@@ -76,6 +94,8 @@ pub unsafe trait WeakPtrTarget {
     #[doc(hidden)]
     unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
     #[doc(hidden)]
+    unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
+    #[doc(hidden)]
     unsafe fn __drop(this: *mut c_void);
 }
 
@@ -110,6 +130,15 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __downgrade(shared, weak);
             }
+            unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")]
+                        fn __upgrade(weak: *const c_void, shared: *mut c_void);
+                    }
+                }
+                __upgrade(weak, shared);
+            }
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {

From bc6e43c15638d71caa39551f4be6a9d9bcc0692a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:18:55 +0000
Subject: [PATCH 1847/2232] Add WeakPtr test


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c41433f..2d564fa 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -178,6 +178,8 @@ pub mod ffi {
         fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
         fn c_set_array(self: &mut Array, value: i32);
 
+        fn c_get_use_count(weak: &WeakPtr<C>) -> usize;
+
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
         #[rust_name = "str_overloaded_method"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 0ecedb1..50a11da 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -538,6 +538,10 @@ const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept {
+  return weak.use_count();
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 1f83ce5..8235f5f 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -168,6 +168,8 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept;
+
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D &d);
 void c_take_trivial(D d);
diff --git a/tests/test.rs b/tests/test.rs
index 4427c7c..273abe9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,5 +1,6 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
+use cxx::SharedPtr;
 use cxx_test_suite::module::ffi2;
 use cxx_test_suite::{cast, ffi, R};
 use std::cell::Cell;
@@ -36,7 +37,6 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, ffi::c_return_box().0);
     ffi::c_return_unique_ptr();
-    ffi::c_return_shared_ptr();
     ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
@@ -242,6 +242,20 @@ fn test_c_method_calls() {
 }
 
 #[test]
+fn test_shared_ptr_weak_ptr() {
+    let shared_ptr = ffi::c_return_shared_ptr();
+    let weak_ptr = SharedPtr::downgrade(&shared_ptr);
+    assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
+
+    assert!(!weak_ptr.upgrade().is_null());
+    assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
+
+    drop(shared_ptr);
+    assert_eq!(0, ffi::c_get_use_count(&weak_ptr));
+    assert!(weak_ptr.upgrade().is_null());
+}
+
+#[test]
 fn test_c_ns_method_calls() {
     let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
 

From 18ed79b04c0e962e355685e0b1f564c5981d899e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:21:46 +0000
Subject: [PATCH 1848/2232] Add impl Debug for WeakPtr


---

diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index 3875a78..7fc4c78 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -1,7 +1,7 @@
 use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
 use crate::string::CxxString;
 use core::ffi::c_void;
-use core::fmt::Display;
+use core::fmt::{self, Debug, Display};
 use core::marker::PhantomData;
 use core::mem::MaybeUninit;
 
@@ -82,6 +82,15 @@ where
     }
 }
 
+impl<T> Debug for WeakPtr<T>
+where
+    T: Debug + WeakPtrTarget + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        Debug::fmt(&self.upgrade(), formatter)
+    }
+}
+
 // Methods are private; not intended to be implemented outside of cxxbridge
 // codebase.
 pub unsafe trait WeakPtrTarget {

From 967866804cc4f11132fedfecba759915900684cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:35:10 +0000
Subject: [PATCH 1849/2232] Merge pull request #609 from dtolnay/weak


Add Rust std::weak_ptr binding
---

diff --git a/README.md b/README.md
index d21eebe..f6a18eb 100644
--- a/README.md
+++ b/README.md
@@ -351,7 +351,6 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
 
 <br>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index ec7e2d2..b6e0e30 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -52,5 +52,4 @@ matter of designing a nice API for each in its non-native language.
 <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-<tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 </table>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 981628c..4e802da 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -208,7 +208,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::RustBox(_) => out.builtin.rust_box = true,
             Type::RustVec(_) => out.builtin.rust_vec = true,
             Type::UniquePtr(_) => out.include.memory = true,
-            Type::SharedPtr(_) => out.include.memory = true,
+            Type::SharedPtr(_) | Type::WeakPtr(_) => out.include.memory = true,
             Type::Str(_) => out.builtin.rust_str = true,
             Type::CxxVector(_) => out.include.vector = true,
             Type::Fn(_) => out.builtin.rust_fn = true,
@@ -1172,6 +1172,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &ptr.inner);
             write!(out, ">");
         }
+        Type::WeakPtr(ptr) => {
+            write!(out, "::std::weak_ptr<");
+            write_type(out, &ptr.inner);
+            write!(out, ">");
+        }
         Type::CxxVector(ty) => {
             write!(out, "::std::vector<");
             write_type(out, &ty.inner);
@@ -1251,6 +1256,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::RustBox(_)
         | Type::UniquePtr(_)
         | Type::SharedPtr(_)
+        | Type::WeakPtr(_)
         | Type::Str(_)
         | Type::CxxVector(_)
         | Type::RustVec(_)
@@ -1357,6 +1363,16 @@ fn write_generic_instantiations(out: &mut OutFile) {
                     write_shared_ptr(out, inner);
                 }
             }
+        } else if let Type::WeakPtr(ptr) = ty {
+            if let Type::Ident(inner) = &ptr.inner {
+                if Atom::from(&inner.rust).is_none()
+                    && (!out.types.aliases.contains_key(&inner.rust)
+                        || out.types.explicit_impls.contains(ty))
+                {
+                    out.next_section();
+                    write_weak_ptr(out, inner);
+                }
+            }
         } else if let Type::CxxVector(vector) = ty {
             if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
@@ -1749,6 +1765,65 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
 }
 
+fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
+    let resolved = out.types.resolve(ident);
+    let inner = resolved.to_fully_qualified();
+    let instance = ident.to_symbol(out.types);
+
+    out.include.new = true;
+    out.include.utility = true;
+
+    writeln!(
+        out,
+        "static_assert(sizeof(::std::weak_ptr<{}>) == 2 * sizeof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "static_assert(alignof(::std::weak_ptr<{}>) == alignof(void *), \"\");",
+        inner,
+    );
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$null(::std::weak_ptr<{}> *ptr) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>();", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$clone(const ::std::weak_ptr<{}>& self, ::std::weak_ptr<{}> *ptr) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  ::new (ptr) ::std::weak_ptr<{}>(self);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$downgrade(const ::std::shared_ptr<{}>& shared, ::std::weak_ptr<{}> *weak) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(out, "  ::new (weak) ::std::weak_ptr<{}>(shared);", inner);
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$upgrade(const ::std::weak_ptr<{}>& weak, ::std::shared_ptr<{}> *shared) noexcept {{",
+        instance, inner, inner,
+    );
+    writeln!(
+        out,
+        "  ::new (shared) ::std::shared_ptr<{}>(weak.lock());",
+        inner,
+    );
+    writeln!(out, "}}");
+    writeln!(
+        out,
+        "void cxxbridge1$weak_ptr${}$drop(::std::weak_ptr<{}> *self) noexcept {{",
+        instance, inner,
+    );
+    writeln!(out, "  self->~weak_ptr();");
+    writeln!(out, "}}");
+}
+
 fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d892599..e53e5b6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -101,6 +101,14 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
                     expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
                 }
             }
+        } else if let Type::WeakPtr(ptr) = ty {
+            if let Type::Ident(ident) = &ptr.inner {
+                if Atom::from(&ident.rust).is_none()
+                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
+                {
+                    expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
+                }
+            }
         } else if let Type::CxxVector(ptr) = ty {
             if let Type::Ident(ident) = &ptr.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1229,6 +1237,62 @@ fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
     }
 }
 
+fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let name = ident.rust.to_string();
+    let prefix = format!("cxxbridge1$weak_ptr${}$", ident.to_symbol(types));
+    let link_null = format!("{}null", prefix);
+    let link_clone = format!("{}clone", prefix);
+    let link_downgrade = format!("{}downgrade", prefix);
+    let link_upgrade = format!("{}upgrade", prefix);
+    let link_drop = format!("{}drop", prefix);
+
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
+        #unsafe_token impl ::cxx::private::WeakPtrTarget for #ident {
+            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            unsafe fn __null(new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_null]
+                    fn __null(new: *mut ::std::ffi::c_void);
+                }
+                __null(new);
+            }
+            unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_clone]
+                    fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void);
+                }
+                __clone(this, new);
+            }
+            unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_downgrade]
+                    fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void);
+                }
+                __downgrade(shared, weak);
+            }
+            unsafe fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_upgrade]
+                    fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void);
+                }
+                __upgrade(weak, shared);
+            }
+            unsafe fn __drop(this: *mut ::std::ffi::c_void) {
+                extern "C" {
+                    #[link_name = #link_drop]
+                    fn __drop(this: *mut ::std::ffi::c_void);
+                }
+                __drop(this);
+            }
+        }
+    }
+}
+
 fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let _ = explicit_impl;
     let name = elem.rust.to_string();
diff --git a/src/cxx.cc b/src/cxx.cc
index b15dcaa..6b71656 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -508,6 +508,31 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop(                           \
       const std::shared_ptr<CXX_TYPE> *self) noexcept {                        \
     self->~shared_ptr();                                                       \
+  }                                                                            \
+  static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), "");    \
+  static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), "");      \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null(                             \
+      std::weak_ptr<CXX_TYPE> *ptr) noexcept {                                 \
+    new (ptr) std::weak_ptr<CXX_TYPE>();                                       \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone(                            \
+      const std::weak_ptr<CXX_TYPE> &self,                                     \
+      std::weak_ptr<CXX_TYPE> *ptr) noexcept {                                 \
+    new (ptr) std::weak_ptr<CXX_TYPE>(self);                                   \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade(                        \
+      const std::shared_ptr<CXX_TYPE> &shared,                                 \
+      std::weak_ptr<CXX_TYPE> *weak) noexcept {                                \
+    new (weak) std::weak_ptr<CXX_TYPE>(shared);                                \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade(                          \
+      const std::weak_ptr<CXX_TYPE> &weak,                                     \
+      std::shared_ptr<CXX_TYPE> *shared) noexcept {                            \
+    new (shared) std::shared_ptr<CXX_TYPE>(weak.lock());                       \
+  }                                                                            \
+  void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop(                             \
+      const std::weak_ptr<CXX_TYPE> *self) noexcept {                          \
+    self->~weak_ptr();                                                         \
   }
 
 // Usize and isize are the same type as one of the below.
diff --git a/src/lib.rs b/src/lib.rs
index ff723c3..76453ea 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,7 +360,6 @@
 //! <tr><td>Option&lt;T&gt;</td><td><sup><i>tbd</i></sup></td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::map&lt;K, V&gt;</td></tr>
 //! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map&lt;K, V&gt;</td></tr>
-//! <tr><td><sup><i>tbd</i></sup></td><td>std::weak_ptr&lt;T&gt;</td></tr>
 //! </table>
 
 #![no_std]
@@ -411,6 +410,7 @@ mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
 pub mod vector;
+mod weak_ptr;
 
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
@@ -419,6 +419,7 @@ pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
 #[doc(inline)]
 pub use crate::vector::CxxVector;
+pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
 /// For use in impls of the `ExternType` trait. See [`ExternType`].
@@ -457,6 +458,7 @@ pub mod private {
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorElement;
+    pub use crate::weak_ptr::WeakPtrTarget;
 }
 
 mod actually_private {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 9269e5a..18f600f 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,5 +1,6 @@
 use crate::kind::Trivial;
 use crate::string::CxxString;
+use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -61,6 +62,24 @@ where
         let this = self as *const Self as *const c_void;
         unsafe { T::__get(this).as_ref() }
     }
+
+    /// Constructs new WeakPtr as a non-owning reference to the object managed
+    /// by `self`. If `self` manages no object, the WeakPtr manages no object
+    /// too.
+    ///
+    /// Matches the behavior of [std::weak_ptr\<T\>::weak_ptr(const std::shared_ptr\<T\> \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr).
+    pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T>
+    where
+        T: WeakPtrTarget,
+    {
+        let this = self as *const Self as *const c_void;
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__downgrade(this, new);
+            weak_ptr.assume_init()
+        }
+    }
 }
 
 unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {}
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
new file mode 100644
index 0000000..7fc4c78
--- /dev/null
+++ b/src/weak_ptr.rs
@@ -0,0 +1,184 @@
+use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
+use crate::string::CxxString;
+use core::ffi::c_void;
+use core::fmt::{self, Debug, Display};
+use core::marker::PhantomData;
+use core::mem::MaybeUninit;
+
+/// Binding to C++ `std::weak_ptr<T>`.
+///
+/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a
+/// SharedPtr.
+///
+/// [downgrading]: crate::SharedPtr::downgrade
+#[repr(C)]
+pub struct WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    repr: [*mut c_void; 2],
+    ty: PhantomData<T>,
+}
+
+impl<T> WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    /// Makes a new WeakPtr wrapping a null pointer.
+    ///
+    /// Matches the behavior of default-constructing a std::weak\_ptr.
+    pub fn null() -> Self {
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__null(new);
+            weak_ptr.assume_init()
+        }
+    }
+
+    /// Upgrades a non-owning reference into an owning reference if possible,
+    /// otherwise to a null reference.
+    ///
+    /// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock).
+    pub fn upgrade(&self) -> SharedPtr<T>
+    where
+        T: SharedPtrTarget,
+    {
+        let this = self as *const Self as *const c_void;
+        let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
+        let new = shared_ptr.as_mut_ptr().cast();
+        unsafe {
+            T::__upgrade(this, new);
+            shared_ptr.assume_init()
+        }
+    }
+}
+
+unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {}
+
+impl<T> Clone for WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    fn clone(&self) -> Self {
+        let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit();
+        let new = weak_ptr.as_mut_ptr().cast();
+        let this = self as *const Self as *mut c_void;
+        unsafe {
+            T::__clone(this, new);
+            weak_ptr.assume_init()
+        }
+    }
+}
+
+impl<T> Drop for WeakPtr<T>
+where
+    T: WeakPtrTarget,
+{
+    fn drop(&mut self) {
+        let this = self as *mut Self as *mut c_void;
+        unsafe { T::__drop(this) }
+    }
+}
+
+impl<T> Debug for WeakPtr<T>
+where
+    T: Debug + WeakPtrTarget + SharedPtrTarget,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        Debug::fmt(&self.upgrade(), formatter)
+    }
+}
+
+// Methods are private; not intended to be implemented outside of cxxbridge
+// codebase.
+pub unsafe trait WeakPtrTarget {
+    #[doc(hidden)]
+    const __NAME: &'static dyn Display;
+    #[doc(hidden)]
+    unsafe fn __null(new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __clone(this: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __downgrade(shared: *const c_void, new: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void);
+    #[doc(hidden)]
+    unsafe fn __drop(this: *mut c_void);
+}
+
+macro_rules! impl_weak_ptr_target {
+    ($segment:expr, $name:expr, $ty:ty) => {
+        unsafe impl WeakPtrTarget for $ty {
+            const __NAME: &'static dyn Display = &$name;
+            unsafe fn __null(new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")]
+                        fn __null(new: *mut c_void);
+                    }
+                }
+                __null(new);
+            }
+            unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")]
+                        fn __clone(this: *const c_void, new: *mut c_void);
+                    }
+                }
+                __clone(this, new);
+            }
+            unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")]
+                        fn __downgrade(shared: *const c_void, weak: *mut c_void);
+                    }
+                }
+                __downgrade(shared, weak);
+            }
+            unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")]
+                        fn __upgrade(weak: *const c_void, shared: *mut c_void);
+                    }
+                }
+                __upgrade(weak, shared);
+            }
+            unsafe fn __drop(this: *mut c_void) {
+                extern "C" {
+                    attr! {
+                        #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")]
+                        fn __drop(this: *mut c_void);
+                    }
+                }
+                __drop(this);
+            }
+        }
+    };
+}
+
+macro_rules! impl_weak_ptr_target_for_primitive {
+    ($ty:ident) => {
+        impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
+impl_weak_ptr_target_for_primitive!(bool);
+impl_weak_ptr_target_for_primitive!(u8);
+impl_weak_ptr_target_for_primitive!(u16);
+impl_weak_ptr_target_for_primitive!(u32);
+impl_weak_ptr_target_for_primitive!(u64);
+impl_weak_ptr_target_for_primitive!(usize);
+impl_weak_ptr_target_for_primitive!(i8);
+impl_weak_ptr_target_for_primitive!(i16);
+impl_weak_ptr_target_for_primitive!(i32);
+impl_weak_ptr_target_for_primitive!(i64);
+impl_weak_ptr_target_for_primitive!(isize);
+impl_weak_ptr_target_for_primitive!(f32);
+impl_weak_ptr_target_for_primitive!(f64);
+
+impl_weak_ptr_target!("string", "CxxString", CxxString);
diff --git a/syntax/check.rs b/syntax/check.rs
index ded5c53..39ea04e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -32,6 +32,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
             Type::SharedPtr(ptr) => check_type_shared_ptr(cx, ptr),
+            Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
@@ -152,6 +153,27 @@ fn check_type_shared_ptr(cx: &mut Check, ptr: &Ty1) {
     cx.error(ptr, "unsupported shared_ptr target type");
 }
 
+fn check_type_weak_ptr(cx: &mut Check, ptr: &Ty1) {
+    if let Type::Ident(ident) = &ptr.inner {
+        if cx.types.rust.contains(&ident.rust) {
+            cx.error(ptr, "weak_ptr of a Rust type is not supported yet");
+            return;
+        }
+
+        match Atom::from(&ident.rust) {
+            None | Some(Bool) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+            | Some(F64) | Some(CxxString) => return,
+            Some(Char) | Some(RustString) => {}
+        }
+    } else if let Type::CxxVector(_) = &ptr.inner {
+        cx.error(ptr, "std::weak_ptr<std::vector> is not supported yet");
+        return;
+    }
+
+    cx.error(ptr, "unsupported weak_ptr target type");
+}
+
 fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
     if let Type::Ident(ident) = &ptr.inner {
         if cx.types.rust.contains(&ident.rust) {
@@ -434,6 +456,7 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
         | Type::RustVec(ty)
         | Type::UniquePtr(ty)
         | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
         | Type::CxxVector(ty) => {
             if let Type::Ident(inner) = &ty.inner {
                 if Atom::from(&inner.rust).is_none() {
@@ -506,6 +529,7 @@ fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"
         || ident == "SharedPtr"
+        || ident == "WeakPtr"
         || ident == "Vec"
         || ident == "CxxVector"
         || ident == "str"
@@ -527,6 +551,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         | Type::RustVec(_)
         | Type::UniquePtr(_)
         | Type::SharedPtr(_)
+        | Type::WeakPtr(_)
         | Type::Ref(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
@@ -599,6 +624,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::RustVec(_) => "Vec".to_owned(),
         Type::UniquePtr(_) => "unique_ptr".to_owned(),
         Type::SharedPtr(_) => "shared_ptr".to_owned(),
+        Type::WeakPtr(_) => "weak_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 9b154f6..d70e7cc 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -46,6 +46,7 @@ impl Hash for Type {
             Type::RustBox(t) => t.hash(state),
             Type::UniquePtr(t) => t.hash(state),
             Type::SharedPtr(t) => t.hash(state),
+            Type::WeakPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
@@ -67,6 +68,7 @@ impl PartialEq for Type {
             (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
             (Type::UniquePtr(lhs), Type::UniquePtr(rhs)) => lhs == rhs,
             (Type::SharedPtr(lhs), Type::SharedPtr(rhs)) => lhs == rhs,
+            (Type::WeakPtr(lhs), Type::WeakPtr(rhs)) => lhs == rhs,
             (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs,
             (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs,
             (Type::RustVec(lhs), Type::RustVec(rhs)) => lhs == rhs,
diff --git a/syntax/improper.rs b/syntax/improper.rs
index c0f6983..d672e7d 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -28,7 +28,9 @@ impl<'a> Types<'a> {
             | Type::Fn(_)
             | Type::Void(_)
             | Type::SliceRef(_) => Definite(true),
-            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::CxxVector(_) => Definite(false),
+            Type::UniquePtr(_) | Type::SharedPtr(_) | Type::WeakPtr(_) | Type::CxxVector(_) => {
+                Definite(false)
+            }
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 7f8fd9a..111cec3 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -170,6 +170,7 @@ pub enum Type {
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
     SharedPtr(Box<Ty1>),
+    WeakPtr(Box<Ty1>),
     Ref(Box<Ref>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
diff --git a/syntax/parse.rs b/syntax/parse.rs
index f72253a..1ae4c2d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -901,6 +901,16 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             rangle: generic.gt_token,
                         })));
                     }
+                } else if ident == "WeakPtr" && generic.args.len() == 1 {
+                    if let GenericArgument::Type(arg) = &generic.args[0] {
+                        let inner = parse_type(arg)?;
+                        return Ok(Type::WeakPtr(Box::new(Ty1 {
+                            name: ident,
+                            langle: generic.lt_token,
+                            inner,
+                            rangle: generic.gt_token,
+                        })));
+                    }
                 } else if ident == "CxxVector" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
                         let inner = parse_type(arg)?;
diff --git a/syntax/pod.rs b/syntax/pod.rs
index d808a99..e1c4831 100644
--- a/syntax/pod.rs
+++ b/syntax/pod.rs
@@ -26,6 +26,7 @@ impl<'a> Types<'a> {
             | Type::RustVec(_)
             | Type::UniquePtr(_)
             | Type::SharedPtr(_)
+            | Type::WeakPtr(_)
             | Type::CxxVector(_)
             | Type::Void(_) => false,
             Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index ae2d1d9..8348704 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -23,6 +23,7 @@ impl ToTokens for Type {
             Type::RustBox(ty)
             | Type::UniquePtr(ty)
             | Type::SharedPtr(ty)
+            | Type::WeakPtr(ty)
             | Type::CxxVector(ty)
             | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
@@ -46,7 +47,7 @@ impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let span = self.name.span();
         let name = self.name.to_string();
-        if let "UniquePtr" | "SharedPtr" | "CxxVector" = name.as_str() {
+        if let "UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" = name.as_str() {
             tokens.extend(quote_spanned!(span=> ::cxx::));
         } else if name == "Vec" {
             tokens.extend(quote_spanned!(span=> ::std::vec::));
diff --git a/syntax/types.rs b/syntax/types.rs
index 1056854..f7682bc 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -45,6 +45,7 @@ impl<'a> Types<'a> {
                 Type::RustBox(ty)
                 | Type::UniquePtr(ty)
                 | Type::SharedPtr(ty)
+                | Type::WeakPtr(ty)
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index c41433f..2d564fa 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -178,6 +178,8 @@ pub mod ffi {
         fn c_method_mut_on_shared(self: &mut Shared) -> &mut usize;
         fn c_set_array(self: &mut Array, value: i32);
 
+        fn c_get_use_count(weak: &WeakPtr<C>) -> usize;
+
         #[rust_name = "i32_overloaded_method"]
         fn cOverloadedMethod(&self, x: i32) -> String;
         #[rust_name = "str_overloaded_method"]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 0ecedb1..50a11da 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -538,6 +538,10 @@ const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c) {
   throw std::runtime_error("unimplemented");
 }
 
+size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept {
+  return weak.use_count();
+}
+
 extern "C" C *cxx_test_suite_get_unique_ptr() noexcept {
   return std::unique_ptr<C>(new C{2020}).release();
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 1f83ce5..8235f5f 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -168,6 +168,8 @@ rust::Vec<uint8_t> c_try_return_rust_vec();
 rust::Vec<rust::String> c_try_return_rust_vec_string();
 const rust::Vec<uint8_t> &c_try_return_ref_rust_vec(const C &c);
 
+size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept;
+
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D &d);
 void c_take_trivial(D d);
diff --git a/tests/test.rs b/tests/test.rs
index 4427c7c..273abe9 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,5 +1,6 @@
 #![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
 
+use cxx::SharedPtr;
 use cxx_test_suite::module::ffi2;
 use cxx_test_suite::{cast, ffi, R};
 use std::cell::Cell;
@@ -36,7 +37,6 @@ fn test_c_return() {
     assert_eq!(2020, ffi::c_return_shared().z);
     assert_eq!(2020, ffi::c_return_box().0);
     ffi::c_return_unique_ptr();
-    ffi::c_return_shared_ptr();
     ffi2::c_return_ns_unique_ptr();
     assert_eq!(2020, *ffi::c_return_ref(&shared));
     assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared));
@@ -242,6 +242,20 @@ fn test_c_method_calls() {
 }
 
 #[test]
+fn test_shared_ptr_weak_ptr() {
+    let shared_ptr = ffi::c_return_shared_ptr();
+    let weak_ptr = SharedPtr::downgrade(&shared_ptr);
+    assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
+
+    assert!(!weak_ptr.upgrade().is_null());
+    assert_eq!(1, ffi::c_get_use_count(&weak_ptr));
+
+    drop(shared_ptr);
+    assert_eq!(0, ffi::c_get_use_count(&weak_ptr));
+    assert!(weak_ptr.upgrade().is_null());
+}
+
+#[test]
 fn test_c_ns_method_calls() {
     let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
 

From cb9408df8b6e7fab2e1c38c5237ac477b356592d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 02:38:44 +0000
Subject: [PATCH 1850/2232] Release 1.0.23


---

diff --git a/Cargo.toml b/Cargo.toml
index 44e9b14..3d50353 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.22" # remember to update html_root_url
+version = "1.0.23" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.22", path = "macro" }
+cxxbridge-macro = { version = "=1.0.23", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.22", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.23", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.22", path = "gen/build" }
+cxx-build = { version = "=1.0.23", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 658e42a..4e84fcb 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.22"
+version = "1.0.23"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 1fc38fc..2c9817f 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.22"
+version = "1.0.23"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index a0ce73c..dd0b897 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.22"
+version = "1.0.23"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 22fdcfb..bf883b2 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.22"
+version = "0.7.23"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 0edd8c6..eac2a71 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.22"
+version = "1.0.23"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 76453ea..d7cead0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.22")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.23")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index f918cb1..2e393f8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.22"
+version = "1.0.23"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.22"
+version = "1.0.23"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.22"
+version = "0.7.23"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.22"
+version = "1.0.23"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.22"
+version = "1.0.23"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.22"
+version = "1.0.23"
 dependencies = [
  "cxx",
  "proc-macro2",

From 3d2ef674a41e25e0546524a8c02a9ae26c7338e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:04:11 +0000
Subject: [PATCH 1851/2232] Add lifetimes to ExternType and TypeAlias syntax tree


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index abc9670..99cfdf8 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -136,6 +136,7 @@ mod tests {
                 cxx: ident.clone(),
                 rust: ident,
             },
+            lifetimes: Vec::new(),
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 111cec3..c878ae2 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,6 +74,7 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub lifetimes: Vec<Lifetime>,
     pub colon_token: Option<Token![:]>,
     pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
@@ -115,6 +116,7 @@ pub struct TypeAlias {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub lifetimes: Vec<Lifetime>,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1ae4c2d..0cbb2aa 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -385,6 +385,7 @@ fn parse_extern_type(
 
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
+    let lifetimes = Vec::new();
     let colon_token = None;
     let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
@@ -398,6 +399,7 @@ fn parse_extern_type(
         derives,
         type_token,
         name,
+        lifetimes,
         colon_token,
         bounds,
         semi_token,
@@ -632,12 +634,14 @@ fn parse_type_alias(
     }
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
+    let lifetimes = Vec::new();
 
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
         type_token,
         name,
+        lifetimes,
         eq_token,
         ty,
         semi_token,
@@ -704,6 +708,7 @@ fn parse_extern_type_bounded(
     );
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
+    let lifetimes = Vec::new();
     let colon_token = Some(colon_token);
 
     Ok(match lang {
@@ -715,6 +720,7 @@ fn parse_extern_type_bounded(
         derives,
         type_token,
         name,
+        lifetimes,
         colon_token,
         bounds,
         semi_token,

From e81647ffdaafb12b5a3bc645ecf7f08d6a37f4dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:04:11 +0000
Subject: [PATCH 1852/2232] Parse lifetimes on foreign module types


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0cbb2aa..5c37570 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -13,8 +13,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lifetime, Lit,
+    LitStr, Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
     Variant as RustVariant,
 };
@@ -580,14 +580,45 @@ fn parse_extern_verbatim(
             }
         };
         let ident: Ident = input.parse()?;
+        let generics: Generics = input.parse()?;
+        let mut lifetimes = Vec::new();
+        let mut has_unsupported_generic_param = false;
+        for param in generics.params {
+            match param {
+                GenericParam::Lifetime(param) => {
+                    if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                        let msg = "lifetime parameter with bounds is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                    lifetimes.push(param.lifetime);
+                }
+                GenericParam::Type(param) => {
+                    if !has_unsupported_generic_param {
+                        let msg = "extern type with generic type parameter is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                }
+                GenericParam::Const(param) => {
+                    if !has_unsupported_generic_param {
+                        let msg = "extern type with const generic parameter is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                }
+            }
+        }
         let lookahead = input.lookahead1();
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
-            parse_type_alias(cx, attrs, type_token, ident, input, lang, namespace)
+            parse_type_alias(
+                cx, attrs, type_token, ident, lifetimes, input, lang, namespace,
+            )
         } else if lookahead.peek(Token![:]) {
             // type Opaque: Bound2 + Bound2;
             parse_extern_type_bounded(
-                cx, attrs, type_token, ident, input, lang, trusted, namespace,
+                cx, attrs, type_token, ident, lifetimes, input, lang, trusted, namespace,
             )
         } else {
             Err(lookahead.error())
@@ -601,6 +632,7 @@ fn parse_type_alias(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
+    lifetimes: Vec<Lifetime>,
     input: ParseStream,
     lang: Lang,
     namespace: &Namespace,
@@ -634,7 +666,6 @@ fn parse_type_alias(
     }
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
-    let lifetimes = Vec::new();
 
     Ok(Api::TypeAlias(TypeAlias {
         doc,
@@ -653,6 +684,7 @@ fn parse_extern_type_bounded(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
+    lifetimes: Vec<Lifetime>,
     input: ParseStream,
     lang: Lang,
     trusted: bool,
@@ -708,7 +740,6 @@ fn parse_extern_type_bounded(
     );
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
-    let lifetimes = Vec::new();
     let colon_token = Some(colon_token);
 
     Ok(match lang {

From fecb988491f9a97061b24ef70fa5f9e7202dff9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:04:12 +0000
Subject: [PATCH 1853/2232] Add ui tests of extern type lifetime parsing


---

diff --git a/tests/ui/extern_type_generic.rs b/tests/ui/extern_type_generic.rs
new file mode 100644
index 0000000..4de2c98
--- /dev/null
+++ b/tests/ui/extern_type_generic.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Generic<T>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_generic.stderr b/tests/ui/extern_type_generic.stderr
new file mode 100644
index 0000000..e710290
--- /dev/null
+++ b/tests/ui/extern_type_generic.stderr
@@ -0,0 +1,11 @@
+error: extern type with generic type parameter is not supported yet
+ --> $DIR/extern_type_generic.rs:4:22
+  |
+4 |         type Generic<T>;
+  |                      ^
+
+error: expected `=` or `:`
+ --> $DIR/extern_type_generic.rs:4:24
+  |
+4 |         type Generic<T>;
+  |                        ^
diff --git a/tests/ui/extern_type_lifetime_bound.rs b/tests/ui/extern_type_lifetime_bound.rs
new file mode 100644
index 0000000..ad58181
--- /dev/null
+++ b/tests/ui/extern_type_lifetime_bound.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Complex<'a, 'b: 'a>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_lifetime_bound.stderr b/tests/ui/extern_type_lifetime_bound.stderr
new file mode 100644
index 0000000..05d430b
--- /dev/null
+++ b/tests/ui/extern_type_lifetime_bound.stderr
@@ -0,0 +1,11 @@
+error: lifetime parameter with bounds is not supported yet
+ --> $DIR/extern_type_lifetime_bound.rs:4:26
+  |
+4 |         type Complex<'a, 'b: 'a>;
+  |                          ^^^^^^
+
+error: expected `=` or `:`
+ --> $DIR/extern_type_lifetime_bound.rs:4:33
+  |
+4 |         type Complex<'a, 'b: 'a>;
+  |                                 ^

From a870ac7724d0ac1ca70a6a6a4b0a7f32861061b2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:04:12 +0000
Subject: [PATCH 1854/2232] Handle extern time lifetimes followed by semicolon


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 5c37570..65e07aa 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -615,7 +615,7 @@ fn parse_extern_verbatim(
             parse_type_alias(
                 cx, attrs, type_token, ident, lifetimes, input, lang, namespace,
             )
-        } else if lookahead.peek(Token![:]) {
+        } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
             // type Opaque: Bound2 + Bound2;
             parse_extern_type_bounded(
                 cx, attrs, type_token, ident, lifetimes, input, lang, trusted, namespace,
@@ -690,33 +690,35 @@ fn parse_extern_type_bounded(
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    let colon_token: Token![:] = input.parse()?;
     let mut bounds = Vec::new();
-    loop {
-        match input.parse()? {
-            TypeParamBound::Trait(TraitBound {
-                paren_token: None,
-                modifier: TraitBoundModifier::None,
-                lifetimes: None,
-                path,
-            }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
-                bounds.push(derive);
-                true
-            } else {
-                false
-            } => {}
-            bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
-                cx.error(bound, "unsupported trait");
+    let colon_token: Option<Token![:]> = input.parse()?;
+    if colon_token.is_some() {
+        loop {
+            match input.parse()? {
+                TypeParamBound::Trait(TraitBound {
+                    paren_token: None,
+                    modifier: TraitBoundModifier::None,
+                    lifetimes: None,
+                    path,
+                }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
+                    bounds.push(derive);
+                    true
+                } else {
+                    false
+                } => {}
+                bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
+                    cx.error(bound, "unsupported trait");
+                }
             }
-        }
 
-        let lookahead = input.lookahead1();
-        if lookahead.peek(Token![+]) {
-            input.parse::<Token![+]>()?;
-        } else if lookahead.peek(Token![;]) {
-            break;
-        } else {
-            return Err(lookahead.error());
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![+]) {
+                input.parse::<Token![+]>()?;
+            } else if lookahead.peek(Token![;]) {
+                break;
+            } else {
+                return Err(lookahead.error());
+            }
         }
     }
     let semi_token: Token![;] = input.parse()?;
@@ -740,7 +742,6 @@ fn parse_extern_type_bounded(
     );
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
-    let colon_token = Some(colon_token);
 
     Ok(match lang {
         Lang::Cxx => Api::CxxType,
diff --git a/tests/ui/extern_type_generic.stderr b/tests/ui/extern_type_generic.stderr
index e710290..95faec6 100644
--- a/tests/ui/extern_type_generic.stderr
+++ b/tests/ui/extern_type_generic.stderr
@@ -3,9 +3,3 @@ error: extern type with generic type parameter is not supported yet
   |
 4 |         type Generic<T>;
   |                      ^
-
-error: expected `=` or `:`
- --> $DIR/extern_type_generic.rs:4:24
-  |
-4 |         type Generic<T>;
-  |                        ^
diff --git a/tests/ui/extern_type_lifetime_bound.stderr b/tests/ui/extern_type_lifetime_bound.stderr
index 05d430b..8c58050 100644
--- a/tests/ui/extern_type_lifetime_bound.stderr
+++ b/tests/ui/extern_type_lifetime_bound.stderr
@@ -3,9 +3,3 @@ error: lifetime parameter with bounds is not supported yet
   |
 4 |         type Complex<'a, 'b: 'a>;
   |                          ^^^^^^
-
-error: expected `=` or `:`
- --> $DIR/extern_type_lifetime_bound.rs:4:33
-  |
-4 |         type Complex<'a, 'b: 'a>;
-  |                                 ^

From 446756f4c93cd1e8650161bcfb56a7e2e2bb8c56 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:04:12 +0000
Subject: [PATCH 1855/2232] Indicate that extern type with lifetimes is not implemented yet


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 39ea04e..29013cb 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -337,6 +337,10 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
+    if let Some(lifetime) = ety.lifetimes.first() {
+        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+    }
+
     if !ety.bounds.is_empty() {
         let bounds = &ety.bounds;
         let span = quote!(#(#bounds)*);
@@ -440,6 +444,10 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         let msg = format!("derive({}) on extern type alias is not supported", derive);
         cx.error(derive, msg);
     }
+
+    if let Some(lifetime) = alias.lifetimes.first() {
+        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+    }
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
diff --git a/tests/ui/extern_type_lifetime.rs b/tests/ui/extern_type_lifetime.rs
new file mode 100644
index 0000000..4e0e2f7
--- /dev/null
+++ b/tests/ui/extern_type_lifetime.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Complex<'a, 'b>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_lifetime.stderr b/tests/ui/extern_type_lifetime.stderr
new file mode 100644
index 0000000..85a5d39
--- /dev/null
+++ b/tests/ui/extern_type_lifetime.stderr
@@ -0,0 +1,5 @@
+error: extern type with lifetimes is not supported yet
+ --> $DIR/extern_type_lifetime.rs:4:22
+  |
+4 |         type Complex<'a, 'b>;
+  |                      ^^

From 0c8cb95a3c5aa964a7c33fce07ab7e11882d2160 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 05:34:05 +0000
Subject: [PATCH 1856/2232] Merge pull request #610 from dtolnay/lifetime


Parse lifetimes on foreign module types
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index abc9670..99cfdf8 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -136,6 +136,7 @@ mod tests {
                 cxx: ident.clone(),
                 rust: ident,
             },
+            lifetimes: Vec::new(),
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/syntax/check.rs b/syntax/check.rs
index 39ea04e..29013cb 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -337,6 +337,10 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
+    if let Some(lifetime) = ety.lifetimes.first() {
+        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+    }
+
     if !ety.bounds.is_empty() {
         let bounds = &ety.bounds;
         let span = quote!(#(#bounds)*);
@@ -440,6 +444,10 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         let msg = format!("derive({}) on extern type alias is not supported", derive);
         cx.error(derive, msg);
     }
+
+    if let Some(lifetime) = alias.lifetimes.first() {
+        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+    }
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 111cec3..c878ae2 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,6 +74,7 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub lifetimes: Vec<Lifetime>,
     pub colon_token: Option<Token![:]>,
     pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
@@ -115,6 +116,7 @@ pub struct TypeAlias {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
+    pub lifetimes: Vec<Lifetime>,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1ae4c2d..65e07aa 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -13,8 +13,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lifetime, Lit,
+    LitStr, Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
     Variant as RustVariant,
 };
@@ -385,6 +385,7 @@ fn parse_extern_type(
 
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
+    let lifetimes = Vec::new();
     let colon_token = None;
     let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
@@ -398,6 +399,7 @@ fn parse_extern_type(
         derives,
         type_token,
         name,
+        lifetimes,
         colon_token,
         bounds,
         semi_token,
@@ -578,14 +580,45 @@ fn parse_extern_verbatim(
             }
         };
         let ident: Ident = input.parse()?;
+        let generics: Generics = input.parse()?;
+        let mut lifetimes = Vec::new();
+        let mut has_unsupported_generic_param = false;
+        for param in generics.params {
+            match param {
+                GenericParam::Lifetime(param) => {
+                    if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                        let msg = "lifetime parameter with bounds is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                    lifetimes.push(param.lifetime);
+                }
+                GenericParam::Type(param) => {
+                    if !has_unsupported_generic_param {
+                        let msg = "extern type with generic type parameter is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                }
+                GenericParam::Const(param) => {
+                    if !has_unsupported_generic_param {
+                        let msg = "extern type with const generic parameter is not supported yet";
+                        cx.error(&param, msg);
+                        has_unsupported_generic_param = true;
+                    }
+                }
+            }
+        }
         let lookahead = input.lookahead1();
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
-            parse_type_alias(cx, attrs, type_token, ident, input, lang, namespace)
-        } else if lookahead.peek(Token![:]) {
+            parse_type_alias(
+                cx, attrs, type_token, ident, lifetimes, input, lang, namespace,
+            )
+        } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
             // type Opaque: Bound2 + Bound2;
             parse_extern_type_bounded(
-                cx, attrs, type_token, ident, input, lang, trusted, namespace,
+                cx, attrs, type_token, ident, lifetimes, input, lang, trusted, namespace,
             )
         } else {
             Err(lookahead.error())
@@ -599,6 +632,7 @@ fn parse_type_alias(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
+    lifetimes: Vec<Lifetime>,
     input: ParseStream,
     lang: Lang,
     namespace: &Namespace,
@@ -638,6 +672,7 @@ fn parse_type_alias(
         derives,
         type_token,
         name,
+        lifetimes,
         eq_token,
         ty,
         semi_token,
@@ -649,38 +684,41 @@ fn parse_extern_type_bounded(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
+    lifetimes: Vec<Lifetime>,
     input: ParseStream,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    let colon_token: Token![:] = input.parse()?;
     let mut bounds = Vec::new();
-    loop {
-        match input.parse()? {
-            TypeParamBound::Trait(TraitBound {
-                paren_token: None,
-                modifier: TraitBoundModifier::None,
-                lifetimes: None,
-                path,
-            }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
-                bounds.push(derive);
-                true
-            } else {
-                false
-            } => {}
-            bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
-                cx.error(bound, "unsupported trait");
+    let colon_token: Option<Token![:]> = input.parse()?;
+    if colon_token.is_some() {
+        loop {
+            match input.parse()? {
+                TypeParamBound::Trait(TraitBound {
+                    paren_token: None,
+                    modifier: TraitBoundModifier::None,
+                    lifetimes: None,
+                    path,
+                }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
+                    bounds.push(derive);
+                    true
+                } else {
+                    false
+                } => {}
+                bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
+                    cx.error(bound, "unsupported trait");
+                }
             }
-        }
 
-        let lookahead = input.lookahead1();
-        if lookahead.peek(Token![+]) {
-            input.parse::<Token![+]>()?;
-        } else if lookahead.peek(Token![;]) {
-            break;
-        } else {
-            return Err(lookahead.error());
+            let lookahead = input.lookahead1();
+            if lookahead.peek(Token![+]) {
+                input.parse::<Token![+]>()?;
+            } else if lookahead.peek(Token![;]) {
+                break;
+            } else {
+                return Err(lookahead.error());
+            }
         }
     }
     let semi_token: Token![;] = input.parse()?;
@@ -704,7 +742,6 @@ fn parse_extern_type_bounded(
     );
 
     let name = pair(namespace, &ident, cxx_name, rust_name);
-    let colon_token = Some(colon_token);
 
     Ok(match lang {
         Lang::Cxx => Api::CxxType,
@@ -715,6 +752,7 @@ fn parse_extern_type_bounded(
         derives,
         type_token,
         name,
+        lifetimes,
         colon_token,
         bounds,
         semi_token,
diff --git a/tests/ui/extern_type_generic.rs b/tests/ui/extern_type_generic.rs
new file mode 100644
index 0000000..4de2c98
--- /dev/null
+++ b/tests/ui/extern_type_generic.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Generic<T>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_generic.stderr b/tests/ui/extern_type_generic.stderr
new file mode 100644
index 0000000..95faec6
--- /dev/null
+++ b/tests/ui/extern_type_generic.stderr
@@ -0,0 +1,5 @@
+error: extern type with generic type parameter is not supported yet
+ --> $DIR/extern_type_generic.rs:4:22
+  |
+4 |         type Generic<T>;
+  |                      ^
diff --git a/tests/ui/extern_type_lifetime.rs b/tests/ui/extern_type_lifetime.rs
new file mode 100644
index 0000000..4e0e2f7
--- /dev/null
+++ b/tests/ui/extern_type_lifetime.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Complex<'a, 'b>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_lifetime.stderr b/tests/ui/extern_type_lifetime.stderr
new file mode 100644
index 0000000..85a5d39
--- /dev/null
+++ b/tests/ui/extern_type_lifetime.stderr
@@ -0,0 +1,5 @@
+error: extern type with lifetimes is not supported yet
+ --> $DIR/extern_type_lifetime.rs:4:22
+  |
+4 |         type Complex<'a, 'b>;
+  |                      ^^
diff --git a/tests/ui/extern_type_lifetime_bound.rs b/tests/ui/extern_type_lifetime_bound.rs
new file mode 100644
index 0000000..ad58181
--- /dev/null
+++ b/tests/ui/extern_type_lifetime_bound.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        type Complex<'a, 'b: 'a>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/extern_type_lifetime_bound.stderr b/tests/ui/extern_type_lifetime_bound.stderr
new file mode 100644
index 0000000..8c58050
--- /dev/null
+++ b/tests/ui/extern_type_lifetime_bound.stderr
@@ -0,0 +1,5 @@
+error: lifetime parameter with bounds is not supported yet
+ --> $DIR/extern_type_lifetime_bound.rs:4:26
+  |
+4 |         type Complex<'a, 'b: 'a>;
+  |                          ^^^^^^

From ee3123241fbc49912ce79da024271d21eba9237c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 06:12:28 +0000
Subject: [PATCH 1857/2232] Store additional token information with extern type lifetimes


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 99cfdf8..66d854e 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -52,9 +52,10 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
 mod tests {
     use super::NamespaceEntries;
     use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Lang, Pair};
+    use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
     use std::iter::FromIterator;
+    use syn::punctuated::Punctuated;
     use syn::Token;
 
     #[test]
@@ -136,7 +137,11 @@ mod tests {
                 cxx: ident.clone(),
                 rust: ident,
             },
-            lifetimes: Vec::new(),
+            generics: Lifetimes {
+                lt_token: None,
+                lifetimes: Punctuated::new(),
+                gt_token: None,
+            },
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/syntax/check.rs b/syntax/check.rs
index 29013cb..fcd5f9a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -337,7 +337,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = ety.lifetimes.first() {
+    if let Some(lifetime) = ety.generics.lifetimes.first() {
         cx.error(lifetime, "extern type with lifetimes is not supported yet");
     }
 
@@ -445,7 +445,7 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = alias.lifetimes.first() {
+    if let Some(lifetime) = alias.generics.lifetimes.first() {
         cx.error(lifetime, "extern type with lifetimes is not supported yet");
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c878ae2..009afee 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,7 +74,7 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
-    pub lifetimes: Vec<Lifetime>,
+    pub generics: Lifetimes,
     pub colon_token: Option<Token![:]>,
     pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
@@ -116,7 +116,7 @@ pub struct TypeAlias {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
-    pub lifetimes: Vec<Lifetime>,
+    pub generics: Lifetimes,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
@@ -130,6 +130,12 @@ pub struct Impl {
     pub negative_token: Option<Token![!]>,
 }
 
+pub struct Lifetimes {
+    pub lt_token: Option<Token![<]>,
+    pub lifetimes: Punctuated<Lifetime, Token![,]>,
+    pub gt_token: Option<Token![>]>,
+}
+
 pub struct Signature {
     pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 65e07aa..bb5ac7b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,8 +4,8 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1, Type,
-    TypeAlias, Var, Variant,
+    Lang, Lifetimes, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1,
+    Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -13,8 +13,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lifetime, Lit,
-    LitStr, Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
+    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
     Variant as RustVariant,
 };
@@ -385,7 +385,11 @@ fn parse_extern_type(
 
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
-    let lifetimes = Vec::new();
+    let generics = Lifetimes {
+        lt_token: None,
+        lifetimes: Punctuated::new(),
+        gt_token: None,
+    };
     let colon_token = None;
     let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
@@ -399,7 +403,7 @@ fn parse_extern_type(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         colon_token,
         bounds,
         semi_token,
@@ -581,9 +585,10 @@ fn parse_extern_verbatim(
         };
         let ident: Ident = input.parse()?;
         let generics: Generics = input.parse()?;
-        let mut lifetimes = Vec::new();
+        let mut lifetimes = Punctuated::new();
         let mut has_unsupported_generic_param = false;
-        for param in generics.params {
+        for pair in generics.params.into_pairs() {
+            let (param, punct) = pair.into_tuple();
             match param {
                 GenericParam::Lifetime(param) => {
                     if !param.bounds.is_empty() && !has_unsupported_generic_param {
@@ -591,7 +596,10 @@ fn parse_extern_verbatim(
                         cx.error(&param, msg);
                         has_unsupported_generic_param = true;
                     }
-                    lifetimes.push(param.lifetime);
+                    lifetimes.push_value(param.lifetime);
+                    if let Some(punct) = punct {
+                        lifetimes.push_punct(punct);
+                    }
                 }
                 GenericParam::Type(param) => {
                     if !has_unsupported_generic_param {
@@ -609,6 +617,11 @@ fn parse_extern_verbatim(
                 }
             }
         }
+        let lifetimes = Lifetimes {
+            lt_token: generics.lt_token,
+            lifetimes,
+            gt_token: generics.gt_token,
+        };
         let lookahead = input.lookahead1();
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
@@ -632,7 +645,7 @@ fn parse_type_alias(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
-    lifetimes: Vec<Lifetime>,
+    generics: Lifetimes,
     input: ParseStream,
     lang: Lang,
     namespace: &Namespace,
@@ -672,7 +685,7 @@ fn parse_type_alias(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         eq_token,
         ty,
         semi_token,
@@ -684,7 +697,7 @@ fn parse_extern_type_bounded(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
-    lifetimes: Vec<Lifetime>,
+    generics: Lifetimes,
     input: ParseStream,
     lang: Lang,
     trusted: bool,
@@ -752,7 +765,7 @@ fn parse_extern_type_bounded(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         colon_token,
         bounds,
         semi_token,

From 8c80de77c6a8dc5cd2422615123e96f49b072890 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 06:41:59 +0000
Subject: [PATCH 1858/2232] Emit lifetimes on extern type into Rust macro output


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e53e5b6..d71db6f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -313,16 +313,23 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
     let doc = &ety.doc;
+    let generics = &ety.generics;
     let type_id = type_id(&ety.name);
 
+    let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
+        let field = format_ident!("_lifetime_{}", lifetime.ident);
+        quote!(#field: ::std::marker::PhantomData<&#lifetime ()>)
+    });
+
     quote! {
         #doc
         #[repr(C)]
-        pub struct #ident {
+        pub struct #ident #generics {
             _private: ::cxx::private::Opaque,
+            #(#lifetime_fields,)*
         }
 
-        unsafe impl ::cxx::ExternType for #ident {
+        unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
             type Kind = ::cxx::kind::Opaque;
         }
@@ -959,10 +966,11 @@ fn expand_rust_function_shim_super(
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let ident = &alias.name.rust;
+    let generics = &alias.generics;
     let ty = &alias.ty;
     quote! {
         #doc
-        pub type #ident = #ty;
+        pub type #ident #generics = #ty;
     }
 }
 
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 8348704..2e14f7a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, RustName, Signature,
-    SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, Receiver, Ref, RustName,
+    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -157,6 +157,14 @@ impl ToTokens for Impl {
     }
 }
 
+impl ToTokens for Lifetimes {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.lt_token.to_tokens(tokens);
+        self.lifetimes.to_tokens(tokens);
+        self.gt_token.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.fn_token.to_tokens(tokens);

From 855bff92ecb2924cd47af631aec9188892e46280 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 06:56:49 +0000
Subject: [PATCH 1859/2232] Merge pull request #611 from dtolnay/lifetime


Emit lifetimes on extern type into Rust macro output
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 99cfdf8..66d854e 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -52,9 +52,10 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
 mod tests {
     use super::NamespaceEntries;
     use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Lang, Pair};
+    use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
     use std::iter::FromIterator;
+    use syn::punctuated::Punctuated;
     use syn::Token;
 
     #[test]
@@ -136,7 +137,11 @@ mod tests {
                 cxx: ident.clone(),
                 rust: ident,
             },
-            lifetimes: Vec::new(),
+            generics: Lifetimes {
+                lt_token: None,
+                lifetimes: Punctuated::new(),
+                gt_token: None,
+            },
             colon_token: None,
             bounds: Vec::new(),
             semi_token: Token![;](Span::call_site()),
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e53e5b6..d71db6f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -313,16 +313,23 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
     let doc = &ety.doc;
+    let generics = &ety.generics;
     let type_id = type_id(&ety.name);
 
+    let lifetime_fields = ety.generics.lifetimes.iter().map(|lifetime| {
+        let field = format_ident!("_lifetime_{}", lifetime.ident);
+        quote!(#field: ::std::marker::PhantomData<&#lifetime ()>)
+    });
+
     quote! {
         #doc
         #[repr(C)]
-        pub struct #ident {
+        pub struct #ident #generics {
             _private: ::cxx::private::Opaque,
+            #(#lifetime_fields,)*
         }
 
-        unsafe impl ::cxx::ExternType for #ident {
+        unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
             type Kind = ::cxx::kind::Opaque;
         }
@@ -959,10 +966,11 @@ fn expand_rust_function_shim_super(
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let ident = &alias.name.rust;
+    let generics = &alias.generics;
     let ty = &alias.ty;
     quote! {
         #doc
-        pub type #ident = #ty;
+        pub type #ident #generics = #ty;
     }
 }
 
diff --git a/syntax/check.rs b/syntax/check.rs
index 29013cb..fcd5f9a 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -337,7 +337,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = ety.lifetimes.first() {
+    if let Some(lifetime) = ety.generics.lifetimes.first() {
         cx.error(lifetime, "extern type with lifetimes is not supported yet");
     }
 
@@ -445,7 +445,7 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = alias.lifetimes.first() {
+    if let Some(lifetime) = alias.generics.lifetimes.first() {
         cx.error(lifetime, "extern type with lifetimes is not supported yet");
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c878ae2..009afee 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,7 +74,7 @@ pub struct ExternType {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
-    pub lifetimes: Vec<Lifetime>,
+    pub generics: Lifetimes,
     pub colon_token: Option<Token![:]>,
     pub bounds: Vec<Derive>,
     pub semi_token: Token![;],
@@ -116,7 +116,7 @@ pub struct TypeAlias {
     pub derives: Vec<Derive>,
     pub type_token: Token![type],
     pub name: Pair,
-    pub lifetimes: Vec<Lifetime>,
+    pub generics: Lifetimes,
     pub eq_token: Token![=],
     pub ty: RustType,
     pub semi_token: Token![;],
@@ -130,6 +130,12 @@ pub struct Impl {
     pub negative_token: Option<Token![!]>,
 }
 
+pub struct Lifetimes {
+    pub lt_token: Option<Token![<]>,
+    pub lifetimes: Punctuated<Lifetime, Token![,]>,
+    pub gt_token: Option<Token![>]>,
+}
+
 pub struct Signature {
     pub unsafety: Option<Token![unsafe]>,
     pub fn_token: Token![fn],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 65e07aa..bb5ac7b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,8 +4,8 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1, Type,
-    TypeAlias, Var, Variant,
+    Lang, Lifetimes, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1,
+    Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -13,8 +13,8 @@ use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
-    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lifetime, Lit,
-    LitStr, Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
+    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
+    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
     Variant as RustVariant,
 };
@@ -385,7 +385,11 @@ fn parse_extern_type(
 
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
-    let lifetimes = Vec::new();
+    let generics = Lifetimes {
+        lt_token: None,
+        lifetimes: Punctuated::new(),
+        gt_token: None,
+    };
     let colon_token = None;
     let bounds = Vec::new();
     let semi_token = foreign_type.semi_token;
@@ -399,7 +403,7 @@ fn parse_extern_type(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         colon_token,
         bounds,
         semi_token,
@@ -581,9 +585,10 @@ fn parse_extern_verbatim(
         };
         let ident: Ident = input.parse()?;
         let generics: Generics = input.parse()?;
-        let mut lifetimes = Vec::new();
+        let mut lifetimes = Punctuated::new();
         let mut has_unsupported_generic_param = false;
-        for param in generics.params {
+        for pair in generics.params.into_pairs() {
+            let (param, punct) = pair.into_tuple();
             match param {
                 GenericParam::Lifetime(param) => {
                     if !param.bounds.is_empty() && !has_unsupported_generic_param {
@@ -591,7 +596,10 @@ fn parse_extern_verbatim(
                         cx.error(&param, msg);
                         has_unsupported_generic_param = true;
                     }
-                    lifetimes.push(param.lifetime);
+                    lifetimes.push_value(param.lifetime);
+                    if let Some(punct) = punct {
+                        lifetimes.push_punct(punct);
+                    }
                 }
                 GenericParam::Type(param) => {
                     if !has_unsupported_generic_param {
@@ -609,6 +617,11 @@ fn parse_extern_verbatim(
                 }
             }
         }
+        let lifetimes = Lifetimes {
+            lt_token: generics.lt_token,
+            lifetimes,
+            gt_token: generics.gt_token,
+        };
         let lookahead = input.lookahead1();
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
@@ -632,7 +645,7 @@ fn parse_type_alias(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
-    lifetimes: Vec<Lifetime>,
+    generics: Lifetimes,
     input: ParseStream,
     lang: Lang,
     namespace: &Namespace,
@@ -672,7 +685,7 @@ fn parse_type_alias(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         eq_token,
         ty,
         semi_token,
@@ -684,7 +697,7 @@ fn parse_extern_type_bounded(
     attrs: Vec<Attribute>,
     type_token: Token![type],
     ident: Ident,
-    lifetimes: Vec<Lifetime>,
+    generics: Lifetimes,
     input: ParseStream,
     lang: Lang,
     trusted: bool,
@@ -752,7 +765,7 @@ fn parse_extern_type_bounded(
         derives,
         type_token,
         name,
-        lifetimes,
+        generics,
         colon_token,
         bounds,
         semi_token,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 8348704..2e14f7a 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, RustName, Signature,
-    SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, Receiver, Ref, RustName,
+    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
@@ -157,6 +157,14 @@ impl ToTokens for Impl {
     }
 }
 
+impl ToTokens for Lifetimes {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        self.lt_token.to_tokens(tokens);
+        self.lifetimes.to_tokens(tokens);
+        self.gt_token.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         self.fn_token.to_tokens(tokens);

From ce088848c5031a59b90ed4160748bdf37f28a252 Mon Sep 17 00:00:00 2001
From: Per Mosegaard <permosegaard@googlemail.com>
Date: Dec 29 2020 21:10:14 +0000
Subject: [PATCH 1860/2232] add support for .hh and .hpp headers


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 6d44e5d..0018dc7 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -425,8 +425,9 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
             }
             Ok(file_type) if file_type.is_file() => {
                 let src = entry.path();
-                if src.extension() != Some(OsStr::new("h")) {
-                    continue;
+                match src.extension().map(|x| x.to_str()).flatten() {
+                    Some("h") | Some("hh") | Some("hpp") => {},
+                    _ => continue
                 }
                 if !dst_created && fs::create_dir_all(dst).is_err() {
                     return;

From c9c473644c9887bc90add859aa89cf17967bd7c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:01:01 +0000
Subject: [PATCH 1861/2232] Merge pull request #613 from permosegaard/permosegaard-additional-header-extensions


add support for .hh and .hpp headers
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 6d44e5d..0018dc7 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -425,8 +425,9 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
             }
             Ok(file_type) if file_type.is_file() => {
                 let src = entry.path();
-                if src.extension() != Some(OsStr::new("h")) {
-                    continue;
+                match src.extension().map(|x| x.to_str()).flatten() {
+                    Some("h") | Some("hh") | Some("hpp") => {},
+                    _ => continue
                 }
                 if !dst_created && fs::create_dir_all(dst).is_err() {
                     return;

From 515cef80447d7bd1fc46de88ce672015142b6b9d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:19:55 +0000
Subject: [PATCH 1862/2232] Format PR 613 with rustfmt 1.4.30-nightly


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 0018dc7..e323071 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -426,8 +426,8 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
             Ok(file_type) if file_type.is_file() => {
                 let src = entry.path();
                 match src.extension().map(|x| x.to_str()).flatten() {
-                    Some("h") | Some("hh") | Some("hpp") => {},
-                    _ => continue
+                    Some("h") | Some("hh") | Some("hpp") => {}
+                    _ => continue,
                 }
                 if !dst_created && fs::create_dir_all(dst).is_err() {
                     return;

From 831b02fc6b6f84143323c0ba0228dac93c40023d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:19:55 +0000
Subject: [PATCH 1863/2232] Resolve clippy map_unwrap_or lint in demo


---

diff --git a/book/src/tutorial.md b/book/src/tutorial.md
index a375ea0..c9fa00c 100644
--- a/book/src/tutorial.md
+++ b/book/src/tutorial.md
@@ -320,7 +320,7 @@ pub struct MultiBuf {
 pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
     let next = buf.chunks.get(buf.pos);
     buf.pos += 1;
-    next.map(Vec::as_slice).unwrap_or(&[])
+    next.map_or(&[], Vec::as_slice)
 }
 #
 # fn main() {
@@ -411,7 +411,7 @@ This is now ready to use. :)
 # pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
 #     let next = buf.chunks.get(buf.pos);
 #     buf.pos += 1;
-#     next.map(Vec::as_slice).unwrap_or(&[])
+#     next.map_or(&[], Vec::as_slice)
 # }
 
 fn main() {
@@ -537,7 +537,7 @@ mod ffi {
 # pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
 #     let next = buf.chunks.get(buf.pos);
 #     buf.pos += 1;
-#     next.map(Vec::as_slice).unwrap_or(&[])
+#     next.map_or(&[], Vec::as_slice)
 # }
 
 fn main() {
diff --git a/demo/src/main.rs b/demo/src/main.rs
index dca596a..458f1f2 100644
--- a/demo/src/main.rs
+++ b/demo/src/main.rs
@@ -38,7 +38,7 @@ pub struct MultiBuf {
 pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] {
     let next = buf.chunks.get(buf.pos);
     buf.pos += 1;
-    next.map(Vec::as_slice).unwrap_or(&[])
+    next.map_or(&[], Vec::as_slice)
 }
 
 fn main() {

From 05aa672b1ebfe224eea34d6decc57aed95ea5bfc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:28:02 +0000
Subject: [PATCH 1864/2232] Suppress all currently triggered clippy pedantic lints


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index e323071..c270415 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -46,13 +46,33 @@
 //! ```
 
 #![allow(
+    clippy::cast_sign_loss,
+    clippy::default_trait_access,
+    clippy::doc_markdown,
     clippy::drop_copy,
+    clippy::enum_glob_use,
     clippy::inherent_to_string,
+    clippy::items_after_statements,
+    clippy::let_underscore_drop,
+    clippy::map_flatten,
+    clippy::match_bool,
+    clippy::match_on_vec_items,
+    clippy::match_same_arms,
+    clippy::module_name_repetitions,
     clippy::needless_doctest_main,
+    clippy::needless_pass_by_value,
     clippy::new_without_default,
     clippy::nonminimal_bool,
+    clippy::option_if_let_else,
     clippy::or_fun_call,
+    clippy::redundant_closure_for_method_calls,
+    clippy::redundant_else,
+    clippy::shadow_unrelated,
+    clippy::similar_names,
+    clippy::single_match_else,
+    clippy::struct_excessive_bools,
     clippy::too_many_arguments,
+    clippy::too_many_lines,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 2372c2c..9072e60 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -1,11 +1,27 @@
 #![allow(
+    clippy::cast_sign_loss,
     clippy::cognitive_complexity,
+    clippy::default_trait_access,
+    clippy::enum_glob_use,
     clippy::inherent_to_string,
+    clippy::items_after_statements,
     clippy::large_enum_variant,
+    clippy::match_bool,
+    clippy::match_on_vec_items,
+    clippy::match_same_arms,
+    clippy::module_name_repetitions,
+    clippy::needless_pass_by_value,
     clippy::new_without_default,
     clippy::nonminimal_bool,
+    clippy::option_if_let_else,
     clippy::or_fun_call,
+    clippy::redundant_else,
+    clippy::shadow_unrelated,
+    clippy::similar_names,
+    clippy::single_match_else,
+    clippy::struct_excessive_bools,
     clippy::too_many_arguments,
+    clippy::too_many_lines,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index dd7d515..4329628 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -9,11 +9,28 @@
 
 #![allow(dead_code)]
 #![allow(
+    clippy::cast_sign_loss,
+    clippy::default_trait_access,
+    clippy::enum_glob_use,
     clippy::inherent_to_string,
+    clippy::items_after_statements,
+    clippy::match_bool,
+    clippy::match_on_vec_items,
+    clippy::match_same_arms,
+    clippy::missing_errors_doc,
+    clippy::module_name_repetitions,
+    clippy::needless_pass_by_value,
     clippy::new_without_default,
     clippy::nonminimal_bool,
+    clippy::option_if_let_else,
     clippy::or_fun_call,
+    clippy::redundant_else,
+    clippy::shadow_unrelated,
+    clippy::similar_names,
+    clippy::single_match_else,
+    clippy::struct_excessive_bools,
     clippy::too_many_arguments,
+    clippy::too_many_lines,
     clippy::toplevel_ref_arg
 )]
 
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 1498bbb..fc7828b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -1,11 +1,27 @@
 #![allow(
+    clippy::cast_sign_loss,
+    clippy::default_trait_access,
+    clippy::doc_markdown,
+    clippy::enum_glob_use,
+    clippy::filter_map,
     clippy::inherent_to_string,
+    clippy::items_after_statements,
     clippy::large_enum_variant,
+    clippy::match_bool,
+    clippy::match_same_arms,
+    clippy::module_name_repetitions,
+    clippy::needless_pass_by_value,
     clippy::new_without_default,
     clippy::nonminimal_bool,
+    clippy::option_if_let_else,
     clippy::or_fun_call,
+    clippy::redundant_else,
+    clippy::shadow_unrelated,
+    clippy::similar_names,
     clippy::single_match,
+    clippy::single_match_else,
     clippy::too_many_arguments,
+    clippy::too_many_lines,
     clippy::toplevel_ref_arg,
     clippy::useless_let_if_seq
 )]
diff --git a/src/lib.rs b/src/lib.rs
index d7cead0..43b7677 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -369,11 +369,17 @@
 #![allow(
     clippy::cognitive_complexity,
     clippy::declare_interior_mutable_const,
+    clippy::doc_markdown,
+    clippy::empty_enum,
     clippy::inherent_to_string,
+    clippy::items_after_statements,
     clippy::large_enum_variant,
     clippy::len_without_is_empty,
+    clippy::missing_errors_doc,
     clippy::missing_safety_doc,
     clippy::module_inception,
+    clippy::module_name_repetitions,
+    clippy::must_use_candidate,
     clippy::needless_doctest_main,
     clippy::new_without_default,
     clippy::or_fun_call,
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 2d564fa..7d7ff9f 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,9 +1,15 @@
 #![allow(
     clippy::boxed_local,
+    clippy::cast_possible_truncation,
     clippy::just_underscores_and_digits,
+    clippy::let_underscore_drop,
+    clippy::must_use_candidate,
+    clippy::needless_pass_by_value,
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref,
-    clippy::unnecessary_wraps
+    clippy::unnecessary_wraps,
+    clippy::unused_self,
+    clippy::used_underscore_binding
 )]
 
 pub mod cast;
diff --git a/tests/test.rs b/tests/test.rs
index 273abe9..d826ecb 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1,4 +1,13 @@
-#![allow(clippy::assertions_on_constants, clippy::float_cmp, clippy::unit_cmp)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::cast_possible_truncation,
+    clippy::cast_possible_wrap,
+    clippy::float_cmp,
+    clippy::needless_pass_by_value,
+    clippy::redundant_closure_for_method_calls,
+    clippy::unit_cmp,
+    clippy::unseparated_literal_suffix
+)]
 
 use cxx::SharedPtr;
 use cxx_test_suite::module::ffi2;
diff --git a/tests/unique_ptr.rs b/tests/unique_ptr.rs
index e5eb66b..bbaa316 100644
--- a/tests/unique_ptr.rs
+++ b/tests/unique_ptr.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::let_underscore_drop)]
+
 use cxx::{CxxString, UniquePtr};
 
 #[test]

From 6208af9ab58e1eaf21dc731d156c76c677efb595 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:30:56 +0000
Subject: [PATCH 1865/2232] Resolve map_flatten pedantic clippy lint


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index c270415..ffce380 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -54,7 +54,6 @@
     clippy::inherent_to_string,
     clippy::items_after_statements,
     clippy::let_underscore_drop,
-    clippy::map_flatten,
     clippy::match_bool,
     clippy::match_on_vec_items,
     clippy::match_same_arms,
@@ -445,7 +444,7 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
             }
             Ok(file_type) if file_type.is_file() => {
                 let src = entry.path();
-                match src.extension().map(|x| x.to_str()).flatten() {
+                match src.extension().and_then(|x| x.to_str()) {
                     Some("h") | Some("hh") | Some("hpp") => {}
                     _ => continue,
                 }

From 9e3df911c538c357fc55d34c8ea9450dc9624891 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:33:28 +0000
Subject: [PATCH 1866/2232] Resolve redundant_closure_for_method_calls pedantic clippy lint


---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index ffce380..fe51cd6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -64,7 +64,6 @@
     clippy::nonminimal_bool,
     clippy::option_if_let_else,
     clippy::or_fun_call,
-    clippy::redundant_closure_for_method_calls,
     clippy::redundant_else,
     clippy::shadow_unrelated,
     clippy::similar_names,
@@ -444,7 +443,7 @@ fn best_effort_copy_headers(src: &Path, dst: &Path, max_depth: usize) {
             }
             Ok(file_type) if file_type.is_file() => {
                 let src = entry.path();
-                match src.extension().and_then(|x| x.to_str()) {
+                match src.extension().and_then(OsStr::to_str) {
                     Some("h") | Some("hh") | Some("hpp") => {}
                     _ => continue,
                 }
diff --git a/tests/test.rs b/tests/test.rs
index d826ecb..950e059 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -4,7 +4,6 @@
     clippy::cast_possible_wrap,
     clippy::float_cmp,
     clippy::needless_pass_by_value,
-    clippy::redundant_closure_for_method_calls,
     clippy::unit_cmp,
     clippy::unseparated_literal_suffix
 )]
@@ -29,7 +28,7 @@ macro_rules! check {
         CORRECT.with(|correct| correct.set(false));
         $run;
         assert!(
-            CORRECT.with(|correct| correct.get()),
+            CORRECT.with(Cell::get),
             "{}",
             stringify!($run),
         );

From d717e8a1a01db4970b06deb700e27f1663105b75 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:40:27 +0000
Subject: [PATCH 1867/2232] Suppress cast_possible_truncation lint in generated Hash shim


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d71db6f..79d678b 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -259,6 +259,7 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
                 operators.extend(quote_spanned! {span=>
                     #[doc(hidden)]
                     #[export_name = #link_name]
+                    #[allow(clippy::cast_possible_truncation)]
                     extern "C" fn #local_name(this: &#ident) -> usize {
                         let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
                         ::std::hash::Hash::hash(this, &mut hasher);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 7d7ff9f..bbce6db 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -1,6 +1,5 @@
 #![allow(
     clippy::boxed_local,
-    clippy::cast_possible_truncation,
     clippy::just_underscores_and_digits,
     clippy::let_underscore_drop,
     clippy::must_use_candidate,

From b4c14554aa34634627e0622557ac9fe126276656 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:44:19 +0000
Subject: [PATCH 1868/2232] Avoid triggering used_underscore_binding on unnamed extern fn args


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index bb5ac7b..c90125a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -501,7 +501,7 @@ fn parse_extern_fn(
                 let ident = match arg.pat.as_ref() {
                     Pat::Ident(pat) => pat.ident.clone(),
                     Pat::Wild(pat) => {
-                        Ident::new(&format!("_{}", args.len()), pat.underscore_token.span)
+                        Ident::new(&format!("arg{}", args.len()), pat.underscore_token.span)
                     }
                     _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                 };
@@ -1070,7 +1070,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             let ty = parse_type(&arg.ty)?;
             let ident = match &arg.name {
                 Some(ident) => ident.0.clone(),
-                None => format_ident!("_{}", i),
+                None => format_ident!("arg{}", i),
             };
             Ok(Var { ident, ty })
         })
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index bbce6db..d07ff45 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -7,8 +7,7 @@
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref,
     clippy::unnecessary_wraps,
-    clippy::unused_self,
-    clippy::used_underscore_binding
+    clippy::unused_self
 )]
 
 pub mod cast;

From cff6f30d38d9cff64768a13fab5a7a833e5d6f2a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:49:31 +0000
Subject: [PATCH 1869/2232] Inform clippy of supported compiler version in clippy.toml


---

diff --git a/.clippy.toml b/.clippy.toml
new file mode 100644
index 0000000..11d46a7
--- /dev/null
+++ b/.clippy.toml
@@ -0,0 +1 @@
+msrv = "1.48.0"

From 6064592053e89e980e9d309614f0375b846eb08c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:53:01 +0000
Subject: [PATCH 1870/2232] Recognize .hh and .hpp as header extensions in cxxbridge-cmd


---

diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 9072e60..e8b6ead 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -69,7 +69,11 @@ fn try_main() -> Result<()> {
     for output in opt.outputs {
         let kind = if opt.input.is_none() {
             Kind::Header
-        } else if opt.header || output.ends_with(".h") {
+        } else if opt.header
+            || output.ends_with(".h")
+            || output.ends_with(".hh")
+            || output.ends_with(".hpp")
+        {
             gen_header = true;
             Kind::GeneratedHeader
         } else {

From 8317c28fc8d509ac74e87c04c3cecbdab8ea5994 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 29 2020 23:53:01 +0000
Subject: [PATCH 1871/2232] Format with rustfmt 1.4.30-nightly


---

diff --git a/tests/test.rs b/tests/test.rs
index 950e059..e0815a6 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -27,11 +27,7 @@ macro_rules! check {
     ($run:expr) => {{
         CORRECT.with(|correct| correct.set(false));
         $run;
-        assert!(
-            CORRECT.with(Cell::get),
-            "{}",
-            stringify!($run),
-        );
+        assert!(CORRECT.with(Cell::get), "{}", stringify!($run));
     }};
 }
 

From b8d51afde9a3c30b4249d69d35a10ec586939f61 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 00:01:52 +0000
Subject: [PATCH 1872/2232] Merge pull request #614 from dtolnay/hpp


Recognize .hh and .hpp as header extensions in cxxbridge-cmd
---

diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index 9072e60..e8b6ead 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -69,7 +69,11 @@ fn try_main() -> Result<()> {
     for output in opt.outputs {
         let kind = if opt.input.is_none() {
             Kind::Header
-        } else if opt.header || output.ends_with(".h") {
+        } else if opt.header
+            || output.ends_with(".h")
+            || output.ends_with(".hh")
+            || output.ends_with(".hpp")
+        {
             gen_header = true;
             Kind::GeneratedHeader
         } else {

From a5b8c38dc42cd7fe8abfbfe7ef5bb66b0a800d25 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 00:04:24 +0000
Subject: [PATCH 1873/2232] Release 1.0.24


---

diff --git a/Cargo.toml b/Cargo.toml
index 3d50353..84c74c8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.23" # remember to update html_root_url
+version = "1.0.24" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.23", path = "macro" }
+cxxbridge-macro = { version = "=1.0.24", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.23", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.24", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.23", path = "gen/build" }
+cxx-build = { version = "=1.0.24", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 4e84fcb..16a1f1e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.23"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 2c9817f..0affec9 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.23"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index dd0b897..17388b2 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.23"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index bf883b2..01f3fad 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.23"
+version = "0.7.24"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index eac2a71..2e2131f 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.23"
+version = "1.0.24"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 43b7677..b6839b4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.23")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.24")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2e393f8..8b6d166 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.23"
+version = "1.0.24"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.23"
+version = "1.0.24"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.23"
+version = "0.7.24"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.23"
+version = "1.0.24"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.23"
+version = "1.0.24"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.23"
+version = "1.0.24"
 dependencies = [
  "cxx",
  "proc-macro2",

From 1eadd2639a73f41be8ae6f756ce5f88f4de5a4b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 00:42:08 +0000
Subject: [PATCH 1874/2232] Extract function for writing cxx_impl_annotations


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4e802da..b0af714 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -623,13 +623,17 @@ fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
     writeln!(out, "}}");
 }
 
+fn begin_function_definition(out: &mut OutFile) {
+    if let Some(annotation) = &out.opt.cxx_impl_annotations {
+        write!(out, "{} ", annotation);
+    }
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);
     out.begin_block(Block::ExternC);
-    if let Some(annotation) = &out.opt.cxx_impl_annotations {
-        write!(out, "{} ", annotation);
-    }
+    begin_function_definition(out);
     if efn.throws {
         out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen ");

From b478fcbf0f6ae2c9a95fd79f28b66c4fdca9b0bd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 00:48:02 +0000
Subject: [PATCH 1875/2232] Add C++ symbol visibility annotations for Rust functions and impls


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b0af714..7a910f1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -950,6 +950,9 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
+    if !out.header {
+        begin_function_definition(out);
+    }
     write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");
@@ -1487,6 +1490,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "{} *Box<{}>::allocation::alloc() noexcept {{",
@@ -1496,6 +1500,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
@@ -1505,6 +1510,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
     writeln!(out, "}}");
@@ -1517,16 +1523,19 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     out.include.cstddef = true;
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$drop(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "::std::size_t Vec<{}>::size() const noexcept {{",
@@ -1536,6 +1545,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "::std::size_t Vec<{}>::capacity() const noexcept {{",
@@ -1549,11 +1559,13 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Vec<{}>::reserve_total(::std::size_t cap) noexcept {{",
@@ -1567,6 +1579,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Vec<{}>::set_len(::std::size_t len) noexcept {{",

From cddf386b9953c155e0f52f2b9f6d8673bd71f8a4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 00:54:58 +0000
Subject: [PATCH 1876/2232] Merge pull request #615 from dtolnay/vis


Add C++ symbol visibility annotations for Rust functions and impls
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 4e802da..7a910f1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -623,13 +623,17 @@ fn write_opaque_type_layout<'a>(out: &mut OutFile<'a>, ety: &'a ExternType) {
     writeln!(out, "}}");
 }
 
+fn begin_function_definition(out: &mut OutFile) {
+    if let Some(annotation) = &out.opt.cxx_impl_annotations {
+        write!(out, "{} ", annotation);
+    }
+}
+
 fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     out.next_section();
     out.set_namespace(&efn.name.namespace);
     out.begin_block(Block::ExternC);
-    if let Some(annotation) = &out.opt.cxx_impl_annotations {
-        write!(out, "{} ", annotation);
-    }
+    begin_function_definition(out);
     if efn.throws {
         out.builtin.ptr_len = true;
         write!(out, "::rust::repr::PtrLen ");
@@ -946,6 +950,9 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
+    if !out.header {
+        begin_function_definition(out);
+    }
     write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");
@@ -1483,6 +1490,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     let instance = ident.to_symbol();
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "{} *Box<{}>::allocation::alloc() noexcept {{",
@@ -1492,6 +1500,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Box<{}>::allocation::dealloc({} *ptr) noexcept {{",
@@ -1501,6 +1510,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "void Box<{}>::drop() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$box${}$drop(this);", instance);
     writeln!(out, "}}");
@@ -1513,16 +1523,19 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     out.include.cstddef = true;
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "Vec<{}>::Vec() noexcept {{", inner);
     writeln!(out, "  cxxbridge1$rust_vec${}$new(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "void Vec<{}>::drop() noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$drop(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "::std::size_t Vec<{}>::size() const noexcept {{",
@@ -1532,6 +1545,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "::std::size_t Vec<{}>::capacity() const noexcept {{",
@@ -1545,11 +1559,13 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(out, "const {} *Vec<{0}>::data() const noexcept {{", inner);
     writeln!(out, "  return cxxbridge1$rust_vec${}$data(this);", instance);
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Vec<{}>::reserve_total(::std::size_t cap) noexcept {{",
@@ -1563,6 +1579,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 
     writeln!(out, "template <>");
+    begin_function_definition(out);
     writeln!(
         out,
         "void Vec<{}>::set_len(::std::size_t len) noexcept {{",

From d61437042ddbae64133ecf6311cfb842de37e7d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 07:48:09 +0000
Subject: [PATCH 1877/2232] Ignore visibility on extern type alias like on other items


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index c90125a..009c3df 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -16,7 +16,7 @@ use syn::{
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
     Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
-    Variant as RustVariant,
+    Variant as RustVariant, Visibility,
 };
 
 pub mod kw {
@@ -576,6 +576,7 @@ fn parse_extern_verbatim(
 ) -> Result<Api> {
     |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
+        input.parse::<Visibility>()?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
             None => {

From 4486f7261e43afc155016e8fec12467858ef2e12 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 08:01:26 +0000
Subject: [PATCH 1878/2232] Preserve doc comments on enum variants


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7a910f1..fc6801c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -357,6 +357,9 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
+        for line in variant.doc.to_string().lines() {
+            writeln!(out, "  //{}", line);
+        }
         writeln!(out, "  {} = {},", variant.name.cxx, variant.discriminant);
     }
     writeln!(out, "}};");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 79d678b..e6773b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -280,9 +280,11 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
+        let doc = &variant.doc;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
+            #doc
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 009afee..0fc7a9d 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -167,6 +167,7 @@ pub struct Receiver {
 }
 
 pub struct Variant {
+    pub doc: Doc,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 009c3df..ab17be4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -199,12 +199,14 @@ fn parse_variant(
     variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
+    let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
     attrs::parse(
         cx,
         &variant.attrs,
         attrs::Parser {
+            doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
             ..Default::default()
@@ -233,6 +235,7 @@ fn parse_variant(
     let expr = variant.discriminant.map(|(_, expr)| expr);
 
     Ok(Variant {
+        doc,
         name,
         discriminant,
         expr,

From f90cc999defca0a8cfab7b6e774046acfb496bbb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 08:08:35 +0000
Subject: [PATCH 1879/2232] Merge pull request #616 from dtolnay/doc


Preserve doc comments on enum variants
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7a910f1..fc6801c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -357,6 +357,9 @@ fn write_enum<'a>(out: &mut OutFile<'a>, enm: &'a Enum) {
     write_atom(out, enm.repr);
     writeln!(out, " {{");
     for variant in &enm.variants {
+        for line in variant.doc.to_string().lines() {
+            writeln!(out, "  //{}", line);
+        }
         writeln!(out, "  {} = {},", variant.name.cxx, variant.discriminant);
     }
     writeln!(out, "}};");
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 79d678b..e6773b5 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -280,9 +280,11 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
+        let doc = &variant.doc;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
+            #doc
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 009afee..0fc7a9d 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -167,6 +167,7 @@ pub struct Receiver {
 }
 
 pub struct Variant {
+    pub doc: Doc,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 009c3df..ab17be4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -199,12 +199,14 @@ fn parse_variant(
     variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
+    let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
     attrs::parse(
         cx,
         &variant.attrs,
         attrs::Parser {
+            doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
             rust_name: Some(&mut rust_name),
             ..Default::default()
@@ -233,6 +235,7 @@ fn parse_variant(
     let expr = variant.discriminant.map(|(_, expr)| expr);
 
     Ok(Variant {
+        doc,
         name,
         discriminant,
         expr,

From 593e04518d25598315ef4536e58a4df8b781cc9b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 08:18:49 +0000
Subject: [PATCH 1880/2232] Add ui test of missing_docs lints inside bridge


---

diff --git a/tests/ui/deny_missing_docs.rs b/tests/ui/deny_missing_docs.rs
new file mode 100644
index 0000000..ee68ef1
--- /dev/null
+++ b/tests/ui/deny_missing_docs.rs
@@ -0,0 +1,89 @@
+// TODO: More work is needed so that the missing_docs lints produced by rustc
+// are properly positioned inside of the bridge.
+
+//! ...
+
+#![deny(missing_docs)]
+
+/// ...
+#[cxx::bridge]
+pub mod ffi {
+    pub struct UndocumentedStruct {
+        pub undocumented_field: u8,
+    }
+
+    /// ...
+    pub struct DocumentedStruct {
+        /// ...
+        pub documented_field: u8,
+    }
+
+    pub enum UndocumentedEnum {
+        UndocumentedVariant = 0,
+    }
+
+    /// ...
+    pub enum DocumentedEnum {
+        /// ...
+        DocumentedVariant = 0,
+    }
+
+    extern "Rust" {
+        pub type UndocumentedRustType;
+
+        /// ...
+        pub type DocumentedRustType;
+
+        pub fn undocumented_rust_fn() -> u8;
+
+        /// ...
+        pub fn documented_rust_fn() -> u8;
+    }
+
+    unsafe extern "C++" {
+        pub type UndocumentedForeignType;
+
+        /// ...
+        pub type DocumentedForeignType;
+
+        pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias;
+
+        /// ...
+        pub type DocumentedTypeAlias = crate::bindgen::DocumentedTypeAlias;
+
+        pub fn undocumented_foreign_fn() -> u8;
+
+        /// ...
+        pub fn documented_foreign_fn() -> u8;
+    }
+}
+
+struct UndocumentedRustType;
+struct DocumentedRustType;
+
+mod bindgen {
+    use cxx::{type_id, ExternType};
+
+    pub struct UndocumentedTypeAlias;
+    pub struct DocumentedTypeAlias;
+
+    unsafe impl ExternType for UndocumentedTypeAlias {
+        type Id = type_id!("UndocumentedTypeAlias");
+        type Kind = cxx::kind::Opaque;
+    }
+
+    unsafe impl ExternType for DocumentedTypeAlias {
+        type Id = type_id!("DocumentedTypeAlias");
+        type Kind = cxx::kind::Opaque;
+    }
+}
+
+fn undocumented_rust_fn() -> u8 {
+    0
+}
+
+fn documented_rust_fn() -> u8 {
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
new file mode 100644
index 0000000..fcf11a5
--- /dev/null
+++ b/tests/ui/deny_missing_docs.stderr
@@ -0,0 +1,64 @@
+error: missing documentation for a struct
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+note: the lint level is defined here
+ --> $DIR/deny_missing_docs.rs:6:9
+  |
+6 | #![deny(missing_docs)]
+  |         ^^^^^^^^^^^^
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:12:13
+   |
+12 |         pub undocumented_field: u8,
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:18:13
+   |
+18 |         pub documented_field: u8,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a struct field
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for an associated constant
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a type alias
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a function
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From cc5b02e4eb8440a8aec27dca76081caf38cee647 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 08:29:44 +0000
Subject: [PATCH 1881/2232] Merge pull request #617 from dtolnay/missing_docs


Add ui test of missing_docs lints inside bridge
---

diff --git a/tests/ui/deny_missing_docs.rs b/tests/ui/deny_missing_docs.rs
new file mode 100644
index 0000000..ee68ef1
--- /dev/null
+++ b/tests/ui/deny_missing_docs.rs
@@ -0,0 +1,89 @@
+// TODO: More work is needed so that the missing_docs lints produced by rustc
+// are properly positioned inside of the bridge.
+
+//! ...
+
+#![deny(missing_docs)]
+
+/// ...
+#[cxx::bridge]
+pub mod ffi {
+    pub struct UndocumentedStruct {
+        pub undocumented_field: u8,
+    }
+
+    /// ...
+    pub struct DocumentedStruct {
+        /// ...
+        pub documented_field: u8,
+    }
+
+    pub enum UndocumentedEnum {
+        UndocumentedVariant = 0,
+    }
+
+    /// ...
+    pub enum DocumentedEnum {
+        /// ...
+        DocumentedVariant = 0,
+    }
+
+    extern "Rust" {
+        pub type UndocumentedRustType;
+
+        /// ...
+        pub type DocumentedRustType;
+
+        pub fn undocumented_rust_fn() -> u8;
+
+        /// ...
+        pub fn documented_rust_fn() -> u8;
+    }
+
+    unsafe extern "C++" {
+        pub type UndocumentedForeignType;
+
+        /// ...
+        pub type DocumentedForeignType;
+
+        pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias;
+
+        /// ...
+        pub type DocumentedTypeAlias = crate::bindgen::DocumentedTypeAlias;
+
+        pub fn undocumented_foreign_fn() -> u8;
+
+        /// ...
+        pub fn documented_foreign_fn() -> u8;
+    }
+}
+
+struct UndocumentedRustType;
+struct DocumentedRustType;
+
+mod bindgen {
+    use cxx::{type_id, ExternType};
+
+    pub struct UndocumentedTypeAlias;
+    pub struct DocumentedTypeAlias;
+
+    unsafe impl ExternType for UndocumentedTypeAlias {
+        type Id = type_id!("UndocumentedTypeAlias");
+        type Kind = cxx::kind::Opaque;
+    }
+
+    unsafe impl ExternType for DocumentedTypeAlias {
+        type Id = type_id!("DocumentedTypeAlias");
+        type Kind = cxx::kind::Opaque;
+    }
+}
+
+fn undocumented_rust_fn() -> u8 {
+    0
+}
+
+fn documented_rust_fn() -> u8 {
+    0
+}
+
+fn main() {}
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
new file mode 100644
index 0000000..fcf11a5
--- /dev/null
+++ b/tests/ui/deny_missing_docs.stderr
@@ -0,0 +1,64 @@
+error: missing documentation for a struct
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+note: the lint level is defined here
+ --> $DIR/deny_missing_docs.rs:6:9
+  |
+6 | #![deny(missing_docs)]
+  |         ^^^^^^^^^^^^
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:12:13
+   |
+12 |         pub undocumented_field: u8,
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:18:13
+   |
+18 |         pub documented_field: u8,
+   |             ^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a struct field
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for an associated constant
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a type alias
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a function
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 232a0e36302ebb07aa442cda46ea3c18b497b0b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:06:41 +0000
Subject: [PATCH 1882/2232] Exclude enum's repr field from missing_docs


This is a synthetic field that isn't visible in the FFI module's source
code.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index e6773b5..c063cf3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -296,6 +296,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         #derives
         #[repr(transparent)]
         pub struct #ident {
+            #[allow(missing_docs)]
             pub repr: #repr,
         }
 
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index fcf11a5..c9cb8c9 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -31,14 +31,6 @@ error: missing documentation for a struct
   |
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: missing documentation for a struct field
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error: missing documentation for an associated constant
  --> $DIR/deny_missing_docs.rs:9:1
   |

From 89902443e84e405c01ecbd16b8923e758f9c41dd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:17:58 +0000
Subject: [PATCH 1883/2232] Preserve visibility token's span on struct field


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c063cf3..1944642 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -157,7 +157,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let fields = strct.fields.iter().map(|field| {
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
-        let vis = Token![pub](field.ident.span());
+        let vis = field.visibility;
         quote!(#vis #field)
     });
     let mut derives = None;
diff --git a/syntax/impls.rs b/syntax/impls.rs
index d70e7cc..c7e1a2c 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type,
+    Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
@@ -292,6 +292,36 @@ impl Hash for Signature {
     }
 }
 
+impl Eq for Var {}
+
+impl PartialEq for Var {
+    fn eq(&self, other: &Var) -> bool {
+        let Var {
+            visibility: _,
+            ident,
+            ty,
+        } = self;
+        let Var {
+            visibility: _,
+            ident: ident2,
+            ty: ty2,
+        } = other;
+        ident == ident2 && ty == ty2
+    }
+}
+
+impl Hash for Var {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Var {
+            visibility: _,
+            ident,
+            ty,
+        } = self;
+        ident.hash(state);
+        ty.hash(state);
+    }
+}
+
 impl Eq for Receiver {}
 
 impl PartialEq for Receiver {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 0fc7a9d..8247d19 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -148,8 +148,8 @@ pub struct Signature {
     pub throws_tokens: Option<(kw::Result, Token![<], Token![>])>,
 }
 
-#[derive(Eq, PartialEq, Hash)]
 pub struct Var {
+    pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index ab17be4..a178421 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -104,7 +104,17 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
                 continue;
             }
         };
-        fields.push(Var { ident, ty });
+        let visibility = Token![pub](match field.vis {
+            Visibility::Public(vis) => vis.pub_token.span,
+            Visibility::Crate(vis) => vis.crate_token.span,
+            Visibility::Restricted(vis) => vis.pub_token.span,
+            Visibility::Inherited => ident.span(),
+        });
+        fields.push(Var {
+            visibility,
+            ident,
+            ty,
+        });
     }
 
     let struct_token = item.struct_token;
@@ -510,7 +520,12 @@ fn parse_extern_fn(
                 };
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
-                    args.push_value(Var { ident, ty });
+                    let visibility = Token![pub](ident.span());
+                    args.push_value(Var {
+                        visibility,
+                        ident,
+                        ty,
+                    });
                     if let Some(comma) = comma {
                         args.push_punct(*comma);
                     }
@@ -1076,7 +1091,12 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("arg{}", i),
             };
-            Ok(Var { ident, ty })
+            let visibility = Token![pub](ident.span());
+            Ok(Var {
+                visibility,
+                ident,
+                ty,
+            })
         })
         .collect::<Result<_>>()?;
 
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index c9cb8c9..d0da255 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -12,16 +12,16 @@ note: the lint level is defined here
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:12:13
+  --> $DIR/deny_missing_docs.rs:12:9
    |
 12 |         pub undocumented_field: u8,
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:18:13
+  --> $DIR/deny_missing_docs.rs:18:9
    |
 18 |         pub documented_field: u8,
-   |             ^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
  --> $DIR/deny_missing_docs.rs:9:1

From 64343af04d3fb5a6c5f745b5871e67d1d23d3dfd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:34:09 +0000
Subject: [PATCH 1884/2232] Fix span placement on shared structs


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1944642..8ba765a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -163,13 +163,20 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
 
+    let span = ident.span();
+    let visibility = strct.visibility;
+    let struct_token = strct.struct_token;
+    let struct_def = quote_spanned! {span=>
+        #visibility #struct_token #ident {
+            #(#fields,)*
+        }
+    };
+
     quote! {
         #doc
         #derives
         #[repr(C)]
-        pub struct #ident {
-            #(#fields,)*
-        }
+        #struct_def
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8247d19..f6bdf72 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -84,6 +84,7 @@ pub struct ExternType {
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a178421..4bfabcd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -117,6 +117,12 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         });
     }
 
+    let visibility = Token![pub](match item.vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => item.ident.span(),
+    });
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let brace_token = named_fields.brace_token;
@@ -124,6 +130,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     Ok(Api::Struct(Struct {
         doc,
         derives,
+        visibility,
         struct_token,
         name,
         brace_token,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index d0da255..96dec46 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -1,15 +1,14 @@
 error: missing documentation for a struct
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
+  --> $DIR/deny_missing_docs.rs:11:5
+   |
+11 |     pub struct UndocumentedStruct {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
 note: the lint level is defined here
- --> $DIR/deny_missing_docs.rs:6:9
-  |
-6 | #![deny(missing_docs)]
-  |         ^^^^^^^^^^^^
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:6:9
+   |
+6  | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
 
 error: missing documentation for a struct field
   --> $DIR/deny_missing_docs.rs:12:9

From 0bdabfdc98d73df7d26c94efcc3e61b62e111fb7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:46:35 +0000
Subject: [PATCH 1885/2232] Merge pull request #618 from dtolnay/span


Fix span placement on shared structs
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1944642..8ba765a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -163,13 +163,20 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
 
+    let span = ident.span();
+    let visibility = strct.visibility;
+    let struct_token = strct.struct_token;
+    let struct_def = quote_spanned! {span=>
+        #visibility #struct_token #ident {
+            #(#fields,)*
+        }
+    };
+
     quote! {
         #doc
         #derives
         #[repr(C)]
-        pub struct #ident {
-            #(#fields,)*
-        }
+        #struct_def
 
         unsafe impl ::cxx::ExternType for #ident {
             type Id = #type_id;
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 8247d19..f6bdf72 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -84,6 +84,7 @@ pub struct ExternType {
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a178421..4bfabcd 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -117,6 +117,12 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         });
     }
 
+    let visibility = Token![pub](match item.vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => item.ident.span(),
+    });
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let brace_token = named_fields.brace_token;
@@ -124,6 +130,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     Ok(Api::Struct(Struct {
         doc,
         derives,
+        visibility,
         struct_token,
         name,
         brace_token,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index d0da255..96dec46 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -1,15 +1,14 @@
 error: missing documentation for a struct
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
+  --> $DIR/deny_missing_docs.rs:11:5
+   |
+11 |     pub struct UndocumentedStruct {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
 note: the lint level is defined here
- --> $DIR/deny_missing_docs.rs:6:9
-  |
-6 | #![deny(missing_docs)]
-  |         ^^^^^^^^^^^^
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:6:9
+   |
+6  | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
 
 error: missing documentation for a struct field
   --> $DIR/deny_missing_docs.rs:12:9

From b4a05c3621964bb2d5d8e9bf9ccb651aebf4f7ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:46:47 +0000
Subject: [PATCH 1886/2232] Preserve doc attributes on struct fields


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8ba765a..3b03115 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -155,10 +155,11 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let doc = &strct.doc;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
+        let doc = &field.doc;
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
         let vis = field.visibility;
-        quote!(#vis #field)
+        quote!(#doc #vis #field)
     });
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index c7e1a2c..624a64d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -297,11 +297,13 @@ impl Eq for Var {}
 impl PartialEq for Var {
     fn eq(&self, other: &Var) -> bool {
         let Var {
+            doc: _,
             visibility: _,
             ident,
             ty,
         } = self;
         let Var {
+            doc: _,
             visibility: _,
             ident: ident2,
             ty: ty2,
@@ -313,6 +315,7 @@ impl PartialEq for Var {
 impl Hash for Var {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Var {
+            doc: _,
             visibility: _,
             ident,
             ty,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f6bdf72..092f403 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -150,6 +150,7 @@ pub struct Signature {
 }
 
 pub struct Var {
+    pub doc: Doc,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 4bfabcd..3d970d8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -97,6 +97,15 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     let mut fields = Vec::new();
     for field in named_fields.named {
         let ident = field.ident.unwrap();
+        let mut doc = Doc::new();
+        attrs::parse(
+            cx,
+            &field.attrs,
+            attrs::Parser {
+                doc: Some(&mut doc),
+                ..Default::default()
+            },
+        );
         let ty = match parse_type(&field.ty) {
             Ok(ty) => ty,
             Err(err) => {
@@ -111,6 +120,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
             Visibility::Inherited => ident.span(),
         });
         fields.push(Var {
+            doc,
             visibility,
             ident,
             ty,
@@ -527,8 +537,10 @@ fn parse_extern_fn(
                 };
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
+                    let doc = Doc::new();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
+                        doc,
                         visibility,
                         ident,
                         ty,
@@ -1098,8 +1110,10 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("arg{}", i),
             };
+            let doc = Doc::new();
             let visibility = Token![pub](ident.span());
             Ok(Var {
+                doc,
                 visibility,
                 ident,
                 ty,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index 96dec46..f31be34 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -16,12 +16,6 @@ error: missing documentation for a struct field
 12 |         pub undocumented_field: u8,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:18:9
-   |
-18 |         pub documented_field: u8,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: missing documentation for a struct
  --> $DIR/deny_missing_docs.rs:9:1
   |

From a4615f1b5eb95c524ec97a670df0bde1f49802aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 30 2020 23:55:04 +0000
Subject: [PATCH 1887/2232] Merge pull request #619 from dtolnay/fielddoc


Preserve doc attributes on struct fields
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8ba765a..3b03115 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -155,10 +155,11 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let doc = &strct.doc;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
+        let doc = &field.doc;
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
         let vis = field.visibility;
-        quote!(#vis #field)
+        quote!(#doc #vis #field)
     });
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index c7e1a2c..624a64d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -297,11 +297,13 @@ impl Eq for Var {}
 impl PartialEq for Var {
     fn eq(&self, other: &Var) -> bool {
         let Var {
+            doc: _,
             visibility: _,
             ident,
             ty,
         } = self;
         let Var {
+            doc: _,
             visibility: _,
             ident: ident2,
             ty: ty2,
@@ -313,6 +315,7 @@ impl PartialEq for Var {
 impl Hash for Var {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Var {
+            doc: _,
             visibility: _,
             ident,
             ty,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index f6bdf72..092f403 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -150,6 +150,7 @@ pub struct Signature {
 }
 
 pub struct Var {
+    pub doc: Doc,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 4bfabcd..3d970d8 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -97,6 +97,15 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     let mut fields = Vec::new();
     for field in named_fields.named {
         let ident = field.ident.unwrap();
+        let mut doc = Doc::new();
+        attrs::parse(
+            cx,
+            &field.attrs,
+            attrs::Parser {
+                doc: Some(&mut doc),
+                ..Default::default()
+            },
+        );
         let ty = match parse_type(&field.ty) {
             Ok(ty) => ty,
             Err(err) => {
@@ -111,6 +120,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
             Visibility::Inherited => ident.span(),
         });
         fields.push(Var {
+            doc,
             visibility,
             ident,
             ty,
@@ -527,8 +537,10 @@ fn parse_extern_fn(
                 };
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
+                    let doc = Doc::new();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
+                        doc,
                         visibility,
                         ident,
                         ty,
@@ -1098,8 +1110,10 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 Some(ident) => ident.0.clone(),
                 None => format_ident!("arg{}", i),
             };
+            let doc = Doc::new();
             let visibility = Token![pub](ident.span());
             Ok(Var {
+                doc,
                 visibility,
                 ident,
                 ty,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index 96dec46..f31be34 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -16,12 +16,6 @@ error: missing documentation for a struct field
 12 |         pub undocumented_field: u8,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:18:9
-   |
-18 |         pub documented_field: u8,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: missing documentation for a struct
  --> $DIR/deny_missing_docs.rs:9:1
   |

From 15a1fc110e188657e333e9ce0c9c22ea1e951aaa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:13:59 +0000
Subject: [PATCH 1888/2232] Consume attributes in attr parser


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 2bc03ea..8740d3d 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -39,7 +39,7 @@ pub struct Parser<'a> {
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
+pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) {
     for attr in attrs {
         if attr.path.is_ident("doc") {
             match parse_doc_attribute.parse2(attr.tokens.clone()) {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d970d8..1ea4db4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -9,6 +9,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
+use std::mem;
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
@@ -55,7 +56,8 @@ pub fn parse_items(
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
+    let attrs = mem::take(&mut item.attrs);
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
@@ -63,7 +65,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &item.attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -100,7 +102,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         let mut doc = Doc::new();
         attrs::parse(
             cx,
-            &field.attrs,
+            field.attrs,
             attrs::Parser {
                 doc: Some(&mut doc),
                 ..Default::default()
@@ -157,7 +159,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &item.attrs,
+        item.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -223,15 +225,16 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
 
 fn parse_variant(
     cx: &mut Errors,
-    variant: RustVariant,
+    mut variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
+    let attrs = mem::take(&mut variant.attrs);
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &variant.attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
@@ -298,7 +301,7 @@ fn parse_foreign_mod(
     let mut namespace = namespace.clone();
     attrs::parse(
         cx,
-        &foreign_mod.attrs,
+        foreign_mod.attrs,
         attrs::Parser {
             namespace: Some(&mut namespace),
             ..Default::default()
@@ -306,7 +309,7 @@ fn parse_foreign_mod(
     );
 
     let mut items = Vec::new();
-    for foreign in &foreign_mod.items {
+    for foreign in foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
                 let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
@@ -390,7 +393,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
 
 fn parse_extern_type(
     cx: &mut Errors,
-    foreign_type: &ForeignItemType,
+    foreign_type: ForeignItemType,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
@@ -402,7 +405,7 @@ fn parse_extern_type(
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &foreign_type.attrs,
+        foreign_type.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -443,18 +446,19 @@ fn parse_extern_type(
 
 fn parse_extern_fn(
     cx: &mut Errors,
-    foreign_fn: &ForeignItemFn,
+    mut foreign_fn: ForeignItemFn,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
+    let attrs = mem::take(&mut foreign_fn.attrs);
     let mut doc = Doc::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &foreign_fn.attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             namespace: Some(&mut namespace),
@@ -606,7 +610,7 @@ fn parse_extern_fn(
 
 fn parse_extern_verbatim(
     cx: &mut Errors,
-    tokens: &TokenStream,
+    tokens: TokenStream,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
@@ -675,7 +679,7 @@ fn parse_extern_verbatim(
             Err(lookahead.error())
         }
     }
-    .parse2(tokens.clone())
+    .parse2(tokens)
 }
 
 fn parse_type_alias(
@@ -699,7 +703,7 @@ fn parse_type_alias(
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -781,7 +785,7 @@ fn parse_extern_type_bounded(
     let mut rust_name = None;
     attrs::parse(
         cx,
-        &attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),

From d5ee99c8bd0f15eb6c4720f82cb6cc4d20dbf8fd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:14:52 +0000
Subject: [PATCH 1889/2232] Add test of `allow` attribute inside bridge


---

diff --git a/tests/ui/deny_missing_docs.rs b/tests/ui/deny_missing_docs.rs
index ee68ef1..037894b 100644
--- a/tests/ui/deny_missing_docs.rs
+++ b/tests/ui/deny_missing_docs.rs
@@ -56,6 +56,11 @@ pub mod ffi {
         /// ...
         pub fn documented_foreign_fn() -> u8;
     }
+
+    #[allow(missing_docs)]
+    pub struct SuppressUndocumentedStruct {
+        pub undocumented_field: u8,
+    }
 }
 
 struct UndocumentedRustType;
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index f31be34..40d9a07 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -1,49 +1,5 @@
-error: missing documentation for a struct
-  --> $DIR/deny_missing_docs.rs:11:5
+error: unsupported attribute
+  --> $DIR/deny_missing_docs.rs:60:5
    |
-11 |     pub struct UndocumentedStruct {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/deny_missing_docs.rs:6:9
-   |
-6  | #![deny(missing_docs)]
-   |         ^^^^^^^^^^^^
-
-error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:12:9
-   |
-12 |         pub undocumented_field: u8,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: missing documentation for a struct
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: missing documentation for an associated constant
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: missing documentation for a type alias
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: missing documentation for a function
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+60 |     #[allow(missing_docs)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^

From 20d980be788a833dc7e374050a24a2a4b9aeda0a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:44:05 +0000
Subject: [PATCH 1890/2232] Skip over rust diagnostic attributes


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 8740d3d..9ad3d51 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -101,6 +101,13 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                 }
                 Err(err) => return cx.push(err),
             }
+        } else if attr.path.is_ident("allow")
+            || attr.path.is_ident("warn")
+            || attr.path.is_ident("deny")
+            || attr.path.is_ident("forbid")
+        {
+            // https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes
+            continue;
         }
         return cx.error(attr, "unsupported attribute");
     }
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index 40d9a07..a5390b1 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -1,5 +1,61 @@
-error: unsupported attribute
-  --> $DIR/deny_missing_docs.rs:60:5
+error: missing documentation for a struct
+  --> $DIR/deny_missing_docs.rs:11:5
    |
-60 |     #[allow(missing_docs)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+11 |     pub struct UndocumentedStruct {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny_missing_docs.rs:6:9
+   |
+6  | #![deny(missing_docs)]
+   |         ^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:12:9
+   |
+12 |         pub undocumented_field: u8,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for an associated constant
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a type alias
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a function
+ --> $DIR/deny_missing_docs.rs:9:1
+  |
+9 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: missing documentation for a struct
+  --> $DIR/deny_missing_docs.rs:61:5
+   |
+61 |     pub struct SuppressUndocumentedStruct {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/deny_missing_docs.rs:62:9
+   |
+62 |         pub undocumented_field: u8,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^

From 067638ea15b8a13e2a3ede69a2c686c330581aee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:50:05 +0000
Subject: [PATCH 1891/2232] Store passthrough attributes for diagnostic lint levels


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 66d854e..bfe370c 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -51,6 +51,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
 #[cfg(test)]
 mod tests {
     use super::NamespaceEntries;
+    use crate::syntax::attrs::OtherAttrs;
     use crate::syntax::namespace::Namespace;
     use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
@@ -131,6 +132,7 @@ mod tests {
             lang: Lang::Rust,
             doc: Doc::new(),
             derives: Vec::new(),
+            attrs: OtherAttrs::none(),
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 9ad3d51..7f50dcb 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -39,7 +39,8 @@ pub struct Parser<'a> {
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) {
+pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Vec<Attribute> {
+    let mut passthrough_attrs = Vec::new();
     for attr in attrs {
         if attr.path.is_ident("doc") {
             match parse_doc_attribute.parse2(attr.tokens.clone()) {
@@ -49,7 +50,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("derive") {
             match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
@@ -59,7 +63,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("repr") {
             match attr.parse_args_with(parse_repr_attribute) {
@@ -69,7 +76,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("namespace") {
             match parse_namespace_attribute.parse2(attr.tokens.clone()) {
@@ -79,7 +89,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("cxx_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -89,7 +102,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("rust_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -99,7 +115,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("allow")
             || attr.path.is_ident("warn")
@@ -107,10 +126,13 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
             || attr.path.is_ident("forbid")
         {
             // https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes
+            passthrough_attrs.push(attr);
             continue;
         }
-        return cx.error(attr, "unsupported attribute");
+        cx.error(attr, "unsupported attribute");
+        break;
     }
+    passthrough_attrs
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 624a64d..4504fe6 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -298,12 +298,14 @@ impl PartialEq for Var {
     fn eq(&self, other: &Var) -> bool {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
         } = self;
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident: ident2,
             ty: ty2,
@@ -316,6 +318,7 @@ impl Hash for Var {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 092f403..c478d3c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -1,7 +1,7 @@
 // Functionality that is shared between the cxxbridge macro and the cmd.
 
 pub mod atom;
-mod attrs;
+pub mod attrs;
 pub mod check;
 pub mod derive;
 mod discriminant;
@@ -32,7 +32,7 @@ use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
+use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::{Derive, Trait};
@@ -72,6 +72,7 @@ pub struct ExternType {
     pub lang: Lang,
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -84,6 +85,7 @@ pub struct ExternType {
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
@@ -94,6 +96,7 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
@@ -106,6 +109,7 @@ pub struct Enum {
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
@@ -115,6 +119,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: Vec<Attribute>,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -151,6 +156,7 @@ pub struct Signature {
 
 pub struct Var {
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
@@ -170,6 +176,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub doc: Doc,
+    pub attrs: Vec<Attribute>,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 1ea4db4..87f43b2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -57,15 +57,14 @@ pub fn parse_items(
 }
 
 fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
-    let attrs = mem::take(&mut item.attrs);
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut item.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -100,7 +99,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     for field in named_fields.named {
         let ident = field.ident.unwrap();
         let mut doc = Doc::new();
-        attrs::parse(
+        let attrs = attrs::parse(
             cx,
             field.attrs,
             attrs::Parser {
@@ -123,6 +122,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
         fields.push(Var {
             doc,
+            attrs,
             visibility,
             ident,
             ty,
@@ -142,6 +142,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     Ok(Api::Struct(Struct {
         doc,
         derives,
+        attrs,
         visibility,
         struct_token,
         name,
@@ -157,7 +158,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         item.attrs,
         attrs::Parser {
@@ -213,6 +214,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     Ok(Api::Enum(Enum {
         doc,
         derives,
+        attrs,
         enum_token,
         name,
         brace_token,
@@ -228,13 +230,12 @@ fn parse_variant(
     mut variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
-    let attrs = mem::take(&mut variant.attrs);
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut variant.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
@@ -266,6 +267,7 @@ fn parse_variant(
 
     Ok(Variant {
         doc,
+        attrs,
         name,
         discriminant,
         expr,
@@ -403,7 +405,7 @@ fn parse_extern_type(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         foreign_type.attrs,
         attrs::Parser {
@@ -434,6 +436,7 @@ fn parse_extern_type(
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -451,14 +454,13 @@ fn parse_extern_fn(
     trusted: bool,
     namespace: &Namespace,
 ) -> Result<Api> {
-    let attrs = mem::take(&mut foreign_fn.attrs);
     let mut doc = Doc::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        attrs,
+        mem::take(&mut foreign_fn.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             namespace: Some(&mut namespace),
@@ -542,9 +544,11 @@ fn parse_extern_fn(
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     let doc = Doc::new();
+                    let attrs = Vec::new();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
                         doc,
+                        attrs,
                         visibility,
                         ident,
                         ty,
@@ -591,6 +595,7 @@ fn parse_extern_fn(
     }(ExternFn {
         lang,
         doc,
+        attrs,
         name,
         sig: Signature {
             unsafety,
@@ -701,7 +706,7 @@ fn parse_type_alias(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         attrs,
         attrs::Parser {
@@ -725,6 +730,7 @@ fn parse_type_alias(
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -783,7 +789,7 @@ fn parse_extern_type_bounded(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
         attrs,
         attrs::Parser {
@@ -805,6 +811,7 @@ fn parse_extern_type_bounded(
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -1115,9 +1122,11 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 None => format_ident!("arg{}", i),
             };
             let doc = Doc::new();
+            let attrs = Vec::new();
             let visibility = Token![pub](ident.span());
             Ok(Var {
                 doc,
+                attrs,
                 visibility,
                 ident,
                 ty,

From cba3d44638641856beb9d8f38fcd73c8fdb6548a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:50:05 +0000
Subject: [PATCH 1892/2232] Add wrapper type for tokenizing passthrough attrs


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 7f50dcb..0d00f22 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -2,7 +2,8 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
-use proc_macro2::Ident;
+use proc_macro2::{Ident, TokenStream};
+use quote::ToTokens;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
@@ -39,7 +40,7 @@ pub struct Parser<'a> {
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Vec<Attribute> {
+pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> OtherAttrs {
     let mut passthrough_attrs = Vec::new();
     for attr in attrs {
         if attr.path.is_ident("doc") {
@@ -132,7 +133,7 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
         cx.error(attr, "unsupported attribute");
         break;
     }
-    passthrough_attrs
+    OtherAttrs(passthrough_attrs)
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
@@ -189,3 +190,19 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
         input.parse()
     }
 }
+
+pub struct OtherAttrs(Vec<Attribute>);
+
+impl OtherAttrs {
+    pub fn none() -> Self {
+        OtherAttrs(Vec::new())
+    }
+}
+
+impl ToTokens for OtherAttrs {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        for attr in &self.0 {
+            attr.to_tokens(tokens);
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index c478d3c..da21204 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -25,6 +25,7 @@ mod toposort;
 pub mod trivial;
 pub mod types;
 
+use self::attrs::OtherAttrs;
 use self::discriminant::Discriminant;
 use self::namespace::Namespace;
 use self::parse::kw;
@@ -32,7 +33,7 @@ use self::symbol::Symbol;
 use proc_macro2::{Ident, Span};
 use syn::punctuated::Punctuated;
 use syn::token::{Brace, Bracket, Paren};
-use syn::{Attribute, Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
+use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 
 pub use self::atom::Atom;
 pub use self::derive::{Derive, Trait};
@@ -72,7 +73,7 @@ pub struct ExternType {
     pub lang: Lang,
     pub doc: Doc,
     pub derives: Vec<Derive>,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -85,7 +86,7 @@ pub struct ExternType {
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
@@ -96,7 +97,7 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
@@ -109,7 +110,7 @@ pub struct Enum {
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
@@ -119,7 +120,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -156,7 +157,7 @@ pub struct Signature {
 
 pub struct Var {
     pub doc: Doc,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
@@ -176,7 +177,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub doc: Doc,
-    pub attrs: Vec<Attribute>,
+    pub attrs: OtherAttrs,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 87f43b2..5ce2cf3 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::attrs::OtherAttrs;
 use crate::syntax::discriminant::DiscriminantSet;
 use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
@@ -544,7 +545,7 @@ fn parse_extern_fn(
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     let doc = Doc::new();
-                    let attrs = Vec::new();
+                    let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
                         doc,
@@ -1122,7 +1123,7 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 None => format_ident!("arg{}", i),
             };
             let doc = Doc::new();
-            let attrs = Vec::new();
+            let attrs = OtherAttrs::none();
             let visibility = Token![pub](ident.span());
             Ok(Var {
                 doc,

From 2b0b6587e576c190aeff2a854b57f3b5b558e4f5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:50:05 +0000
Subject: [PATCH 1893/2232] Emit passthrough attrs into macro output


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3b03115..249afdc 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -153,13 +153,15 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 fn expand_struct(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let doc = &strct.doc;
+    let attrs = &strct.attrs;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         let doc = &field.doc;
+        let attrs = &field.attrs;
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
         let vis = field.visibility;
-        quote!(#doc #vis #field)
+        quote!(#doc #attrs #vis #field)
     });
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
@@ -175,6 +177,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #derives
         #[repr(C)]
         #struct_def
@@ -285,14 +288,17 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
+    let attrs = &enm.attrs;
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
         let doc = &variant.doc;
+        let attrs = &variant.attrs;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
             #doc
+            #attrs
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
@@ -301,6 +307,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #derives
         #[repr(transparent)]
         pub struct #ident {
@@ -325,6 +332,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
     let doc = &ety.doc;
+    let attrs = &ety.attrs;
     let generics = &ety.generics;
     let type_id = type_id(&ety.name);
 
@@ -335,6 +343,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #[repr(C)]
         pub struct #ident #generics {
             _private: ::cxx::private::Opaque,
@@ -423,6 +432,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
 
 fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
+    let attrs = &efn.attrs;
     let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
         let var = receiver.var;
@@ -600,6 +610,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let generics = &efn.generics;
     let function_shim = quote! {
         #doc
+        #attrs
         pub #unsafety fn #ident #generics(#(#all_args,)*) #ret {
             extern "C" {
                 #decl
@@ -977,11 +988,13 @@ fn expand_rust_function_shim_super(
 
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
+    let attrs = &alias.attrs;
     let ident = &alias.name.rust;
     let generics = &alias.generics;
     let ty = &alias.ty;
     quote! {
         #doc
+        #attrs
         pub type #ident #generics = #ty;
     }
 }
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index a5390b1..f31be34 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -47,15 +47,3 @@ error: missing documentation for a function
   | ^^^^^^^^^^^^^^
   |
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: missing documentation for a struct
-  --> $DIR/deny_missing_docs.rs:61:5
-   |
-61 |     pub struct SuppressUndocumentedStruct {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: missing documentation for a struct field
-  --> $DIR/deny_missing_docs.rs:62:9
-   |
-62 |         pub undocumented_field: u8,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^

From f08e94d2d68a606d6578ceee0cf931d156f022eb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:50:06 +0000
Subject: [PATCH 1894/2232] Update attrs::Parser intended usage comment


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 0d00f22..9a6be92 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -13,9 +13,9 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token};
 //     let mut cxx_name = None;
 //     let mut rust_name = None;
 //     /* ... */
-//     attrs::parse(
+//     let attrs = attrs::parse(
 //         cx,
-//         &item.attrs,
+//         item.attrs,
 //         attrs::Parser {
 //             doc: Some(&mut doc),
 //             cxx_name: Some(&mut cxx_name),

From 6cbfa7cf8cb14d86928bd3178cc2972cfc52674b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:56:19 +0000
Subject: [PATCH 1895/2232] Merge pull request #620 from dtolnay/allow


Propagate rust lint control attributes into macro output
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index 66d854e..bfe370c 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -51,6 +51,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
 #[cfg(test)]
 mod tests {
     use super::NamespaceEntries;
+    use crate::syntax::attrs::OtherAttrs;
     use crate::syntax::namespace::Namespace;
     use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
@@ -131,6 +132,7 @@ mod tests {
             lang: Lang::Rust,
             doc: Doc::new(),
             derives: Vec::new(),
+            attrs: OtherAttrs::none(),
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 3b03115..249afdc 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -153,13 +153,15 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
 fn expand_struct(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let doc = &strct.doc;
+    let attrs = &strct.attrs;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         let doc = &field.doc;
+        let attrs = &field.attrs;
         // This span on the pub makes "private type in public interface" errors
         // appear in the right place.
         let vis = field.visibility;
-        quote!(#doc #vis #field)
+        quote!(#doc #attrs #vis #field)
     });
     let mut derives = None;
     let derived_traits = derive::expand_struct(strct, &mut derives);
@@ -175,6 +177,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #derives
         #[repr(C)]
         #struct_def
@@ -285,14 +288,17 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
+    let attrs = &enm.attrs;
     let repr = enm.repr;
     let type_id = type_id(&enm.name);
     let variants = enm.variants.iter().map(|variant| {
         let doc = &variant.doc;
+        let attrs = &variant.attrs;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
         Some(quote! {
             #doc
+            #attrs
             pub const #variant_ident: Self = #ident { repr: #discriminant };
         })
     });
@@ -301,6 +307,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #derives
         #[repr(transparent)]
         pub struct #ident {
@@ -325,6 +332,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
 fn expand_cxx_type(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
     let doc = &ety.doc;
+    let attrs = &ety.attrs;
     let generics = &ety.generics;
     let type_id = type_id(&ety.name);
 
@@ -335,6 +343,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
 
     quote! {
         #doc
+        #attrs
         #[repr(C)]
         pub struct #ident #generics {
             _private: ::cxx::private::Opaque,
@@ -423,6 +432,7 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
 
 fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let doc = &efn.doc;
+    let attrs = &efn.attrs;
     let decl = expand_cxx_function_decl(efn, types);
     let receiver = efn.receiver.iter().map(|receiver| {
         let var = receiver.var;
@@ -600,6 +610,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let generics = &efn.generics;
     let function_shim = quote! {
         #doc
+        #attrs
         pub #unsafety fn #ident #generics(#(#all_args,)*) #ret {
             extern "C" {
                 #decl
@@ -977,11 +988,13 @@ fn expand_rust_function_shim_super(
 
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
+    let attrs = &alias.attrs;
     let ident = &alias.name.rust;
     let generics = &alias.generics;
     let ty = &alias.ty;
     quote! {
         #doc
+        #attrs
         pub type #ident #generics = #ty;
     }
 }
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 2bc03ea..9a6be92 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -2,7 +2,8 @@ use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
 use crate::syntax::{Derive, Doc};
-use proc_macro2::Ident;
+use proc_macro2::{Ident, TokenStream};
+use quote::ToTokens;
 use syn::parse::{ParseStream, Parser as _};
 use syn::{Attribute, Error, LitStr, Path, Result, Token};
 
@@ -12,9 +13,9 @@ use syn::{Attribute, Error, LitStr, Path, Result, Token};
 //     let mut cxx_name = None;
 //     let mut rust_name = None;
 //     /* ... */
-//     attrs::parse(
+//     let attrs = attrs::parse(
 //         cx,
-//         &item.attrs,
+//         item.attrs,
 //         attrs::Parser {
 //             doc: Some(&mut doc),
 //             cxx_name: Some(&mut cxx_name),
@@ -39,7 +40,8 @@ pub struct Parser<'a> {
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
+pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> OtherAttrs {
+    let mut passthrough_attrs = Vec::new();
     for attr in attrs {
         if attr.path.is_ident("doc") {
             match parse_doc_attribute.parse2(attr.tokens.clone()) {
@@ -49,7 +51,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("derive") {
             match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
@@ -59,7 +64,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("repr") {
             match attr.parse_args_with(parse_repr_attribute) {
@@ -69,7 +77,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("namespace") {
             match parse_namespace_attribute.parse2(attr.tokens.clone()) {
@@ -79,7 +90,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("cxx_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -89,7 +103,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
         } else if attr.path.is_ident("rust_name") {
             match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
@@ -99,11 +116,24 @@ pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
                         continue;
                     }
                 }
-                Err(err) => return cx.push(err),
+                Err(err) => {
+                    cx.push(err);
+                    break;
+                }
             }
+        } else if attr.path.is_ident("allow")
+            || attr.path.is_ident("warn")
+            || attr.path.is_ident("deny")
+            || attr.path.is_ident("forbid")
+        {
+            // https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes
+            passthrough_attrs.push(attr);
+            continue;
         }
-        return cx.error(attr, "unsupported attribute");
+        cx.error(attr, "unsupported attribute");
+        break;
     }
+    OtherAttrs(passthrough_attrs)
 }
 
 fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
@@ -160,3 +190,19 @@ fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
         input.parse()
     }
 }
+
+pub struct OtherAttrs(Vec<Attribute>);
+
+impl OtherAttrs {
+    pub fn none() -> Self {
+        OtherAttrs(Vec::new())
+    }
+}
+
+impl ToTokens for OtherAttrs {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        for attr in &self.0 {
+            attr.to_tokens(tokens);
+        }
+    }
+}
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 624a64d..4504fe6 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -298,12 +298,14 @@ impl PartialEq for Var {
     fn eq(&self, other: &Var) -> bool {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
         } = self;
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident: ident2,
             ty: ty2,
@@ -316,6 +318,7 @@ impl Hash for Var {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Var {
             doc: _,
+            attrs: _,
             visibility: _,
             ident,
             ty,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 092f403..da21204 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -1,7 +1,7 @@
 // Functionality that is shared between the cxxbridge macro and the cmd.
 
 pub mod atom;
-mod attrs;
+pub mod attrs;
 pub mod check;
 pub mod derive;
 mod discriminant;
@@ -25,6 +25,7 @@ mod toposort;
 pub mod trivial;
 pub mod types;
 
+use self::attrs::OtherAttrs;
 use self::discriminant::Discriminant;
 use self::namespace::Namespace;
 use self::parse::kw;
@@ -72,6 +73,7 @@ pub struct ExternType {
     pub lang: Lang,
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: OtherAttrs,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -84,6 +86,7 @@ pub struct ExternType {
 pub struct Struct {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: OtherAttrs,
     pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
@@ -94,6 +97,7 @@ pub struct Struct {
 pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: OtherAttrs,
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
@@ -106,6 +110,7 @@ pub struct Enum {
 pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
+    pub attrs: OtherAttrs,
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
@@ -115,6 +120,7 @@ pub struct ExternFn {
 pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
+    pub attrs: OtherAttrs,
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -151,6 +157,7 @@ pub struct Signature {
 
 pub struct Var {
     pub doc: Doc,
+    pub attrs: OtherAttrs,
     pub visibility: Token![pub],
     pub ident: Ident,
     pub ty: Type,
@@ -170,6 +177,7 @@ pub struct Receiver {
 
 pub struct Variant {
     pub doc: Doc,
+    pub attrs: OtherAttrs,
     pub name: Pair,
     pub discriminant: Discriminant,
     pub expr: Option<Expr>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d970d8..5ce2cf3 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1,3 +1,4 @@
+use crate::syntax::attrs::OtherAttrs;
 use crate::syntax::discriminant::DiscriminantSet;
 use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
@@ -9,6 +10,7 @@ use crate::syntax::{
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
+use std::mem;
 use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
@@ -55,15 +57,15 @@ pub fn parse_items(
     apis
 }
 
-fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Result<Api> {
+fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &item.attrs,
+        mem::take(&mut item.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -98,9 +100,9 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     for field in named_fields.named {
         let ident = field.ident.unwrap();
         let mut doc = Doc::new();
-        attrs::parse(
+        let attrs = attrs::parse(
             cx,
-            &field.attrs,
+            field.attrs,
             attrs::Parser {
                 doc: Some(&mut doc),
                 ..Default::default()
@@ -121,6 +123,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
         });
         fields.push(Var {
             doc,
+            attrs,
             visibility,
             ident,
             ty,
@@ -140,6 +143,7 @@ fn parse_struct(cx: &mut Errors, item: ItemStruct, namespace: &Namespace) -> Res
     Ok(Api::Struct(Struct {
         doc,
         derives,
+        attrs,
         visibility,
         struct_token,
         name,
@@ -155,9 +159,9 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &item.attrs,
+        item.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -211,6 +215,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     Ok(Api::Enum(Enum {
         doc,
         derives,
+        attrs,
         enum_token,
         name,
         brace_token,
@@ -223,15 +228,15 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
 
 fn parse_variant(
     cx: &mut Errors,
-    variant: RustVariant,
+    mut variant: RustVariant,
     discriminants: &mut DiscriminantSet,
 ) -> Result<Variant> {
     let mut doc = Doc::new();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &variant.attrs,
+        mem::take(&mut variant.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             cxx_name: Some(&mut cxx_name),
@@ -263,6 +268,7 @@ fn parse_variant(
 
     Ok(Variant {
         doc,
+        attrs,
         name,
         discriminant,
         expr,
@@ -298,7 +304,7 @@ fn parse_foreign_mod(
     let mut namespace = namespace.clone();
     attrs::parse(
         cx,
-        &foreign_mod.attrs,
+        foreign_mod.attrs,
         attrs::Parser {
             namespace: Some(&mut namespace),
             ..Default::default()
@@ -306,7 +312,7 @@ fn parse_foreign_mod(
     );
 
     let mut items = Vec::new();
-    for foreign in &foreign_mod.items {
+    for foreign in foreign_mod.items {
         match foreign {
             ForeignItem::Type(foreign) => {
                 let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
@@ -390,7 +396,7 @@ fn parse_lang(abi: &Abi) -> Result<Lang> {
 
 fn parse_extern_type(
     cx: &mut Errors,
-    foreign_type: &ForeignItemType,
+    foreign_type: ForeignItemType,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
@@ -400,9 +406,9 @@ fn parse_extern_type(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &foreign_type.attrs,
+        foreign_type.attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -431,6 +437,7 @@ fn parse_extern_type(
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -443,7 +450,7 @@ fn parse_extern_type(
 
 fn parse_extern_fn(
     cx: &mut Errors,
-    foreign_fn: &ForeignItemFn,
+    mut foreign_fn: ForeignItemFn,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
@@ -452,9 +459,9 @@ fn parse_extern_fn(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &foreign_fn.attrs,
+        mem::take(&mut foreign_fn.attrs),
         attrs::Parser {
             doc: Some(&mut doc),
             namespace: Some(&mut namespace),
@@ -538,9 +545,11 @@ fn parse_extern_fn(
                 let ty = parse_type(&arg.ty)?;
                 if ident != "self" {
                     let doc = Doc::new();
+                    let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     args.push_value(Var {
                         doc,
+                        attrs,
                         visibility,
                         ident,
                         ty,
@@ -587,6 +596,7 @@ fn parse_extern_fn(
     }(ExternFn {
         lang,
         doc,
+        attrs,
         name,
         sig: Signature {
             unsafety,
@@ -606,7 +616,7 @@ fn parse_extern_fn(
 
 fn parse_extern_verbatim(
     cx: &mut Errors,
-    tokens: &TokenStream,
+    tokens: TokenStream,
     lang: Lang,
     trusted: bool,
     namespace: &Namespace,
@@ -675,7 +685,7 @@ fn parse_extern_verbatim(
             Err(lookahead.error())
         }
     }
-    .parse2(tokens.clone())
+    .parse2(tokens)
 }
 
 fn parse_type_alias(
@@ -697,9 +707,9 @@ fn parse_type_alias(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -721,6 +731,7 @@ fn parse_type_alias(
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -779,9 +790,9 @@ fn parse_extern_type_bounded(
     let mut namespace = namespace.clone();
     let mut cxx_name = None;
     let mut rust_name = None;
-    attrs::parse(
+    let attrs = attrs::parse(
         cx,
-        &attrs,
+        attrs,
         attrs::Parser {
             doc: Some(&mut doc),
             derives: Some(&mut derives),
@@ -801,6 +812,7 @@ fn parse_extern_type_bounded(
         lang,
         doc,
         derives,
+        attrs,
         type_token,
         name,
         generics,
@@ -1111,9 +1123,11 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
                 None => format_ident!("arg{}", i),
             };
             let doc = Doc::new();
+            let attrs = OtherAttrs::none();
             let visibility = Token![pub](ident.span());
             Ok(Var {
                 doc,
+                attrs,
                 visibility,
                 ident,
                 ty,
diff --git a/tests/ui/deny_missing_docs.rs b/tests/ui/deny_missing_docs.rs
index ee68ef1..037894b 100644
--- a/tests/ui/deny_missing_docs.rs
+++ b/tests/ui/deny_missing_docs.rs
@@ -56,6 +56,11 @@ pub mod ffi {
         /// ...
         pub fn documented_foreign_fn() -> u8;
     }
+
+    #[allow(missing_docs)]
+    pub struct SuppressUndocumentedStruct {
+        pub undocumented_field: u8,
+    }
 }
 
 struct UndocumentedRustType;

From 511c6fdb556e2f5dadbe06760207cf736e6782e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 00:58:54 +0000
Subject: [PATCH 1896/2232] Pass through two other diagnostics attributes as well


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 9a6be92..ccb1c51 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -125,8 +125,10 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
             || attr.path.is_ident("warn")
             || attr.path.is_ident("deny")
             || attr.path.is_ident("forbid")
+            || attr.path.is_ident("deprecated")
+            || attr.path.is_ident("must_use")
         {
-            // https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes
+            // https://doc.rust-lang.org/reference/attributes/diagnostics.html
             passthrough_attrs.push(attr);
             continue;
         }

From dc182794ecd2201f74cba0cc160bfeb8834dab0b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:01:34 +0000
Subject: [PATCH 1897/2232] Handle tool attrs inside the bridge module


---

diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index ccb1c51..87c4508 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -131,6 +131,15 @@ pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) 
             // https://doc.rust-lang.org/reference/attributes/diagnostics.html
             passthrough_attrs.push(attr);
             continue;
+        } else if attr.path.segments.len() > 1 {
+            let tool = &attr.path.segments.first().unwrap().ident;
+            if tool == "rustfmt" {
+                // Skip, rustfmt only needs to find it in the pre-expansion source file.
+                continue;
+            } else if tool == "clippy" {
+                passthrough_attrs.push(attr);
+                continue;
+            }
         }
         cx.error(attr, "unsupported attribute");
         break;

From 41e147c5cfe46c67e907f6add277ac09ad8a2332 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:06:45 +0000
Subject: [PATCH 1898/2232] Process outer attributes on the bridge module


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 249afdc..c355a9e 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,11 +1,12 @@
 use crate::derive;
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Signature, Struct,
-    Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, RustName, Signature,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -14,6 +15,17 @@ use syn::{parse_quote, Result, Token};
 
 pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
+
+    let mut doc = Doc::new();
+    let attrs = attrs::parse(
+        errors,
+        mem::take(&mut ffi.attrs),
+        attrs::Parser {
+            doc: Some(&mut doc),
+            ..Default::default()
+        },
+    );
+
     let content = mem::take(&mut ffi.content);
     let trusted = ffi.unsafety.is_some();
     let namespace = &ffi.namespace;
@@ -23,10 +35,10 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     check::typecheck(errors, apis, types);
     errors.propagate()?;
 
-    Ok(expand(ffi, apis, types))
+    Ok(expand(ffi, doc, attrs, apis, types))
 }
 
-fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
+fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
 
@@ -133,15 +145,12 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
         });
     }
 
-    let attrs = ffi
-        .attrs
-        .into_iter()
-        .filter(|attr| attr.path.is_ident("doc"));
     let vis = &ffi.vis;
     let ident = &ffi.ident;
 
     quote! {
-        #(#attrs)*
+        #doc
+        #attrs
         #[deny(improper_ctypes)]
         #[allow(non_snake_case)]
         #vis mod #ident {
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index 87c4508..d3e2bb0 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -40,7 +40,7 @@ pub struct Parser<'a> {
     pub(crate) _more: (),
 }
 
-pub(super) fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> OtherAttrs {
+pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> OtherAttrs {
     let mut passthrough_attrs = Vec::new();
     for attr in attrs {
         if attr.path.is_ident("doc") {

From 8fbaea8dbb92be11ad5f6b43c8c4ec6e862ec5e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:21:28 +0000
Subject: [PATCH 1899/2232] Fix span placement on shared enums


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c355a9e..a29434f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -314,15 +314,25 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let mut derives = None;
     let derived_traits = derive::expand_enum(enm, &mut derives);
 
+    let span = ident.span();
+    let visibility = enm.visibility;
+    let struct_token = Token![struct](enm.enum_token.span);
+    let enum_repr = quote! {
+        #[allow(missing_docs)]
+        pub repr: #repr,
+    };
+    let enum_def = quote_spanned! {span=>
+        #visibility #struct_token #ident {
+            #enum_repr
+        }
+    };
+
     quote! {
         #doc
         #attrs
         #derives
         #[repr(transparent)]
-        pub struct #ident {
-            #[allow(missing_docs)]
-            pub repr: #repr,
-        }
+        #enum_def
 
         #[allow(non_upper_case_globals)]
         impl #ident {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index da21204..0d07fd0 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -98,6 +98,7 @@ pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 5ce2cf3..b8bf515 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -194,6 +194,12 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
+    let visibility = Token![pub](match item.vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => item.ident.span(),
+    });
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
@@ -216,6 +222,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         doc,
         derives,
         attrs,
+        visibility,
         enum_token,
         name,
         brace_token,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index f31be34..6feec4f 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -17,6 +17,12 @@ error: missing documentation for a struct field
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
+  --> $DIR/deny_missing_docs.rs:21:5
+   |
+21 |     pub enum UndocumentedEnum {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for an associated constant
  --> $DIR/deny_missing_docs.rs:9:1
   |
 9 | #[cxx::bridge]
@@ -24,7 +30,7 @@ error: missing documentation for a struct
   |
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: missing documentation for an associated constant
+error: missing documentation for a struct
  --> $DIR/deny_missing_docs.rs:9:1
   |
 9 | #[cxx::bridge]
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 85cc0c5..183aa5e 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,8 +1,8 @@
 error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
-1  | #[cxx::bridge]
-   | -------------- `ffi::A` defined here
+3  |     enum A {
+   |          - `ffi::A` defined here
 ...
 12 |     match a {
    |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered

From e563fd951f5819ea1e9afd2651da37fa80bb996c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:21:52 +0000
Subject: [PATCH 1900/2232] Fix span placement on enum variants


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index a29434f..4fec02d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -305,7 +305,8 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         let attrs = &variant.attrs;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
-        Some(quote! {
+        let span = variant_ident.span();
+        Some(quote_spanned! {span=>
             #doc
             #attrs
             pub const #variant_ident: Self = #ident { repr: #discriminant };
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index 6feec4f..df82b3b 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -23,12 +23,10 @@ error: missing documentation for a struct
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for an associated constant
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:22:9
+   |
+22 |         UndocumentedVariant = 0,
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
  --> $DIR/deny_missing_docs.rs:9:1

From 524ff680819b0cc347032210cbf6e24389630a03 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:29:12 +0000
Subject: [PATCH 1901/2232] Fix span placement on extern C++ type


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index bfe370c..d94d36d 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -133,6 +133,7 @@ mod tests {
             doc: Doc::new(),
             derives: Vec::new(),
             attrs: OtherAttrs::none(),
+            visibility: Token![pub](Span::call_site()),
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4fec02d..b6746ac 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -360,15 +360,25 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
         let field = format_ident!("_lifetime_{}", lifetime.ident);
         quote!(#field: ::std::marker::PhantomData<&#lifetime ()>)
     });
+    let repr_fields = quote! {
+        _private: ::cxx::private::Opaque,
+        #(#lifetime_fields,)*
+    };
+
+    let span = ident.span();
+    let visibility = &ety.visibility;
+    let struct_token = Token![struct](ety.type_token.span);
+    let extern_type_def = quote_spanned! {span=>
+        #visibility #struct_token #ident #generics {
+            #repr_fields
+        }
+    };
 
     quote! {
         #doc
         #attrs
         #[repr(C)]
-        pub struct #ident #generics {
-            _private: ::cxx::private::Opaque,
-            #(#lifetime_fields,)*
-        }
+        #extern_type_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 0d07fd0..77e7e64 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,6 +74,7 @@ pub struct ExternType {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index b8bf515..0fbdda2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -426,6 +426,12 @@ fn parse_extern_type(
         },
     );
 
+    let visibility = Token![pub](match foreign_type.vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => foreign_type.ident.span(),
+    });
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
@@ -445,6 +451,7 @@ fn parse_extern_type(
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
@@ -630,7 +637,7 @@ fn parse_extern_verbatim(
 ) -> Result<Api> {
     |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
-        input.parse::<Visibility>()?;
+        let visibility: Visibility = input.parse()?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
             None => {
@@ -686,7 +693,8 @@ fn parse_extern_verbatim(
         } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
             // type Opaque: Bound2 + Bound2;
             parse_extern_type_bounded(
-                cx, attrs, type_token, ident, lifetimes, input, lang, trusted, namespace,
+                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted,
+                namespace,
             )
         } else {
             Err(lookahead.error())
@@ -751,6 +759,7 @@ fn parse_type_alias(
 fn parse_extern_type_bounded(
     cx: &mut Errors,
     attrs: Vec<Attribute>,
+    visibility: Visibility,
     type_token: Token![type],
     ident: Ident,
     generics: Lifetimes,
@@ -810,6 +819,12 @@ fn parse_extern_type_bounded(
         },
     );
 
+    let visibility = Token![pub](match visibility {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => ident.span(),
+    });
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -820,6 +835,7 @@ fn parse_extern_type_bounded(
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index df82b3b..55ae806 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -29,12 +29,10 @@ error: missing documentation for an associated constant
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:44:9
+   |
+44 |         pub type UndocumentedForeignType;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a type alias
  --> $DIR/deny_missing_docs.rs:9:1

From 291c9350d6473614cbd1c133cb476d3904ea0646 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 01:57:14 +0000
Subject: [PATCH 1902/2232] Fix span placement on type aliases


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index b6746ac..7e6182d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1019,13 +1019,18 @@ fn expand_rust_function_shim_super(
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let attrs = &alias.attrs;
+    let visibility = alias.visibility;
+    let type_token = alias.type_token;
     let ident = &alias.name.rust;
     let generics = &alias.generics;
+    let eq_token = alias.eq_token;
     let ty = &alias.ty;
+    let semi_token = alias.semi_token;
+
     quote! {
         #doc
         #attrs
-        pub type #ident #generics = #ty;
+        #visibility #type_token #ident #generics #eq_token #ty #semi_token
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 77e7e64..12904c3 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -123,6 +123,7 @@ pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0fbdda2..17c216d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -688,7 +688,7 @@ fn parse_extern_verbatim(
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
             parse_type_alias(
-                cx, attrs, type_token, ident, lifetimes, input, lang, namespace,
+                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
             )
         } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
             // type Opaque: Bound2 + Bound2;
@@ -706,6 +706,7 @@ fn parse_extern_verbatim(
 fn parse_type_alias(
     cx: &mut Errors,
     attrs: Vec<Attribute>,
+    visibility: Visibility,
     type_token: Token![type],
     ident: Ident,
     generics: Lifetimes,
@@ -741,12 +742,19 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
+    let visibility = Token![pub](match visibility {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => ident.span(),
+    });
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index 55ae806..fe8b250 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -35,12 +35,10 @@ error: missing documentation for a struct
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a type alias
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:49:9
+   |
+49 |         pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
  --> $DIR/deny_missing_docs.rs:9:1

From 49f9df7923ca195538cb721bda1af4b87f30d25f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 02:07:30 +0000
Subject: [PATCH 1903/2232] Fix span placement on extern functions


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 7e6182d..82cfed3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -632,22 +632,26 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         }
     };
     let mut dispatch = quote!(#setup #expr);
+    let visibility = efn.visibility;
     let unsafety = &efn.sig.unsafety;
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
+    let fn_token = efn.sig.fn_token;
     let ident = &efn.name.rust;
     let generics = &efn.generics;
+    let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*));
+    let fn_body = quote_spanned!(efn.semi_token.span=> {
+        extern "C" {
+            #decl
+        }
+        #trampolines
+        #dispatch
+    });
     let function_shim = quote! {
         #doc
         #attrs
-        pub #unsafety fn #ident #generics(#(#all_args,)*) #ret {
-            extern "C" {
-                #decl
-            }
-            #trampolines
-            #dispatch
-        }
+        #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
     };
     match &efn.receiver {
         None => function_shim,
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 12904c3..4dd18ea 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -113,6 +113,7 @@ pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 17c216d..0ef0b0b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -597,6 +597,12 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
+    let visibility = Token![pub](match foreign_fn.vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => foreign_fn.sig.ident.span(),
+    });
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
@@ -611,6 +617,7 @@ fn parse_extern_fn(
         lang,
         doc,
         attrs,
+        visibility,
         name,
         sig: Signature {
             unsafety,
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index fe8b250..e7aadfb 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -41,9 +41,7 @@ error: missing documentation for a type alias
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:54:9
+   |
+54 |         pub fn undocumented_foreign_fn() -> u8;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From a00f468cfaca9777d89e32ac6fb0c47584a12a6f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 02:11:16 +0000
Subject: [PATCH 1904/2232] Factor out visibility conversion helper


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0ef0b0b..93dfba0 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -115,12 +115,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
                 continue;
             }
         };
-        let visibility = Token![pub](match field.vis {
-            Visibility::Public(vis) => vis.pub_token.span,
-            Visibility::Crate(vis) => vis.crate_token.span,
-            Visibility::Restricted(vis) => vis.pub_token.span,
-            Visibility::Inherited => ident.span(),
-        });
+        let visibility = visibility_pub(&field.vis, &ident);
         fields.push(Var {
             doc,
             attrs,
@@ -130,12 +125,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
     }
 
-    let visibility = Token![pub](match item.vis {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => item.ident.span(),
-    });
+    let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let brace_token = named_fields.brace_token;
@@ -194,12 +184,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
-    let visibility = Token![pub](match item.vis {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => item.ident.span(),
-    });
+    let visibility = visibility_pub(&item.vis, &item.ident);
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
@@ -426,12 +411,7 @@ fn parse_extern_type(
         },
     );
 
-    let visibility = Token![pub](match foreign_type.vis {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => foreign_type.ident.span(),
-    });
+    let visibility = visibility_pub(&foreign_type.vis, &foreign_type.ident);
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
@@ -597,12 +577,7 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let visibility = Token![pub](match foreign_fn.vis {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => foreign_fn.sig.ident.span(),
-    });
+    let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
@@ -749,12 +724,7 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
-    let visibility = Token![pub](match visibility {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => ident.span(),
-    });
+    let visibility = visibility_pub(&visibility, &ident);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
@@ -834,12 +804,7 @@ fn parse_extern_type_bounded(
         },
     );
 
-    let visibility = Token![pub](match visibility {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => ident.span(),
-    });
+    let visibility = visibility_pub(&visibility, &ident);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -1228,6 +1193,15 @@ fn parse_return_type(
     }
 }
 
+fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
+    Token![pub](match vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => inherited.span(),
+    })
+}
+
 fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
     let default = || default.clone();
     Pair {

From 9a1de625ea64f1ab50da5c52429dff981ebfe14a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 02:18:18 +0000
Subject: [PATCH 1905/2232] Merge pull request #621 from dtolnay/spans


Fix span placement for rust lints inside of bridge module
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index bfe370c..d94d36d 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -133,6 +133,7 @@ mod tests {
             doc: Doc::new(),
             derives: Vec::new(),
             attrs: OtherAttrs::none(),
+            visibility: Token![pub](Span::call_site()),
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c355a9e..82cfed3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -305,7 +305,8 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         let attrs = &variant.attrs;
         let variant_ident = &variant.name.rust;
         let discriminant = &variant.discriminant;
-        Some(quote! {
+        let span = variant_ident.span();
+        Some(quote_spanned! {span=>
             #doc
             #attrs
             pub const #variant_ident: Self = #ident { repr: #discriminant };
@@ -314,15 +315,25 @@ fn expand_enum(enm: &Enum) -> TokenStream {
     let mut derives = None;
     let derived_traits = derive::expand_enum(enm, &mut derives);
 
+    let span = ident.span();
+    let visibility = enm.visibility;
+    let struct_token = Token![struct](enm.enum_token.span);
+    let enum_repr = quote! {
+        #[allow(missing_docs)]
+        pub repr: #repr,
+    };
+    let enum_def = quote_spanned! {span=>
+        #visibility #struct_token #ident {
+            #enum_repr
+        }
+    };
+
     quote! {
         #doc
         #attrs
         #derives
         #[repr(transparent)]
-        pub struct #ident {
-            #[allow(missing_docs)]
-            pub repr: #repr,
-        }
+        #enum_def
 
         #[allow(non_upper_case_globals)]
         impl #ident {
@@ -349,15 +360,25 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
         let field = format_ident!("_lifetime_{}", lifetime.ident);
         quote!(#field: ::std::marker::PhantomData<&#lifetime ()>)
     });
+    let repr_fields = quote! {
+        _private: ::cxx::private::Opaque,
+        #(#lifetime_fields,)*
+    };
+
+    let span = ident.span();
+    let visibility = &ety.visibility;
+    let struct_token = Token![struct](ety.type_token.span);
+    let extern_type_def = quote_spanned! {span=>
+        #visibility #struct_token #ident #generics {
+            #repr_fields
+        }
+    };
 
     quote! {
         #doc
         #attrs
         #[repr(C)]
-        pub struct #ident #generics {
-            _private: ::cxx::private::Opaque,
-            #(#lifetime_fields,)*
-        }
+        #extern_type_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
@@ -611,22 +632,26 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         }
     };
     let mut dispatch = quote!(#setup #expr);
+    let visibility = efn.visibility;
     let unsafety = &efn.sig.unsafety;
     if unsafety.is_none() {
         dispatch = quote!(unsafe { #dispatch });
     }
+    let fn_token = efn.sig.fn_token;
     let ident = &efn.name.rust;
     let generics = &efn.generics;
+    let arg_list = quote_spanned!(efn.sig.paren_token.span=> (#(#all_args,)*));
+    let fn_body = quote_spanned!(efn.semi_token.span=> {
+        extern "C" {
+            #decl
+        }
+        #trampolines
+        #dispatch
+    });
     let function_shim = quote! {
         #doc
         #attrs
-        pub #unsafety fn #ident #generics(#(#all_args,)*) #ret {
-            extern "C" {
-                #decl
-            }
-            #trampolines
-            #dispatch
-        }
+        #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
     };
     match &efn.receiver {
         None => function_shim,
@@ -998,13 +1023,18 @@ fn expand_rust_function_shim_super(
 fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
     let doc = &alias.doc;
     let attrs = &alias.attrs;
+    let visibility = alias.visibility;
+    let type_token = alias.type_token;
     let ident = &alias.name.rust;
     let generics = &alias.generics;
+    let eq_token = alias.eq_token;
     let ty = &alias.ty;
+    let semi_token = alias.semi_token;
+
     quote! {
         #doc
         #attrs
-        pub type #ident #generics = #ty;
+        #visibility #type_token #ident #generics #eq_token #ty #semi_token
     }
 }
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index da21204..4dd18ea 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -74,6 +74,7 @@ pub struct ExternType {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
@@ -98,6 +99,7 @@ pub struct Enum {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub enum_token: Token![enum],
     pub name: Pair,
     pub brace_token: Brace,
@@ -111,6 +113,7 @@ pub struct ExternFn {
     pub lang: Lang,
     pub doc: Doc,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub name: Pair,
     pub sig: Signature,
     pub semi_token: Token![;],
@@ -121,6 +124,7 @@ pub struct TypeAlias {
     pub doc: Doc,
     pub derives: Vec<Derive>,
     pub attrs: OtherAttrs,
+    pub visibility: Token![pub],
     pub type_token: Token![type],
     pub name: Pair,
     pub generics: Lifetimes,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 5ce2cf3..93dfba0 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -115,12 +115,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
                 continue;
             }
         };
-        let visibility = Token![pub](match field.vis {
-            Visibility::Public(vis) => vis.pub_token.span,
-            Visibility::Crate(vis) => vis.crate_token.span,
-            Visibility::Restricted(vis) => vis.pub_token.span,
-            Visibility::Inherited => ident.span(),
-        });
+        let visibility = visibility_pub(&field.vis, &ident);
         fields.push(Var {
             doc,
             attrs,
@@ -130,12 +125,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
     }
 
-    let visibility = Token![pub](match item.vis {
-        Visibility::Public(vis) => vis.pub_token.span,
-        Visibility::Crate(vis) => vis.crate_token.span,
-        Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => item.ident.span(),
-    });
+    let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let brace_token = named_fields.brace_token;
@@ -194,6 +184,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         }
     }
 
+    let visibility = visibility_pub(&item.vis, &item.ident);
     let enum_token = item.enum_token;
     let brace_token = item.brace_token;
 
@@ -216,6 +207,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         doc,
         derives,
         attrs,
+        visibility,
         enum_token,
         name,
         brace_token,
@@ -419,6 +411,7 @@ fn parse_extern_type(
         },
     );
 
+    let visibility = visibility_pub(&foreign_type.vis, &foreign_type.ident);
     let type_token = foreign_type.type_token;
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
@@ -438,6 +431,7 @@ fn parse_extern_type(
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
@@ -583,6 +577,7 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
+    let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
@@ -597,6 +592,7 @@ fn parse_extern_fn(
         lang,
         doc,
         attrs,
+        visibility,
         name,
         sig: Signature {
             unsafety,
@@ -623,7 +619,7 @@ fn parse_extern_verbatim(
 ) -> Result<Api> {
     |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
-        input.parse::<Visibility>()?;
+        let visibility: Visibility = input.parse()?;
         let type_token: Token![type] = match input.parse()? {
             Some(type_token) => type_token,
             None => {
@@ -674,12 +670,13 @@ fn parse_extern_verbatim(
         if lookahead.peek(Token![=]) {
             // type Alias = crate::path::to::Type;
             parse_type_alias(
-                cx, attrs, type_token, ident, lifetimes, input, lang, namespace,
+                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
             )
         } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
             // type Opaque: Bound2 + Bound2;
             parse_extern_type_bounded(
-                cx, attrs, type_token, ident, lifetimes, input, lang, trusted, namespace,
+                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted,
+                namespace,
             )
         } else {
             Err(lookahead.error())
@@ -691,6 +688,7 @@ fn parse_extern_verbatim(
 fn parse_type_alias(
     cx: &mut Errors,
     attrs: Vec<Attribute>,
+    visibility: Visibility,
     type_token: Token![type],
     ident: Ident,
     generics: Lifetimes,
@@ -726,12 +724,14 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
+    let visibility = visibility_pub(&visibility, &ident);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
@@ -744,6 +744,7 @@ fn parse_type_alias(
 fn parse_extern_type_bounded(
     cx: &mut Errors,
     attrs: Vec<Attribute>,
+    visibility: Visibility,
     type_token: Token![type],
     ident: Ident,
     generics: Lifetimes,
@@ -803,6 +804,7 @@ fn parse_extern_type_bounded(
         },
     );
 
+    let visibility = visibility_pub(&visibility, &ident);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -813,6 +815,7 @@ fn parse_extern_type_bounded(
         doc,
         derives,
         attrs,
+        visibility,
         type_token,
         name,
         generics,
@@ -1190,6 +1193,15 @@ fn parse_return_type(
     }
 }
 
+fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
+    Token![pub](match vis {
+        Visibility::Public(vis) => vis.pub_token.span,
+        Visibility::Crate(vis) => vis.crate_token.span,
+        Visibility::Restricted(vis) => vis.pub_token.span,
+        Visibility::Inherited => inherited.span(),
+    })
+}
+
 fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
     let default = || default.clone();
     Pair {
diff --git a/tests/ui/deny_missing_docs.stderr b/tests/ui/deny_missing_docs.stderr
index f31be34..e7aadfb 100644
--- a/tests/ui/deny_missing_docs.stderr
+++ b/tests/ui/deny_missing_docs.stderr
@@ -17,33 +17,31 @@ error: missing documentation for a struct field
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a struct
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:21:5
+   |
+21 |     pub enum UndocumentedEnum {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for an associated constant
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:22:9
+   |
+22 |         UndocumentedVariant = 0,
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+  --> $DIR/deny_missing_docs.rs:44:9
+   |
+44 |         pub type UndocumentedForeignType;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a type alias
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:49:9
+   |
+49 |         pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: missing documentation for a function
- --> $DIR/deny_missing_docs.rs:9:1
-  |
-9 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  --> $DIR/deny_missing_docs.rs:54:9
+   |
+54 |         pub fn undocumented_foreign_fn() -> u8;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 85cc0c5..183aa5e 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -1,8 +1,8 @@
 error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
-1  | #[cxx::bridge]
-   | -------------- `ffi::A` defined here
+3  |     enum A {
+   |          - `ffi::A` defined here
 ...
 12 |     match a {
    |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered

From 444f2dce6b5c2edbae0f0ca9a79f1ea90ad873c7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:02:12 +0000
Subject: [PATCH 1906/2232] Update ToTokens impls with exhaustive field matching


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 2e14f7a..f4478bc 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -37,39 +37,64 @@ impl ToTokens for Type {
 
 impl ToTokens for Var {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.ident.to_tokens(tokens);
-        Token![:](self.ident.span()).to_tokens(tokens);
-        self.ty.to_tokens(tokens);
+        let Var {
+            doc: _,
+            attrs: _,
+            visibility: _,
+            ident,
+            ty,
+        } = self;
+        ident.to_tokens(tokens);
+        Token![:](ident.span()).to_tokens(tokens);
+        ty.to_tokens(tokens);
     }
 }
 
 impl ToTokens for Ty1 {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let span = self.name.span();
-        let name = self.name.to_string();
-        if let "UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" = name.as_str() {
-            tokens.extend(quote_spanned!(span=> ::cxx::));
-        } else if name == "Vec" {
-            tokens.extend(quote_spanned!(span=> ::std::vec::));
+        let Ty1 {
+            name,
+            langle,
+            inner,
+            rangle,
+        } = self;
+        let span = name.span();
+        match name.to_string().as_str() {
+            "UniquePtr" | "SharedPtr" | "WeakPtr" | "CxxVector" => {
+                tokens.extend(quote_spanned!(span=> ::cxx::));
+            }
+            "Vec" => {
+                tokens.extend(quote_spanned!(span=> ::std::vec::));
+            }
+            _ => {}
         }
-        self.name.to_tokens(tokens);
-        self.langle.to_tokens(tokens);
-        self.inner.to_tokens(tokens);
-        self.rangle.to_tokens(tokens);
+        name.to_tokens(tokens);
+        langle.to_tokens(tokens);
+        inner.to_tokens(tokens);
+        rangle.to_tokens(tokens);
     }
 }
 
 impl ToTokens for Ref {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if let Some((pin, langle, _rangle)) = self.pin_tokens {
+        let Ref {
+            pinned: _,
+            ampersand,
+            lifetime,
+            mutable: _,
+            inner,
+            pin_tokens,
+            mutability,
+        } = self;
+        if let Some((pin, langle, _rangle)) = pin_tokens {
             tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
             langle.to_tokens(tokens);
         }
-        self.ampersand.to_tokens(tokens);
-        self.lifetime.to_tokens(tokens);
-        self.mutability.to_tokens(tokens);
-        self.inner.to_tokens(tokens);
-        if let Some((_pin, _langle, rangle)) = self.pin_tokens {
+        ampersand.to_tokens(tokens);
+        lifetime.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        inner.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = pin_tokens {
             rangle.to_tokens(tokens);
         }
     }
@@ -77,21 +102,36 @@ impl ToTokens for Ref {
 
 impl ToTokens for SliceRef {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.ampersand.to_tokens(tokens);
-        self.lifetime.to_tokens(tokens);
-        self.mutability.to_tokens(tokens);
-        self.bracket.surround(tokens, |tokens| {
-            self.inner.to_tokens(tokens);
+        let SliceRef {
+            ampersand,
+            lifetime,
+            mutable: _,
+            bracket,
+            inner,
+            mutability,
+        } = self;
+        ampersand.to_tokens(tokens);
+        lifetime.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        bracket.surround(tokens, |tokens| {
+            inner.to_tokens(tokens);
         });
     }
 }
 
 impl ToTokens for Array {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.bracket.surround(tokens, |tokens| {
-            self.inner.to_tokens(tokens);
-            self.semi_token.to_tokens(tokens);
-            self.len_token.to_tokens(tokens);
+        let Array {
+            bracket,
+            inner,
+            semi_token,
+            len: _,
+            len_token,
+        } = self;
+        bracket.surround(tokens, |tokens| {
+            inner.to_tokens(tokens);
+            semi_token.to_tokens(tokens);
+            len_token.to_tokens(tokens);
         });
     }
 }
@@ -150,30 +190,53 @@ impl ToTokens for ExternFn {
 
 impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.impl_token.to_tokens(tokens);
-        self.negative_token.to_tokens(tokens);
-        self.ty.to_tokens(tokens);
-        self.brace_token.surround(tokens, |_tokens| {});
+        let Impl {
+            impl_token,
+            negative: _,
+            ty,
+            brace_token,
+            negative_token,
+        } = self;
+        impl_token.to_tokens(tokens);
+        negative_token.to_tokens(tokens);
+        ty.to_tokens(tokens);
+        brace_token.surround(tokens, |_tokens| {});
     }
 }
 
 impl ToTokens for Lifetimes {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.lt_token.to_tokens(tokens);
-        self.lifetimes.to_tokens(tokens);
-        self.gt_token.to_tokens(tokens);
+        let Lifetimes {
+            lt_token,
+            lifetimes,
+            gt_token,
+        } = self;
+        lt_token.to_tokens(tokens);
+        lifetimes.to_tokens(tokens);
+        gt_token.to_tokens(tokens);
     }
 }
 
 impl ToTokens for Signature {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.fn_token.to_tokens(tokens);
-        self.paren_token.surround(tokens, |tokens| {
-            self.args.to_tokens(tokens);
+        let Signature {
+            unsafety: _,
+            fn_token,
+            generics: _,
+            receiver: _,
+            args,
+            ret,
+            throws: _,
+            paren_token,
+            throws_tokens,
+        } = self;
+        fn_token.to_tokens(tokens);
+        paren_token.surround(tokens, |tokens| {
+            args.to_tokens(tokens);
         });
-        if let Some(ret) = &self.ret {
-            Token![->](self.paren_token.span).to_tokens(tokens);
-            if let Some((result, langle, rangle)) = self.throws_tokens {
+        if let Some(ret) = ret {
+            Token![->](paren_token.span).to_tokens(tokens);
+            if let Some((result, langle, rangle)) = throws_tokens {
                 result.to_tokens(tokens);
                 langle.to_tokens(tokens);
                 ret.to_tokens(tokens);
@@ -181,8 +244,8 @@ impl ToTokens for Signature {
             } else {
                 ret.to_tokens(tokens);
             }
-        } else if let Some((result, langle, rangle)) = self.throws_tokens {
-            Token![->](self.paren_token.span).to_tokens(tokens);
+        } else if let Some((result, langle, rangle)) = throws_tokens {
+            Token![->](paren_token.span).to_tokens(tokens);
             result.to_tokens(tokens);
             langle.to_tokens(tokens);
             token::Paren(langle.span).surround(tokens, |_| ());
@@ -193,7 +256,8 @@ impl ToTokens for Signature {
 
 impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        self.rust.to_tokens(tokens);
+        let RustName { rust } = self;
+        rust.to_tokens(tokens);
     }
 }
 
@@ -208,15 +272,26 @@ impl Receiver {
 
 impl ToTokens for ReceiverType<'_> {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        if let Some((pin, langle, _rangle)) = self.0.pin_tokens {
+        let Receiver {
+            pinned: _,
+            ampersand,
+            lifetime,
+            mutable: _,
+            var: _,
+            ty,
+            shorthand: _,
+            pin_tokens,
+            mutability,
+        } = &self.0;
+        if let Some((pin, langle, _rangle)) = pin_tokens {
             tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
             langle.to_tokens(tokens);
         }
-        self.0.ampersand.to_tokens(tokens);
-        self.0.lifetime.to_tokens(tokens);
-        self.0.mutability.to_tokens(tokens);
-        self.0.ty.to_tokens(tokens);
-        if let Some((_pin, _langle, rangle)) = self.0.pin_tokens {
+        ampersand.to_tokens(tokens);
+        lifetime.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        ty.to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = pin_tokens {
             rangle.to_tokens(tokens);
         }
     }

From 0c669ea3d10d707f5210449c9c98d57b46c501ef Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:02:35 +0000
Subject: [PATCH 1907/2232] Replace ref cast to RustName with just using Ident


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4dd18ea..64ff8e7 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -255,7 +255,6 @@ pub struct Pair {
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[repr(transparent)]
 pub struct RustName {
     pub rust: Ident,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index ec93c3d..51b1341 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -26,10 +26,6 @@ impl RustName {
         RustName { rust }
     }
 
-    pub fn from_ref(rust: &Ident) -> &Self {
-        unsafe { &*(rust as *const Ident as *const Self) }
-    }
-
     pub fn span(&self) -> Span {
         self.rust.span()
     }
diff --git a/syntax/types.rs b/syntax/types.rs
index f7682bc..58a3086 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -19,7 +19,7 @@ pub struct Types<'a> {
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
     pub explicit_impls: Set<&'a Impl>,
-    pub resolutions: Map<&'a RustName, &'a Pair>,
+    pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -63,7 +63,7 @@ impl<'a> Types<'a> {
         }
 
         let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(RustName::from_ref(&pair.rust), pair);
+            resolutions.insert(&pair.rust, pair);
         };
 
         let mut type_names = UnorderedSet::new();
@@ -238,7 +238,9 @@ impl<'a> Types<'a> {
     }
 
     pub fn resolve(&self, ident: &RustName) -> &Pair {
-        self.resolutions.get(ident).expect("Unable to resolve type")
+        self.resolutions
+            .get(&ident.rust)
+            .expect("Unable to resolve type")
     }
 }
 

From 4a79b7f8d849541d9241dcc7e48b50d75bd9d5e1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:03:35 +0000
Subject: [PATCH 1908/2232] Track lifetimes on rust name types


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4504fe6..8c16f2d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
+    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
@@ -81,6 +81,38 @@ impl PartialEq for Type {
     }
 }
 
+impl Eq for Lifetimes {}
+
+impl PartialEq for Lifetimes {
+    fn eq(&self, other: &Lifetimes) -> bool {
+        let Lifetimes {
+            lt_token: _,
+            lifetimes,
+            gt_token: _,
+        } = self;
+        let Lifetimes {
+            lt_token: _,
+            lifetimes: lifetimes2,
+            gt_token: _,
+        } = other;
+        lifetimes.iter().eq(lifetimes2)
+    }
+}
+
+impl Hash for Lifetimes {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Lifetimes {
+            lt_token: _,
+            lifetimes,
+            gt_token: _,
+        } = self;
+        lifetimes.len().hash(state);
+        for lifetime in lifetimes {
+            lifetime.hash(state);
+        }
+    }
+}
+
 impl Eq for Ty1 {}
 
 impl PartialEq for Ty1 {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 64ff8e7..6fe45d3 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -254,7 +254,8 @@ pub struct Pair {
 
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(PartialEq, Eq, Hash)]
 pub struct RustName {
     pub rust: Ident,
+    pub generics: Lifetimes,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index 51b1341..50f6ebd 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,6 +1,7 @@
-use crate::syntax::{Pair, RustName, Symbol, Types};
+use crate::syntax::{Lifetimes, Pair, RustName, Symbol, Types};
 use proc_macro2::{Ident, Span};
 use std::iter;
+use syn::punctuated::Punctuated;
 
 impl Pair {
     pub fn to_symbol(&self) -> Symbol {
@@ -23,7 +24,12 @@ impl Pair {
 
 impl RustName {
     pub fn new(rust: Ident) -> Self {
-        RustName { rust }
+        let generics = Lifetimes {
+            lt_token: None,
+            lifetimes: Punctuated::new(),
+            gt_token: None,
+        };
+        RustName { rust, generics }
     }
 
     pub fn span(&self) -> Span {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index f4478bc..71f77b1 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -256,7 +256,7 @@ impl ToTokens for Signature {
 
 impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let RustName { rust } = self;
+        let RustName { rust, generics: _ } = self;
         rust.to_tokens(tokens);
     }
 }

From 926634ac3becceb7d4d012671b00f6f24f4e02b6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:10:58 +0000
Subject: [PATCH 1909/2232] Merge pull request #622 from dtolnay/lifetimes


Represent type names with generic lifetime parameters
---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4504fe6..8c16f2d 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    Array, ExternFn, Impl, Include, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
+    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
@@ -81,6 +81,38 @@ impl PartialEq for Type {
     }
 }
 
+impl Eq for Lifetimes {}
+
+impl PartialEq for Lifetimes {
+    fn eq(&self, other: &Lifetimes) -> bool {
+        let Lifetimes {
+            lt_token: _,
+            lifetimes,
+            gt_token: _,
+        } = self;
+        let Lifetimes {
+            lt_token: _,
+            lifetimes: lifetimes2,
+            gt_token: _,
+        } = other;
+        lifetimes.iter().eq(lifetimes2)
+    }
+}
+
+impl Hash for Lifetimes {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Lifetimes {
+            lt_token: _,
+            lifetimes,
+            gt_token: _,
+        } = self;
+        lifetimes.len().hash(state);
+        for lifetime in lifetimes {
+            lifetime.hash(state);
+        }
+    }
+}
+
 impl Eq for Ty1 {}
 
 impl PartialEq for Ty1 {
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 4dd18ea..6fe45d3 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -254,8 +254,8 @@ pub struct Pair {
 
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[repr(transparent)]
+#[derive(PartialEq, Eq, Hash)]
 pub struct RustName {
     pub rust: Ident,
+    pub generics: Lifetimes,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index ec93c3d..50f6ebd 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,6 +1,7 @@
-use crate::syntax::{Pair, RustName, Symbol, Types};
+use crate::syntax::{Lifetimes, Pair, RustName, Symbol, Types};
 use proc_macro2::{Ident, Span};
 use std::iter;
+use syn::punctuated::Punctuated;
 
 impl Pair {
     pub fn to_symbol(&self) -> Symbol {
@@ -23,11 +24,12 @@ impl Pair {
 
 impl RustName {
     pub fn new(rust: Ident) -> Self {
-        RustName { rust }
-    }
-
-    pub fn from_ref(rust: &Ident) -> &Self {
-        unsafe { &*(rust as *const Ident as *const Self) }
+        let generics = Lifetimes {
+            lt_token: None,
+            lifetimes: Punctuated::new(),
+            gt_token: None,
+        };
+        RustName { rust, generics }
     }
 
     pub fn span(&self) -> Span {
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index f4478bc..71f77b1 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -256,7 +256,7 @@ impl ToTokens for Signature {
 
 impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let RustName { rust } = self;
+        let RustName { rust, generics: _ } = self;
         rust.to_tokens(tokens);
     }
 }
diff --git a/syntax/types.rs b/syntax/types.rs
index f7682bc..58a3086 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -19,7 +19,7 @@ pub struct Types<'a> {
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
     pub explicit_impls: Set<&'a Impl>,
-    pub resolutions: Map<&'a RustName, &'a Pair>,
+    pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -63,7 +63,7 @@ impl<'a> Types<'a> {
         }
 
         let mut add_resolution = |pair: &'a Pair| {
-            resolutions.insert(RustName::from_ref(&pair.rust), pair);
+            resolutions.insert(&pair.rust, pair);
         };
 
         let mut type_names = UnorderedSet::new();
@@ -238,7 +238,9 @@ impl<'a> Types<'a> {
     }
 
     pub fn resolve(&self, ident: &RustName) -> &Pair {
-        self.resolutions.get(ident).expect("Unable to resolve type")
+        self.resolutions
+            .get(&ident.rust)
+            .expect("Unable to resolve type")
     }
 }
 

From 5b41c09e9a146ef2293f6f14d23d954f172a39b2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:11:33 +0000
Subject: [PATCH 1910/2232] Defer Cargo links metadata printing until after code generation


This results in slightly less noise when code generation produces an
error during a Cargo build.

Before:

    process didn't exit successfully: `/git/example-cxx/target/debug/build/example-f20ef12178a95a23/build-script-build` (exit code: 1)
    --- stdout
    cargo:CXXBRIDGE_PREFIX=example
    cargo:CXXBRIDGE_DIR0=/git/example-cxx/target/debug/build/example-188c8410ffc8bb7d/out/cxxbridge/include
    cargo:CXXBRIDGE_DIR1=/git/example-cxx/target/debug/build/example-188c8410ffc8bb7d/out/cxxbridge/crate

    --- stderr

    error[cxxbridge]: extern type with lifetimes is not supported yet
      ┌─ src/main.rs:9:21
      │
    9 │         type Object<'a>;
      │                     ^^ extern type with lifetimes is not supported yet

After:

    process didn't exit successfully: `/git/example-cxx/target/debug/build/example-f20ef12178a95a23/build-script-build` (exit code: 1)
    --- stderr

    error[cxxbridge]: extern type with lifetimes is not supported yet
      ┌─ src/main.rs:9:21
      │
    9 │         type Object<'a>;
      │                     ^^ extern type with lifetimes is not supported yet

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index fe51cd6..f7d4182 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -206,7 +206,6 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let ref prj = Project::init()?;
     validate_cfg(prj)?;
     let this_crate = make_this_crate(prj)?;
-    this_crate.print_to_cargo();
 
     let mut build = Build::new();
     build.cpp(true);
@@ -216,6 +215,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
+    this_crate.print_to_cargo();
     eprintln!("\nCXX include path:");
     for header_dir in this_crate.header_dirs {
         build.include(&header_dir.path);

From 5a565827d0ee123c363d58955566246c51faf65f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:20:18 +0000
Subject: [PATCH 1911/2232] Merge pull request #623 from dtolnay/metadata


Defer Cargo links metadata printing until after code generation
---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index fe51cd6..f7d4182 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -206,7 +206,6 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
     let ref prj = Project::init()?;
     validate_cfg(prj)?;
     let this_crate = make_this_crate(prj)?;
-    this_crate.print_to_cargo();
 
     let mut build = Build::new();
     build.cpp(true);
@@ -216,6 +215,7 @@ fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Resul
         generate_bridge(prj, &mut build, path.as_ref())?;
     }
 
+    this_crate.print_to_cargo();
     eprintln!("\nCXX include path:");
     for header_dir in this_crate.header_dirs {
         build.include(&header_dir.path);

From 679b15d677ac92d72b443fb342510b268299ea7a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:51:39 +0000
Subject: [PATCH 1912/2232] Parse lifetimes on Ident type names


---

diff --git a/syntax/check.rs b/syntax/check.rs
index fcd5f9a..42e92f4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
     error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref,
-    Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    RustName, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -27,7 +27,7 @@ fn do_typecheck(cx: &mut Check) {
 
     for ty in cx.types {
         match ty {
-            Type::Ident(ident) => check_type_ident(cx, &ident.rust),
+            Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
@@ -61,7 +61,8 @@ impl Check<'_> {
     }
 }
 
-fn check_type_ident(cx: &mut Check, ident: &Ident) {
+fn check_type_ident(cx: &mut Check, name: &RustName) {
+    let ident = &name.rust;
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
         && !cx.types.enums.contains_key(ident)
@@ -70,6 +71,11 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
     {
         let msg = format!("unsupported type: {}", ident);
         cx.error(ident, &msg);
+        return;
+    }
+
+    if !name.generics.lifetimes.is_empty() {
+        cx.error(name, "type with lifetime parameter is not supported yet");
     }
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 93dfba0..405006c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1056,6 +1056,31 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             return Ok(Type::Ref(inner));
                         }
                     }
+                } else {
+                    let mut lifetimes = Punctuated::new();
+                    let mut only_lifetimes = true;
+                    for pair in generic.args.pairs() {
+                        let (param, punct) = pair.into_tuple();
+                        if let GenericArgument::Lifetime(param) = param {
+                            lifetimes.push_value(param.clone());
+                            if let Some(punct) = punct {
+                                lifetimes.push_punct(*punct);
+                            }
+                        } else {
+                            only_lifetimes = false;
+                            break;
+                        }
+                    }
+                    if only_lifetimes {
+                        return Ok(Type::Ident(RustName {
+                            rust: ident,
+                            generics: Lifetimes {
+                                lt_token: Some(generic.lt_token),
+                                lifetimes,
+                                gt_token: Some(generic.gt_token),
+                            },
+                        }));
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 71f77b1..19e361f 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -256,8 +256,9 @@ impl ToTokens for Signature {
 
 impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let RustName { rust, generics: _ } = self;
+        let RustName { rust, generics } = self;
         rust.to_tokens(tokens);
+        generics.to_tokens(tokens);
     }
 }
 

From 249df3baefff6b26fb36e82f1a99f8f064338c98 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 04:59:12 +0000
Subject: [PATCH 1913/2232] Merge pull request #624 from dtolnay/identlife


Parse lifetimes on Ident type names
---

diff --git a/syntax/check.rs b/syntax/check.rs
index fcd5f9a..42e92f4 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
     error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref,
-    Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    RustName, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -27,7 +27,7 @@ fn do_typecheck(cx: &mut Check) {
 
     for ty in cx.types {
         match ty {
-            Type::Ident(ident) => check_type_ident(cx, &ident.rust),
+            Type::Ident(ident) => check_type_ident(cx, ident),
             Type::RustBox(ptr) => check_type_box(cx, ptr),
             Type::RustVec(ty) => check_type_rust_vec(cx, ty),
             Type::UniquePtr(ptr) => check_type_unique_ptr(cx, ptr),
@@ -61,7 +61,8 @@ impl Check<'_> {
     }
 }
 
-fn check_type_ident(cx: &mut Check, ident: &Ident) {
+fn check_type_ident(cx: &mut Check, name: &RustName) {
+    let ident = &name.rust;
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
         && !cx.types.enums.contains_key(ident)
@@ -70,6 +71,11 @@ fn check_type_ident(cx: &mut Check, ident: &Ident) {
     {
         let msg = format!("unsupported type: {}", ident);
         cx.error(ident, &msg);
+        return;
+    }
+
+    if !name.generics.lifetimes.is_empty() {
+        cx.error(name, "type with lifetime parameter is not supported yet");
     }
 }
 
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 93dfba0..405006c 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1056,6 +1056,31 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                             return Ok(Type::Ref(inner));
                         }
                     }
+                } else {
+                    let mut lifetimes = Punctuated::new();
+                    let mut only_lifetimes = true;
+                    for pair in generic.args.pairs() {
+                        let (param, punct) = pair.into_tuple();
+                        if let GenericArgument::Lifetime(param) = param {
+                            lifetimes.push_value(param.clone());
+                            if let Some(punct) = punct {
+                                lifetimes.push_punct(*punct);
+                            }
+                        } else {
+                            only_lifetimes = false;
+                            break;
+                        }
+                    }
+                    if only_lifetimes {
+                        return Ok(Type::Ident(RustName {
+                            rust: ident,
+                            generics: Lifetimes {
+                                lt_token: Some(generic.lt_token),
+                                lifetimes,
+                                gt_token: Some(generic.gt_token),
+                            },
+                        }));
+                    }
                 }
             }
             PathArguments::Parenthesized(_) => {}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 71f77b1..19e361f 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -256,8 +256,9 @@ impl ToTokens for Signature {
 
 impl ToTokens for RustName {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let RustName { rust, generics: _ } = self;
+        let RustName { rust, generics } = self;
         rust.to_tokens(tokens);
+        generics.to_tokens(tokens);
     }
 }
 

From 30bea1c6c6c3261614692bff5be5cd82dfc319f2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 18:48:36 +0000
Subject: [PATCH 1914/2232] Move CxxVector mut indexing to Pin<&mut Self>


Fixes #625.

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 4bfb7a2..593c73a 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -64,9 +64,9 @@ where
 
     /// Returns a pinned mutable reference to an element at the given position,
     /// or `None` if out of bounds.
-    pub fn get_mut(&mut self, pos: usize) -> Option<Pin<&mut T>> {
+    pub fn get_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
         if pos < self.len() {
-            Some(unsafe { self.get_unchecked_mut(pos) })
+            Some(unsafe { CxxVector::get_unchecked_mut(self, pos) })
         } else {
             None
         }
@@ -99,8 +99,8 @@ where
     /// [std::vector\<T\>::operator\[\]][operator_at].
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
-    pub unsafe fn get_unchecked_mut(&mut self, pos: usize) -> Pin<&mut T> {
-        let ptr = T::__get_unchecked(self, pos);
+    pub unsafe fn get_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
+        let ptr = T::__get_unchecked(Pin::get_unchecked_mut(self), pos);
         Pin::new_unchecked(&mut *ptr)
     }
 
@@ -131,7 +131,7 @@ where
     }
 
     /// Returns an iterator over elements of type `Pin<&mut T>`.
-    pub fn iter_mut(&mut self) -> IterMut<T> {
+    pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> {
         IterMut { v: self, index: 0 }
     }
 }
@@ -189,11 +189,11 @@ impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {}
 ///
 /// The iterator element type is `Pin<&'a mut T>`.
 pub struct IterMut<'a, T> {
-    v: &'a mut CxxVector<T>,
+    v: Pin<&'a mut CxxVector<T>>,
     index: usize,
 }
 
-impl<'a, T> IntoIterator for &'a mut CxxVector<T>
+impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>>
 where
     T: VectorElement,
 {
@@ -212,7 +212,7 @@ where
     type Item = Pin<&'a mut T>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        let next = self.v.get_mut(self.index)?;
+        let next = CxxVector::get_mut(self.v.as_mut(), self.index)?;
         self.index += 1;
         // Extend lifetime to allow simultaneous holding of nonoverlapping
         // elements, analogous to slice::split_first_mut.

From 5b395b33db9ed259df29310569d0fdd2daa8f092 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 18:49:18 +0000
Subject: [PATCH 1915/2232] Work around conflict between CxxVector::get_mut and Pin::get_mut


Previously:

    error[E0034]: multiple applicable items in scope
      --> src/main.rs:39:20
       |
    39 |     let _ = vector.get_mut(0);
       |                    ^^^^^^^ multiple `get_mut` found
       |
       = note: candidate #1 is defined in an impl for the type `Pin<&'a mut T>`
       = note: candidate #2 is defined in an impl for the type `CxxVector<T>`

---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index 593c73a..d112bc4 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -64,9 +64,9 @@ where
 
     /// Returns a pinned mutable reference to an element at the given position,
     /// or `None` if out of bounds.
-    pub fn get_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
+    pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> {
         if pos < self.len() {
-            Some(unsafe { CxxVector::get_unchecked_mut(self, pos) })
+            Some(unsafe { self.index_unchecked_mut(pos) })
         } else {
             None
         }
@@ -99,8 +99,8 @@ where
     /// [std::vector\<T\>::operator\[\]][operator_at].
     ///
     /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at
-    pub unsafe fn get_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
-        let ptr = T::__get_unchecked(Pin::get_unchecked_mut(self), pos);
+    pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> {
+        let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos);
         Pin::new_unchecked(&mut *ptr)
     }
 
@@ -212,7 +212,7 @@ where
     type Item = Pin<&'a mut T>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        let next = CxxVector::get_mut(self.v.as_mut(), self.index)?;
+        let next = self.v.as_mut().index_mut(self.index)?;
         self.index += 1;
         // Extend lifetime to allow simultaneous holding of nonoverlapping
         // elements, analogous to slice::split_first_mut.

From 3fab70e0dec226d29ee2b87b6fa8c9522e4264d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 18:51:19 +0000
Subject: [PATCH 1916/2232] Release 1.0.25


---

diff --git a/Cargo.toml b/Cargo.toml
index 84c74c8..a6937b4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.24" # remember to update html_root_url
+version = "1.0.25" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.24", path = "macro" }
+cxxbridge-macro = { version = "=1.0.25", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.24", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.25", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.24", path = "gen/build" }
+cxx-build = { version = "=1.0.25", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 16a1f1e..31ffd70 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.24"
+version = "1.0.25"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 0affec9..d0fbf64 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.24"
+version = "1.0.25"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 17388b2..7070ede 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.24"
+version = "1.0.25"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 01f3fad..ee067a0 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.24"
+version = "0.7.25"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 2e2131f..9ce375a 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.24"
+version = "1.0.25"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index b6839b4..20c6346 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.24")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.25")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8b6d166..cedab32 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.24"
+version = "1.0.25"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.24"
+version = "1.0.25"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.24"
+version = "0.7.25"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.24"
+version = "1.0.25"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.24"
+version = "1.0.25"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.24"
+version = "1.0.25"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5573e529e5c824e0026565bb45037e0b6b063e15 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 19:07:52 +0000
Subject: [PATCH 1917/2232] Emit docs on struct fields into generated C++ code


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index fc6801c..6b89178 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -233,6 +233,9 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
     writeln!(out, "struct {} final {{", strct.name.cxx);
 
     for field in &strct.fields {
+        for line in field.doc.to_string().lines() {
+            writeln!(out, "  //{}", line);
+        }
         write!(out, "  ");
         write_type_space(out, &field.ty);
         writeln!(out, "{};", field.ident);

From ab1ac88c4430b1c4c04001f9e9b38d75bc8b99f0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 19:58:26 +0000
Subject: [PATCH 1918/2232] Add CxxVector::as_mut_slice


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d112bc4..d78ee47 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -125,6 +125,21 @@ where
         }
     }
 
+    /// Returns a slice to the underlying contiguous array of elements by
+    /// mutable reference.
+    pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
+    where
+        T: ExternType<Kind = Trivial>,
+    {
+        let len = self.len();
+        if len == 0 {
+            &mut []
+        } else {
+            let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) };
+            unsafe { slice::from_raw_parts_mut(ptr, len) }
+        }
+    }
+
     /// Returns an iterator over elements of type `&T`.
     pub fn iter(&self) -> Iter<T> {
         Iter { v: self, index: 0 }

From 89fd09b66bf59d2af1a20b59e8fb860f8bb1f7c7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 22:51:12 +0000
Subject: [PATCH 1919/2232] Emit lifetime parameters in ToTokens of Type


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 19e361f..1c7c5bc 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -18,7 +18,7 @@ impl ToTokens for Type {
                     let span = ident.rust.span();
                     tokens.extend(quote_spanned!(span=> ::cxx::));
                 }
-                ident.rust.to_tokens(tokens);
+                ident.to_tokens(tokens);
             }
             Type::RustBox(ty)
             | Type::UniquePtr(ty)

From f4d978941e6b069978945d14fdacc724747ae2c4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 23:30:55 +0000
Subject: [PATCH 1920/2232] Ignore wrong_self_convention clippy lint


    warning: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name
       --> src/cxx_vector.rs:130:25
        |
    130 |     pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T]
        |                         ^^^^
        |
        = note: `#[warn(clippy::wrong_self_convention)]` on by default
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

---

diff --git a/src/lib.rs b/src/lib.rs
index 20c6346..bed0bc0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -385,7 +385,8 @@
     clippy::or_fun_call,
     clippy::ptr_arg,
     clippy::toplevel_ref_arg,
-    clippy::useless_let_if_seq
+    clippy::useless_let_if_seq,
+    clippy::wrong_self_convention
 )]
 
 #[cfg(built_with_cargo)]

From 4c6052d74942912d3607025f4559c340409dd4e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 23:31:28 +0000
Subject: [PATCH 1921/2232] Key impls by an enum rather than by Type


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6b89178..8242b2e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1336,11 +1336,15 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
         if let Type::RustBox(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_rust_box_extern(out, &out.types.resolve(&inner));
@@ -1350,7 +1354,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vec.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_rust_vec_extern(out, inner);
@@ -1360,7 +1364,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_unique_ptr(out, inner);
@@ -1370,7 +1374,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_shared_ptr(out, inner);
@@ -1380,7 +1384,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_weak_ptr(out, inner);
@@ -1390,7 +1394,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_cxx_vector(out, inner);
@@ -1403,11 +1407,15 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
         if let Type::RustBox(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     write_rust_box_impl(out, &out.types.resolve(&inner));
                 }
@@ -1416,7 +1424,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vec.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     write_rust_vec_impl(out, inner);
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 82cfed3..85f834d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -80,7 +80,11 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
     }
 
     for ty in types {
-        let explicit_impl = types.explicit_impls.get(ty);
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
+        let explicit_impl = types.explicit_impls.get(&impl_key).copied();
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1366,7 +1370,6 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
 }
 
 fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
-    let _ = explicit_impl;
     let name = elem.rust.to_string();
     let prefix = format!("cxxbridge1$std$vector${}$", elem.to_symbol(types));
     let link_size = format!("{}size", prefix);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8c16f2d..4fa0335 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,7 +1,6 @@
 use crate::syntax::{
     Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
-use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
@@ -447,9 +446,3 @@ impl PartialEq for Impl {
         negative == negative2 && ty == ty2
     }
 }
-
-impl Borrow<Type> for &Impl {
-    fn borrow(&self) -> &Type {
-        &self.ty
-    }
-}
diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
new file mode 100644
index 0000000..2891485
--- /dev/null
+++ b/syntax/instantiate.rs
@@ -0,0 +1,43 @@
+use crate::syntax::Type;
+use proc_macro2::Ident;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ImplKey<'a> {
+    RustBox(&'a Ident),
+    RustVec(&'a Ident),
+    UniquePtr(&'a Ident),
+    SharedPtr(&'a Ident),
+    WeakPtr(&'a Ident),
+    CxxVector(&'a Ident),
+}
+
+impl Type {
+    pub(crate) fn impl_key(&self) -> Option<ImplKey> {
+        if let Type::RustBox(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::RustBox(&ident.rust));
+            }
+        } else if let Type::RustVec(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::RustVec(&ident.rust));
+            }
+        } else if let Type::UniquePtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::UniquePtr(&ident.rust));
+            }
+        } else if let Type::SharedPtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::SharedPtr(&ident.rust));
+            }
+        } else if let Type::WeakPtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::WeakPtr(&ident.rust));
+            }
+        } else if let Type::CxxVector(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::CxxVector(&ident.rust));
+            }
+        }
+        None
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 6fe45d3..9a21087 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -11,6 +11,7 @@ pub mod file;
 pub mod ident;
 mod impls;
 mod improper;
+pub mod instantiate;
 pub mod mangle;
 mod names;
 pub mod namespace;
diff --git a/syntax/types.rs b/syntax/types.rs
index 58a3086..4c1fef0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,4 +1,5 @@
 use crate::syntax::improper::ImproperCtype;
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
@@ -18,7 +19,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: Set<&'a Impl>,
+    pub explicit_impls: Map<ImplKey<'a>, &'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
@@ -33,7 +34,7 @@ impl<'a> Types<'a> {
         let mut rust = Set::new();
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
-        let mut explicit_impls = Set::new();
+        let mut explicit_impls = Map::new();
         let mut resolutions = Map::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
@@ -160,7 +161,9 @@ impl<'a> Types<'a> {
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
-                    explicit_impls.insert(imp);
+                    if let Some(key) = imp.ty.impl_key() {
+                        explicit_impls.insert(key, imp);
+                    }
                 }
             }
         }

From 0acb2d63373576f3cdb5be529b2a66873659f221 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 23:38:08 +0000
Subject: [PATCH 1922/2232] Merge pull request #628 from dtolnay/implkey


Key impls by an enum rather than by Type
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 6b89178..8242b2e 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1336,11 +1336,15 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
     for ty in out.types {
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
         if let Type::RustBox(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_rust_box_extern(out, &out.types.resolve(&inner));
@@ -1350,7 +1354,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vec.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_rust_vec_extern(out, inner);
@@ -1360,7 +1364,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_unique_ptr(out, inner);
@@ -1370,7 +1374,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_shared_ptr(out, inner);
@@ -1380,7 +1384,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_weak_ptr(out, inner);
@@ -1390,7 +1394,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vector.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     out.next_section();
                     write_cxx_vector(out, inner);
@@ -1403,11 +1407,15 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for ty in out.types {
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
         if let Type::RustBox(ptr) = ty {
             if let Type::Ident(inner) = &ptr.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     write_rust_box_impl(out, &out.types.resolve(&inner));
                 }
@@ -1416,7 +1424,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
             if let Type::Ident(inner) = &vec.inner {
                 if Atom::from(&inner.rust).is_none()
                     && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains(ty))
+                        || out.types.explicit_impls.contains_key(&impl_key))
                 {
                     write_rust_vec_impl(out, inner);
                 }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 82cfed3..85f834d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -80,7 +80,11 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
     }
 
     for ty in types {
-        let explicit_impl = types.explicit_impls.get(ty);
+        let impl_key = match ty.impl_key() {
+            Some(impl_key) => impl_key,
+            None => continue,
+        };
+        let explicit_impl = types.explicit_impls.get(&impl_key).copied();
         if let Type::RustBox(ty) = ty {
             if let Type::Ident(ident) = &ty.inner {
                 if Atom::from(&ident.rust).is_none()
@@ -1366,7 +1370,6 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
 }
 
 fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
-    let _ = explicit_impl;
     let name = elem.rust.to_string();
     let prefix = format!("cxxbridge1$std$vector${}$", elem.to_symbol(types));
     let link_size = format!("{}size", prefix);
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 8c16f2d..4fa0335 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,7 +1,6 @@
 use crate::syntax::{
     Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
-use std::borrow::Borrow;
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
@@ -447,9 +446,3 @@ impl PartialEq for Impl {
         negative == negative2 && ty == ty2
     }
 }
-
-impl Borrow<Type> for &Impl {
-    fn borrow(&self) -> &Type {
-        &self.ty
-    }
-}
diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
new file mode 100644
index 0000000..2891485
--- /dev/null
+++ b/syntax/instantiate.rs
@@ -0,0 +1,43 @@
+use crate::syntax::Type;
+use proc_macro2::Ident;
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub enum ImplKey<'a> {
+    RustBox(&'a Ident),
+    RustVec(&'a Ident),
+    UniquePtr(&'a Ident),
+    SharedPtr(&'a Ident),
+    WeakPtr(&'a Ident),
+    CxxVector(&'a Ident),
+}
+
+impl Type {
+    pub(crate) fn impl_key(&self) -> Option<ImplKey> {
+        if let Type::RustBox(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::RustBox(&ident.rust));
+            }
+        } else if let Type::RustVec(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::RustVec(&ident.rust));
+            }
+        } else if let Type::UniquePtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::UniquePtr(&ident.rust));
+            }
+        } else if let Type::SharedPtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::SharedPtr(&ident.rust));
+            }
+        } else if let Type::WeakPtr(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::WeakPtr(&ident.rust));
+            }
+        } else if let Type::CxxVector(ty) = self {
+            if let Type::Ident(ident) = &ty.inner {
+                return Some(ImplKey::CxxVector(&ident.rust));
+            }
+        }
+        None
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 6fe45d3..9a21087 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -11,6 +11,7 @@ pub mod file;
 pub mod ident;
 mod impls;
 mod improper;
+pub mod instantiate;
 pub mod mangle;
 mod names;
 pub mod namespace;
diff --git a/syntax/types.rs b/syntax/types.rs
index 58a3086..4c1fef0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,4 +1,5 @@
 use crate::syntax::improper::ImproperCtype;
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
@@ -18,7 +19,7 @@ pub struct Types<'a> {
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: Set<&'a Impl>,
+    pub explicit_impls: Map<ImplKey<'a>, &'a Impl>,
     pub resolutions: Map<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
@@ -33,7 +34,7 @@ impl<'a> Types<'a> {
         let mut rust = Set::new();
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
-        let mut explicit_impls = Set::new();
+        let mut explicit_impls = Map::new();
         let mut resolutions = Map::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
@@ -160,7 +161,9 @@ impl<'a> Types<'a> {
                 }
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
-                    explicit_impls.insert(imp);
+                    if let Some(key) = imp.ty.impl_key() {
+                        explicit_impls.insert(key, imp);
+                    }
                 }
             }
         }

From c455e97405694858cc839b519e8eec97b76d12ae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 23:38:19 +0000
Subject: [PATCH 1923/2232] Parse generic params on impl block


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4fa0335..fd8162f 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -413,11 +413,13 @@ impl Hash for Impl {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Impl {
             impl_token: _,
+            generics,
             negative,
             ty,
             brace_token: _,
             negative_token: _,
         } = self;
+        generics.hash(state);
         if *negative {
             negative.hash(state);
         }
@@ -431,6 +433,7 @@ impl PartialEq for Impl {
     fn eq(&self, other: &Impl) -> bool {
         let Impl {
             impl_token: _,
+            generics,
             negative,
             ty,
             brace_token: _,
@@ -438,11 +441,12 @@ impl PartialEq for Impl {
         } = self;
         let Impl {
             impl_token: _,
+            generics: generics2,
             negative: negative2,
             ty: ty2,
             brace_token: _,
             negative_token: _,
         } = other;
-        negative == negative2 && ty == ty2
+        generics == generics2 && negative == negative2 && ty == ty2
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9a21087..1dcb55c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -136,6 +136,7 @@ pub struct TypeAlias {
 
 pub struct Impl {
     pub impl_token: Token![impl],
+    pub generics: Lifetimes,
     pub negative: bool,
     pub ty: Type,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 405006c..07fbf4a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -827,6 +827,8 @@ fn parse_extern_type_bounded(
 }
 
 fn parse_impl(imp: ItemImpl) -> Result<Api> {
+    let impl_token = imp.impl_token;
+
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -842,13 +844,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         ));
     }
 
-    let generics = &imp.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
+    if let Some(where_clause) = imp.generics.where_clause {
         return Err(Error::new_spanned(
-            imp,
-            "generic parameters on an impl is not supported",
+            where_clause,
+            "where-clause on an impl is not supported yet",
         ));
     }
+    let mut generics = Lifetimes {
+        lt_token: imp.generics.lt_token,
+        lifetimes: Punctuated::new(),
+        gt_token: imp.generics.gt_token,
+    };
+    for pair in imp.generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(def) if def.bounds.is_empty() => {
+                generics.lifetimes.push_value(def.lifetime);
+                if let Some(punct) = punct {
+                    generics.lifetimes.push_punct(punct);
+                }
+            }
+            _ => {
+                let span = quote!(#impl_token #generics);
+                return Err(Error::new_spanned(
+                    span,
+                    "generic parameter on an impl is not supported yet",
+                ));
+            }
+        }
+    }
 
     let mut negative_token = None;
     let mut self_ty = *imp.self_ty;
@@ -865,13 +889,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         }
     }
 
-    let impl_token = imp.impl_token;
     let negative = negative_token.is_some();
     let ty = parse_type(&self_ty)?;
     let brace_token = imp.brace_token;
 
     Ok(Api::Impl(Impl {
         impl_token,
+        generics,
         negative,
         ty,
         brace_token,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 1c7c5bc..dd5be01 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -192,12 +192,14 @@ impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let Impl {
             impl_token,
+            generics,
             negative: _,
             ty,
             brace_token,
             negative_token,
         } = self;
         impl_token.to_tokens(tokens);
+        generics.to_tokens(tokens);
         negative_token.to_tokens(tokens);
         ty.to_tokens(tokens);
         brace_token.surround(tokens, |_tokens| {});

From 7248f0ee51d199d72e80ea45949760a14b103b5d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Dec 31 2020 23:47:14 +0000
Subject: [PATCH 1924/2232] Merge pull request #627 from dtolnay/impl


Parse generic params on impl block
---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index 4fa0335..fd8162f 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -413,11 +413,13 @@ impl Hash for Impl {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let Impl {
             impl_token: _,
+            generics,
             negative,
             ty,
             brace_token: _,
             negative_token: _,
         } = self;
+        generics.hash(state);
         if *negative {
             negative.hash(state);
         }
@@ -431,6 +433,7 @@ impl PartialEq for Impl {
     fn eq(&self, other: &Impl) -> bool {
         let Impl {
             impl_token: _,
+            generics,
             negative,
             ty,
             brace_token: _,
@@ -438,11 +441,12 @@ impl PartialEq for Impl {
         } = self;
         let Impl {
             impl_token: _,
+            generics: generics2,
             negative: negative2,
             ty: ty2,
             brace_token: _,
             negative_token: _,
         } = other;
-        negative == negative2 && ty == ty2
+        generics == generics2 && negative == negative2 && ty == ty2
     }
 }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9a21087..1dcb55c 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -136,6 +136,7 @@ pub struct TypeAlias {
 
 pub struct Impl {
     pub impl_token: Token![impl],
+    pub generics: Lifetimes,
     pub negative: bool,
     pub ty: Type,
     pub brace_token: Brace,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 405006c..07fbf4a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -827,6 +827,8 @@ fn parse_extern_type_bounded(
 }
 
 fn parse_impl(imp: ItemImpl) -> Result<Api> {
+    let impl_token = imp.impl_token;
+
     if !imp.items.is_empty() {
         let mut span = Group::new(Delimiter::Brace, TokenStream::new());
         span.set_span(imp.brace_token.span);
@@ -842,13 +844,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         ));
     }
 
-    let generics = &imp.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
+    if let Some(where_clause) = imp.generics.where_clause {
         return Err(Error::new_spanned(
-            imp,
-            "generic parameters on an impl is not supported",
+            where_clause,
+            "where-clause on an impl is not supported yet",
         ));
     }
+    let mut generics = Lifetimes {
+        lt_token: imp.generics.lt_token,
+        lifetimes: Punctuated::new(),
+        gt_token: imp.generics.gt_token,
+    };
+    for pair in imp.generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(def) if def.bounds.is_empty() => {
+                generics.lifetimes.push_value(def.lifetime);
+                if let Some(punct) = punct {
+                    generics.lifetimes.push_punct(punct);
+                }
+            }
+            _ => {
+                let span = quote!(#impl_token #generics);
+                return Err(Error::new_spanned(
+                    span,
+                    "generic parameter on an impl is not supported yet",
+                ));
+            }
+        }
+    }
 
     let mut negative_token = None;
     let mut self_ty = *imp.self_ty;
@@ -865,13 +889,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         }
     }
 
-    let impl_token = imp.impl_token;
     let negative = negative_token.is_some();
     let ty = parse_type(&self_ty)?;
     let brace_token = imp.brace_token;
 
     Ok(Api::Impl(Impl {
         impl_token,
+        generics,
         negative,
         ty,
         brace_token,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 1c7c5bc..dd5be01 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -192,12 +192,14 @@ impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let Impl {
             impl_token,
+            generics,
             negative: _,
             ty,
             brace_token,
             negative_token,
         } = self;
         impl_token.to_tokens(tokens);
+        generics.to_tokens(tokens);
         negative_token.to_tokens(tokens);
         ty.to_tokens(tokens);
         brace_token.surround(tokens, |_tokens| {});

From 292cfffe5a3cefc9a60761462206cb526467491f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 00:37:55 +0000
Subject: [PATCH 1925/2232] Downgrade some ordered type checker sets to unordered


---

diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index d74bd66..070a366 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -1,4 +1,4 @@
-use crate::syntax::set::OrderedSet as Set;
+use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{Api, Enum, ExternFn, Pair, RustName, Struct, Type};
 use proc_macro2::Ident;
 use std::collections::BTreeMap as Map;
@@ -19,7 +19,7 @@ pub fn required_trivial_reasons<'a>(
     all: &Set<&'a Type>,
     structs: &Map<&'a Ident, &'a Struct>,
     enums: &Map<&'a Ident, &'a Enum>,
-    cxx: &Set<&'a Ident>,
+    cxx: &UnorderedSet<&'a Ident>,
 ) -> Map<&'a Ident, Vec<TrivialReason<'a>>> {
     let mut required_trivial = Map::new();
 
diff --git a/syntax/types.rs b/syntax/types.rs
index 4c1fef0..87a2992 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,8 +14,8 @@ pub struct Types<'a> {
     pub all: Set<&'a Type>,
     pub structs: Map<&'a Ident, &'a Struct>,
     pub enums: Map<&'a Ident, &'a Enum>,
-    pub cxx: Set<&'a Ident>,
-    pub rust: Set<&'a Ident>,
+    pub cxx: UnorderedSet<&'a Ident>,
+    pub rust: UnorderedSet<&'a Ident>,
     pub aliases: Map<&'a Ident, &'a TypeAlias>,
     pub untrusted: Map<&'a Ident, &'a ExternType>,
     pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
@@ -30,8 +30,8 @@ impl<'a> Types<'a> {
         let mut all = Set::new();
         let mut structs = Map::new();
         let mut enums = Map::new();
-        let mut cxx = Set::new();
-        let mut rust = Set::new();
+        let mut cxx = UnorderedSet::new();
+        let mut rust = UnorderedSet::new();
         let mut aliases = Map::new();
         let mut untrusted = Map::new();
         let mut explicit_impls = Map::new();

From e352c1e140292a75faa7b12b13bc2956f0515a43 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 01:15:56 +0000
Subject: [PATCH 1926/2232] Add wrapper to prevent iteration of unordered maps


---

diff --git a/gen/build/src/cfg.rs b/gen/build/src/cfg.rs
index c15a173..6818bda 100644
--- a/gen/build/src/cfg.rs
+++ b/gen/build/src/cfg.rs
@@ -266,10 +266,10 @@ pub use self::r#impl::Cfg::CFG;
 #[cfg(not(doc))]
 mod r#impl {
     use crate::intern::{intern, InternedString};
+    use crate::syntax::map::UnorderedMap as Map;
     use crate::vec::{self, InternedVec as _};
     use lazy_static::lazy_static;
     use std::cell::RefCell;
-    use std::collections::HashMap;
     use std::fmt::{self, Debug};
     use std::marker::PhantomData;
     use std::ops::{Deref, DerefMut};
@@ -316,7 +316,7 @@ mod r#impl {
         //         cfg: AtomicPtr<super::Cfg>,
         //     }
         //
-        static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
+        static CONST_DEREFS: RefCell<Map<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
     }
 
     #[derive(Eq, PartialEq, Hash)]
diff --git a/gen/build/src/intern.rs b/gen/build/src/intern.rs
index 51bc07c..25b8706 100644
--- a/gen/build/src/intern.rs
+++ b/gen/build/src/intern.rs
@@ -1,5 +1,5 @@
+use crate::syntax::set::UnorderedSet as Set;
 use lazy_static::lazy_static;
-use std::collections::HashSet;
 use std::sync::{Mutex, PoisonError};
 
 #[derive(Copy, Clone, Default)]
@@ -13,7 +13,7 @@ impl InternedString {
 
 pub fn intern(s: &str) -> InternedString {
     lazy_static! {
-        static ref INTERN: Mutex<HashSet<&'static str>> = Mutex::new(HashSet::new());
+        static ref INTERN: Mutex<Set<&'static str>> = Mutex::new(Set::new());
     }
 
     let mut set = INTERN.lock().unwrap_or_else(PoisonError::into_inner);
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index f7d4182..204c89f 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -90,10 +90,10 @@ use crate::error::{Error, Result};
 use crate::gen::error::report;
 use crate::gen::Opt;
 use crate::paths::PathExt;
+use crate::syntax::map::{Entry, UnorderedMap};
 use crate::target::TargetDir;
 use cc::Build;
-use std::collections::btree_map::Entry;
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::BTreeSet;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::io::{self, Write};
@@ -288,7 +288,7 @@ fn make_this_crate(prj: &Project) -> Result<Crate> {
         });
     }
 
-    let mut header_dirs_index = BTreeMap::new();
+    let mut header_dirs_index = UnorderedMap::new();
     let mut used_header_links = BTreeSet::new();
     let mut used_header_prefixes = BTreeSet::new();
     for krate in deps::direct_dependencies() {
diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index d94d36d..c030717 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -1,6 +1,6 @@
+use crate::syntax::map::UnorderedMap as Map;
 use crate::syntax::Api;
 use proc_macro2::Ident;
-use std::collections::HashMap as Map;
 
 pub struct NamespaceEntries<'a> {
     direct: Vec<&'a Api>,
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 8242b2e..d2dbe02 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,6 +3,8 @@ use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::map::UnorderedMap as Map;
+use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
@@ -10,7 +12,6 @@ use crate::syntax::{
     Type, TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
-use std::collections::{HashMap, HashSet};
 
 pub(super) fn gen(apis: &[Api], types: &Types, opt: &Opt, header: bool) -> Vec<u8> {
     let mut out_file = OutFile::new(header, opt, types);
@@ -65,7 +66,7 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
 }
 
 fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
-    let mut methods_for_type = HashMap::new();
+    let mut methods_for_type = Map::new();
     for api in apis {
         if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
             if let Some(receiver) = &efn.sig.receiver {
@@ -77,7 +78,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
-    let mut structs_written = HashSet::new();
+    let mut structs_written = UnorderedSet::new();
     let mut toposorted_structs = out.types.toposorted_structs.iter();
     for api in apis {
         match api {
diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
index 2891485..e9c6f29 100644
--- a/syntax/instantiate.rs
+++ b/syntax/instantiate.rs
@@ -1,7 +1,7 @@
 use crate::syntax::Type;
 use proc_macro2::Ident;
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImplKey<'a> {
     RustBox(&'a Ident),
     RustVec(&'a Ident),
diff --git a/syntax/map.rs b/syntax/map.rs
new file mode 100644
index 0000000..a3b33ed
--- /dev/null
+++ b/syntax/map.rs
@@ -0,0 +1,89 @@
+use std::borrow::Borrow;
+use std::hash::Hash;
+use std::ops::Index;
+
+pub use self::unordered::UnorderedMap;
+pub use std::collections::hash_map::Entry;
+
+mod unordered {
+    use crate::syntax::set::UnorderedSet;
+    use std::borrow::Borrow;
+    use std::collections::hash_map::{Entry, HashMap};
+    use std::hash::Hash;
+
+    // Wrapper prohibits accidentally introducing iteration over the map, which
+    // could lead to nondeterministic generated code.
+    pub struct UnorderedMap<K, V>(HashMap<K, V>);
+
+    impl<K, V> UnorderedMap<K, V> {
+        pub fn new() -> Self {
+            UnorderedMap(HashMap::new())
+        }
+    }
+
+    impl<K, V> UnorderedMap<K, V>
+    where
+        K: Hash + Eq,
+    {
+        pub fn insert(&mut self, key: K, value: V) -> Option<V> {
+            self.0.insert(key, value)
+        }
+
+        pub fn contains_key<Q>(&self, key: &Q) -> bool
+        where
+            K: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.contains_key(key)
+        }
+
+        pub fn get<Q>(&self, key: &Q) -> Option<&V>
+        where
+            K: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.get(key)
+        }
+
+        pub fn entry(&mut self, key: K) -> Entry<K, V> {
+            self.0.entry(key)
+        }
+
+        pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
+        where
+            K: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.0.remove(key)
+        }
+
+        pub fn keys(&self) -> UnorderedSet<K>
+        where
+            K: Copy,
+        {
+            let mut set = UnorderedSet::new();
+            for key in self.0.keys() {
+                set.insert(*key);
+            }
+            set
+        }
+    }
+}
+
+impl<K, V> Default for UnorderedMap<K, V> {
+    fn default() -> Self {
+        UnorderedMap::new()
+    }
+}
+
+impl<Q, K, V> Index<&Q> for UnorderedMap<K, V>
+where
+    K: Borrow<Q> + Hash + Eq,
+    Q: ?Sized + Hash + Eq,
+{
+    type Output = V;
+
+    fn index(&self, key: &Q) -> &V {
+        self.get(key).unwrap()
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 1dcb55c..96169e8 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -13,6 +13,7 @@ mod impls;
 mod improper;
 pub mod instantiate;
 pub mod mangle;
+pub mod map;
 mod names;
 pub mod namespace;
 mod parse;
diff --git a/syntax/set.rs b/syntax/set.rs
index 0df5f87..ca0c43e 100644
--- a/syntax/set.rs
+++ b/syntax/set.rs
@@ -105,6 +105,10 @@ mod unordered {
         {
             self.0.get(value)
         }
+
+        pub fn retain(&mut self, f: impl FnMut(&T) -> bool) {
+            self.0.retain(f);
+        }
     }
 }
 
diff --git a/syntax/toposort.rs b/syntax/toposort.rs
index 876f9ad..8fe55b8 100644
--- a/syntax/toposort.rs
+++ b/syntax/toposort.rs
@@ -1,6 +1,6 @@
+use crate::syntax::map::{Entry, UnorderedMap as Map};
 use crate::syntax::report::Errors;
 use crate::syntax::{Api, Struct, Type, Types};
-use std::collections::btree_map::{BTreeMap as Map, Entry};
 
 enum Mark {
     Visiting,
diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index 070a366..b7ba4f9 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -1,7 +1,7 @@
+use crate::syntax::map::UnorderedMap;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::{Api, Enum, ExternFn, Pair, RustName, Struct, Type};
 use proc_macro2::Ident;
-use std::collections::BTreeMap as Map;
 use std::fmt::{self, Display};
 
 #[derive(Copy, Clone)]
@@ -17,11 +17,11 @@ pub enum TrivialReason<'a> {
 pub fn required_trivial_reasons<'a>(
     apis: &'a [Api],
     all: &Set<&'a Type>,
-    structs: &Map<&'a Ident, &'a Struct>,
-    enums: &Map<&'a Ident, &'a Enum>,
+    structs: &UnorderedMap<&'a Ident, &'a Struct>,
+    enums: &UnorderedMap<&'a Ident, &'a Enum>,
     cxx: &UnorderedSet<&'a Ident>,
-) -> Map<&'a Ident, Vec<TrivialReason<'a>>> {
-    let mut required_trivial = Map::new();
+) -> UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>> {
+    let mut required_trivial = UnorderedMap::new();
 
     let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
         if cxx.contains(&ident.rust)
diff --git a/syntax/types.rs b/syntax/types.rs
index 87a2992..7a45939 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,5 +1,6 @@
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::instantiate::ImplKey;
+use crate::syntax::map::UnorderedMap;
 use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
@@ -8,19 +9,18 @@ use crate::syntax::{
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
-use std::collections::BTreeMap as Map;
 
 pub struct Types<'a> {
     pub all: Set<&'a Type>,
-    pub structs: Map<&'a Ident, &'a Struct>,
-    pub enums: Map<&'a Ident, &'a Enum>,
+    pub structs: UnorderedMap<&'a Ident, &'a Struct>,
+    pub enums: UnorderedMap<&'a Ident, &'a Enum>,
     pub cxx: UnorderedSet<&'a Ident>,
     pub rust: UnorderedSet<&'a Ident>,
-    pub aliases: Map<&'a Ident, &'a TypeAlias>,
-    pub untrusted: Map<&'a Ident, &'a ExternType>,
-    pub required_trivial: Map<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: Map<ImplKey<'a>, &'a Impl>,
-    pub resolutions: Map<&'a Ident, &'a Pair>,
+    pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>,
+    pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>,
+    pub required_trivial: UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>>,
+    pub explicit_impls: UnorderedMap<ImplKey<'a>, &'a Impl>,
+    pub resolutions: UnorderedMap<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
 }
@@ -28,14 +28,14 @@ pub struct Types<'a> {
 impl<'a> Types<'a> {
     pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
         let mut all = Set::new();
-        let mut structs = Map::new();
-        let mut enums = Map::new();
+        let mut structs = UnorderedMap::new();
+        let mut enums = UnorderedMap::new();
         let mut cxx = UnorderedSet::new();
         let mut rust = UnorderedSet::new();
-        let mut aliases = Map::new();
-        let mut untrusted = Map::new();
-        let mut explicit_impls = Map::new();
-        let mut resolutions = Map::new();
+        let mut aliases = UnorderedMap::new();
+        let mut untrusted = UnorderedMap::new();
+        let mut explicit_impls = UnorderedMap::new();
+        let mut resolutions = UnorderedMap::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
 
@@ -192,7 +192,7 @@ impl<'a> Types<'a> {
 
         types.toposorted_structs = toposort::sort(cx, apis, &types);
 
-        let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
+        let mut unresolved_structs = types.structs.keys();
         let mut new_information = true;
         while new_information {
             new_information = false;

From 873b822c54a73b95d905de5b80e35626a7977dd7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 07:39:06 +0000
Subject: [PATCH 1927/2232] Add OrderedMap type


---

diff --git a/syntax/map.rs b/syntax/map.rs
index a3b33ed..f1ea5fc 100644
--- a/syntax/map.rs
+++ b/syntax/map.rs
@@ -1,10 +1,81 @@
 use std::borrow::Borrow;
 use std::hash::Hash;
 use std::ops::Index;
+use std::slice;
 
+pub use self::ordered::OrderedMap;
 pub use self::unordered::UnorderedMap;
 pub use std::collections::hash_map::Entry;
 
+mod ordered {
+    use super::{Entry, Iter, UnorderedMap};
+    use std::borrow::Borrow;
+    use std::hash::Hash;
+    use std::mem;
+
+    pub struct OrderedMap<K, V> {
+        map: UnorderedMap<K, usize>,
+        vec: Vec<(K, V)>,
+    }
+
+    impl<K, V> OrderedMap<K, V> {
+        pub fn new() -> Self {
+            OrderedMap {
+                map: UnorderedMap::new(),
+                vec: Vec::new(),
+            }
+        }
+
+        pub fn iter(&self) -> Iter<K, V> {
+            Iter(self.vec.iter())
+        }
+    }
+
+    impl<K, V> OrderedMap<K, V>
+    where
+        K: Copy + Hash + Eq,
+    {
+        pub fn insert(&mut self, key: K, value: V) -> Option<V> {
+            match self.map.entry(key) {
+                Entry::Occupied(entry) => {
+                    let i = &mut self.vec[*entry.get()];
+                    Some(mem::replace(&mut i.1, value))
+                }
+                Entry::Vacant(entry) => {
+                    entry.insert(self.vec.len());
+                    self.vec.push((key, value));
+                    None
+                }
+            }
+        }
+
+        pub fn contains_key<Q>(&self, key: &Q) -> bool
+        where
+            K: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            self.map.contains_key(key)
+        }
+
+        pub fn get<Q>(&self, key: &Q) -> Option<&V>
+        where
+            K: Borrow<Q>,
+            Q: ?Sized + Hash + Eq,
+        {
+            let i = *self.map.get(key)?;
+            Some(&self.vec[i].1)
+        }
+    }
+
+    impl<'a, K, V> IntoIterator for &'a OrderedMap<K, V> {
+        type Item = (&'a K, &'a V);
+        type IntoIter = Iter<'a, K, V>;
+        fn into_iter(self) -> Self::IntoIter {
+            self.iter()
+        }
+    }
+}
+
 mod unordered {
     use crate::syntax::set::UnorderedSet;
     use std::borrow::Borrow;
@@ -70,6 +141,21 @@ mod unordered {
     }
 }
 
+pub struct Iter<'a, K, V>(slice::Iter<'a, (K, V)>);
+
+impl<'a, K, V> Iterator for Iter<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let (k, v) = self.0.next()?;
+        Some((k, v))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
 impl<K, V> Default for UnorderedMap<K, V> {
     fn default() -> Self {
         UnorderedMap::new()

From bbcd75c0d1b3bf92fd0884726e0945c6bd29016e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 21:04:55 +0000
Subject: [PATCH 1928/2232] Pull in syn 1.0.57 for const Punctuated::new support


---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index d0fbf64..811b261 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -18,7 +18,7 @@ lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 scratch = "1.0"
-syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [dev-dependencies]
 cxx-gen = { version = "0.7", path = "../lib" }
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 7070ede..a8129df 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -20,7 +20,7 @@ clap = "2.33"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index ee067a0..2780187 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -15,7 +15,7 @@ cc = "1.0.49"
 codespan-reporting = "0.9"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
-syn = { version = "1.0.53", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
+syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
 
 [package.metadata.docs.rs]
 targets = ["x86_64-unknown-linux-gnu"]
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9ce375a..5aa2292 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -17,7 +17,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0.4"
-syn = { version = "1.0.53", features = ["full"] }
+syn = { version = "1.0.57", features = ["full"] }
 
 [dev-dependencies]
 cxx = { version = "1.0", path = ".." }
diff --git a/third-party/BUCK b/third-party/BUCK
index e92cd5f..43d94c9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.56/src/**"]),
+    srcs = glob(["vendor/syn-1.0.57/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 88304c6..cda5cdd 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.56/src/**"]),
+    srcs = glob(["vendor/syn-1.0.57/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index cedab32..148af20 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.56"
+version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72"
+checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
 dependencies = [
  "proc-macro2",
  "quote",

From 95bc57fc47dd069a67738cf26007442f38283979 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 21:36:49 +0000
Subject: [PATCH 1929/2232] Remove RustName::to_symbol in favor of explicit resolve


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index d2dbe02..781d8b2 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1315,7 +1315,7 @@ trait ToMangled {
 
 impl ToMangled for RustName {
     fn to_mangled(&self, types: &Types) -> Symbol {
-        self.to_symbol(types)
+        types.resolve(self).to_symbol()
     }
 }
 
@@ -1726,9 +1726,9 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
 }
 
 fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
-    let resolved = out.types.resolve(ident);
-    let inner = resolved.to_fully_qualified();
-    let instance = ident.to_symbol(out.types);
+    let resolve = out.types.resolve(ident);
+    let inner = resolve.to_fully_qualified();
+    let instance = resolve.to_symbol();
 
     out.include.new = true;
     out.include.utility = true;
@@ -1798,9 +1798,9 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
 }
 
 fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
-    let resolved = out.types.resolve(ident);
-    let inner = resolved.to_fully_qualified();
-    let instance = ident.to_symbol(out.types);
+    let resolve = out.types.resolve(ident);
+    let inner = resolve.to_fully_qualified();
+    let instance = resolve.to_symbol();
 
     out.include.new = true;
     out.include.utility = true;
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 85f834d..9cbb2c3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1072,7 +1072,8 @@ fn type_id(name: &Pair) -> TokenStream {
 }
 
 fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
-    let link_prefix = format!("cxxbridge1$box${}$", types.resolve(ident).to_symbol());
+    let resolve = types.resolve(ident);
+    let link_prefix = format!("cxxbridge1$box${}$", resolve.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
     let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
@@ -1105,7 +1106,8 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
 }
 
 fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
-    let link_prefix = format!("cxxbridge1$rust_vec${}$", elem.to_symbol(types));
+    let resolve = types.resolve(elem);
+    let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.to_symbol());
     let link_new = format!("{}new", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
     let link_len = format!("{}len", link_prefix);
@@ -1167,7 +1169,8 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
 
 fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
-    let prefix = format!("cxxbridge1$unique_ptr${}$", ident.to_symbol(types));
+    let resolve = types.resolve(ident);
+    let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_uninit = format!("{}uninit", prefix);
     let link_raw = format!("{}raw", prefix);
@@ -1248,7 +1251,8 @@ fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
 
 fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
-    let prefix = format!("cxxbridge1$shared_ptr${}$", ident.to_symbol(types));
+    let resolve = types.resolve(ident);
+    let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_uninit = format!("{}uninit", prefix);
     let link_clone = format!("{}clone", prefix);
@@ -1315,7 +1319,8 @@ fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
 
 fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
-    let prefix = format!("cxxbridge1$weak_ptr${}$", ident.to_symbol(types));
+    let resolve = types.resolve(ident);
+    let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.to_symbol());
     let link_null = format!("{}null", prefix);
     let link_clone = format!("{}clone", prefix);
     let link_downgrade = format!("{}downgrade", prefix);
@@ -1371,13 +1376,11 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
 
 fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let name = elem.rust.to_string();
-    let prefix = format!("cxxbridge1$std$vector${}$", elem.to_symbol(types));
+    let resolve = types.resolve(elem);
+    let prefix = format!("cxxbridge1$std$vector${}$", resolve.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${}$",
-        elem.to_symbol(types)
-    );
+    let unique_ptr_prefix = format!("cxxbridge1$unique_ptr$std$vector${}$", resolve.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/names.rs b/syntax/names.rs
index 50f6ebd..d818f86 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{Lifetimes, Pair, RustName, Symbol, Types};
+use crate::syntax::{Lifetimes, Pair, RustName, Symbol};
 use proc_macro2::{Ident, Span};
 use std::iter;
 use syn::punctuated::Punctuated;
@@ -35,8 +35,4 @@ impl RustName {
     pub fn span(&self) -> Span {
         self.rust.span()
     }
-
-    pub fn to_symbol(&self, types: &Types) -> Symbol {
-        types.resolve(self).to_symbol()
-    }
 }

From 77a5e758e641c8d05e12c86215b24334cadb5a1c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 22:15:26 +0000
Subject: [PATCH 1930/2232] Rename RustName -> NamedType


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 781d8b2..96592b3 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -8,7 +8,7 @@ use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, RustName, Signature, Struct, Trait,
+    derive, mangle, Api, Enum, ExternFn, ExternType, NamedType, Pair, Signature, Struct, Trait,
     Type, TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
@@ -1284,15 +1284,15 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 #[derive(Copy, Clone)]
 enum UniquePtr<'a> {
-    Ident(&'a RustName),
-    CxxVector(&'a RustName),
+    Ident(&'a NamedType),
+    CxxVector(&'a NamedType),
 }
 
 trait ToTypename {
     fn to_typename(&self, types: &Types) -> String;
 }
 
-impl ToTypename for RustName {
+impl ToTypename for NamedType {
     fn to_typename(&self, types: &Types) -> String {
         types.resolve(self).to_fully_qualified()
     }
@@ -1313,7 +1313,7 @@ trait ToMangled {
     fn to_mangled(&self, types: &Types) -> Symbol;
 }
 
-impl ToMangled for RustName {
+impl ToMangled for NamedType {
     fn to_mangled(&self, types: &Types) -> Symbol {
         types.resolve(self).to_symbol()
     }
@@ -1457,7 +1457,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &RustName) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1531,7 +1531,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1608,7 +1608,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &RustName) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &RustName) {
+fn write_unique_ptr(out: &mut OutFile, ident: &NamedType) {
     let ty = UniquePtr::Ident(ident);
     write_unique_ptr_common(out, ty);
 }
@@ -1725,7 +1725,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
+fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
     let resolve = out.types.resolve(ident);
     let inner = resolve.to_fully_qualified();
     let instance = resolve.to_symbol();
@@ -1797,7 +1797,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
+fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
     let resolve = out.types.resolve(ident);
     let inner = resolve.to_fully_qualified();
     let instance = resolve.to_symbol();
@@ -1856,7 +1856,7 @@ fn write_weak_ptr(out: &mut OutFile, ident: &RustName) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &RustName) {
+fn write_cxx_vector(out: &mut OutFile, element: &NamedType) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 9cbb2c3..4e1b7fa 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -5,7 +5,7 @@ use crate::syntax::file::Module;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, RustName, Signature,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, NamedType, Pair, Signature,
     Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -1071,7 +1071,7 @@ fn type_id(name: &Pair) -> TokenStream {
     }
 }
 
-fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
+fn expand_rust_box(ident: &NamedType, types: &Types) -> TokenStream {
     let resolve = types.resolve(ident);
     let link_prefix = format!("cxxbridge1$box${}$", resolve.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
@@ -1105,7 +1105,7 @@ fn expand_rust_box(ident: &RustName, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
+fn expand_rust_vec(elem: &NamedType, types: &Types) -> TokenStream {
     let resolve = types.resolve(elem);
     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.to_symbol());
     let link_new = format!("{}new", link_prefix);
@@ -1167,7 +1167,11 @@ fn expand_rust_vec(elem: &RustName, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_unique_ptr(
+    ident: &NamedType,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
     let name = ident.rust.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.to_symbol());
@@ -1249,7 +1253,11 @@ fn expand_unique_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
     }
 }
 
-fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_shared_ptr(
+    ident: &NamedType,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
     let name = ident.rust.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.to_symbol());
@@ -1317,7 +1325,7 @@ fn expand_shared_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Imp
     }
 }
 
-fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let name = ident.rust.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.to_symbol());
@@ -1374,7 +1382,7 @@ fn expand_weak_ptr(ident: &RustName, types: &Types, explicit_impl: Option<&Impl>
     }
 }
 
-fn expand_cxx_vector(elem: &RustName, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
+fn expand_cxx_vector(elem: &NamedType, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
     let name = elem.rust.to_string();
     let resolve = types.resolve(elem);
     let prefix = format!("cxxbridge1$std$vector${}$", resolve.to_symbol());
diff --git a/syntax/check.rs b/syntax/check.rs
index 42e92f4..44be4dc 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,8 +1,8 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
-    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref,
-    RustName, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Receiver,
+    Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
@@ -61,7 +61,7 @@ impl Check<'_> {
     }
 }
 
-fn check_type_ident(cx: &mut Check, name: &RustName) {
+fn check_type_ident(cx: &mut Check, name: &NamedType) {
     let ident = &name.rust;
     if Atom::from(ident).is_none()
         && !cx.types.structs.contains_key(ident)
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 96169e8..3a77b82 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -176,7 +176,7 @@ pub struct Receiver {
     pub lifetime: Option<Lifetime>,
     pub mutable: bool,
     pub var: Token![self],
-    pub ty: RustName,
+    pub ty: NamedType,
     pub shorthand: bool,
     pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>,
     pub mutability: Option<Token![mut]>,
@@ -191,7 +191,7 @@ pub struct Variant {
 }
 
 pub enum Type {
-    Ident(RustName),
+    Ident(NamedType),
     RustBox(Box<Ty1>),
     RustVec(Box<Ty1>),
     UniquePtr(Box<Ty1>),
@@ -258,7 +258,7 @@ pub struct Pair {
 // Wrapper for a type which needs to be resolved before it can be printed in
 // C++.
 #[derive(PartialEq, Eq, Hash)]
-pub struct RustName {
+pub struct NamedType {
     pub rust: Ident,
     pub generics: Lifetimes,
 }
diff --git a/syntax/names.rs b/syntax/names.rs
index d818f86..c4cbcff 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,4 +1,4 @@
-use crate::syntax::{Lifetimes, Pair, RustName, Symbol};
+use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
 use proc_macro2::{Ident, Span};
 use std::iter;
 use syn::punctuated::Punctuated;
@@ -22,14 +22,14 @@ impl Pair {
     }
 }
 
-impl RustName {
+impl NamedType {
     pub fn new(rust: Ident) -> Self {
         let generics = Lifetimes {
             lt_token: None,
             lifetimes: Punctuated::new(),
             gt_token: None,
         };
-        RustName { rust, generics }
+        NamedType { rust, generics }
     }
 
     pub fn span(&self) -> Span {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 07fbf4a..b36bcbf 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,7 +5,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Lifetimes, Namespace, Pair, Receiver, Ref, RustName, Signature, SliceRef, Struct, Ty1,
+    Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef, Struct, Ty1,
     Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
@@ -201,7 +201,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
 
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
-    let repr_type = Type::Ident(RustName::new(repr_ident));
+    let repr_type = Type::Ident(NamedType::new(repr_ident));
 
     Ok(Api::Enum(Enum {
         doc,
@@ -519,7 +519,7 @@ fn parse_extern_fn(
                         lifetime: lifetime.clone(),
                         mutable: arg.mutability.is_some(),
                         var: arg.self_token,
-                        ty: RustName::new(Ident::new("Self", arg.self_token.span)),
+                        ty: NamedType::new(Ident::new("Self", arg.self_token.span)),
                         shorthand: true,
                         pin_tokens: None,
                         mutability: arg.mutability,
@@ -1007,7 +1007,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
         let segment = &path.segments[0];
         let ident = segment.ident.clone();
         match &segment.arguments {
-            PathArguments::None => return Ok(Type::Ident(RustName::new(ident))),
+            PathArguments::None => return Ok(Type::Ident(NamedType::new(ident))),
             PathArguments::AngleBracketed(generic) => {
                 if ident == "UniquePtr" && generic.args.len() == 1 {
                     if let GenericArgument::Type(arg) = &generic.args[0] {
@@ -1096,7 +1096,7 @@ fn parse_type_path(ty: &TypePath) -> Result<Type> {
                         }
                     }
                     if only_lifetimes {
-                        return Ok(Type::Ident(RustName {
+                        return Ok(Type::Ident(NamedType {
                             rust: ident,
                             generics: Lifetimes {
                                 lt_token: Some(generic.lt_token),
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index dd5be01..df0b702 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,6 +1,6 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, Receiver, Ref, RustName,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Receiver, Ref,
     Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
@@ -256,9 +256,9 @@ impl ToTokens for Signature {
     }
 }
 
-impl ToTokens for RustName {
+impl ToTokens for NamedType {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        let RustName { rust, generics } = self;
+        let NamedType { rust, generics } = self;
         rust.to_tokens(tokens);
         generics.to_tokens(tokens);
     }
diff --git a/syntax/trivial.rs b/syntax/trivial.rs
index b7ba4f9..fe95e2b 100644
--- a/syntax/trivial.rs
+++ b/syntax/trivial.rs
@@ -1,6 +1,6 @@
 use crate::syntax::map::UnorderedMap;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
-use crate::syntax::{Api, Enum, ExternFn, Pair, RustName, Struct, Type};
+use crate::syntax::{Api, Enum, ExternFn, NamedType, Pair, Struct, Type};
 use proc_macro2::Ident;
 use std::fmt::{self, Display};
 
@@ -23,7 +23,7 @@ pub fn required_trivial_reasons<'a>(
 ) -> UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>> {
     let mut required_trivial = UnorderedMap::new();
 
-    let mut insist_extern_types_are_trivial = |ident: &'a RustName, reason| {
+    let mut insist_extern_types_are_trivial = |ident: &'a NamedType, reason| {
         if cxx.contains(&ident.rust)
             && !structs.contains_key(&ident.rust)
             && !enums.contains_key(&ident.rust)
diff --git a/syntax/types.rs b/syntax/types.rs
index 7a45939..54cd8f0 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -5,7 +5,7 @@ use crate::syntax::report::Errors;
 use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    toposort, Api, Enum, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
+    toposort, Api, Enum, ExternType, Impl, NamedType, Pair, Struct, Type, TypeAlias,
 };
 use proc_macro2::Ident;
 use quote::ToTokens;
@@ -240,7 +240,7 @@ impl<'a> Types<'a> {
         }
     }
 
-    pub fn resolve(&self, ident: &RustName) -> &Pair {
+    pub fn resolve(&self, ident: &NamedType) -> &Pair {
         self.resolutions
             .get(&ident.rust)
             .expect("Unable to resolve type")

From b1f0b9be9377e8f6a8fbade9820e7ab028d121ec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 22:26:26 +0000
Subject: [PATCH 1931/2232] Incorporate explicit impl spans into Box and Vec instantiation


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 4e1b7fa..90b835a 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -90,7 +90,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
                 if Atom::from(&ident.rust).is_none()
                     && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
-                    hidden.extend(expand_rust_box(ident, types));
+                    hidden.extend(expand_rust_box(ident, types, explicit_impl));
                 }
             }
         } else if let Type::RustVec(ty) = ty {
@@ -98,7 +98,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
                 if Atom::from(&ident.rust).is_none()
                     && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
                 {
-                    hidden.extend(expand_rust_vec(ident, types));
+                    hidden.extend(expand_rust_vec(ident, types, explicit_impl));
                 }
             }
         } else if let Type::UniquePtr(ptr) = ty {
@@ -1071,7 +1071,7 @@ fn type_id(name: &Pair) -> TokenStream {
     }
 }
 
-fn expand_rust_box(ident: &NamedType, types: &Types) -> TokenStream {
+fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(ident);
     let link_prefix = format!("cxxbridge1$box${}$", resolve.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
@@ -1083,10 +1083,14 @@ fn expand_rust_box(ident: &NamedType, types: &Types) -> TokenStream {
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
-    let span = ident.span();
-    quote_spanned! {span=>
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
         #[doc(hidden)]
-        unsafe impl ::cxx::private::ImplBox for #ident {}
+        #unsafe_token impl ::cxx::private::ImplBox for #ident {}
         #[doc(hidden)]
         #[export_name = #link_alloc]
         unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
@@ -1105,7 +1109,7 @@ fn expand_rust_box(ident: &NamedType, types: &Types) -> TokenStream {
     }
 }
 
-fn expand_rust_vec(elem: &NamedType, types: &Types) -> TokenStream {
+fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
     let resolve = types.resolve(elem);
     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.to_symbol());
     let link_new = format!("{}new", link_prefix);
@@ -1125,10 +1129,14 @@ fn expand_rust_vec(elem: &NamedType, types: &Types) -> TokenStream {
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
-    let span = elem.span();
-    quote_spanned! {span=>
+    let begin_span =
+        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let unsafe_token = format_ident!("unsafe", span = begin_span);
+
+    quote_spanned! {end_span=>
         #[doc(hidden)]
-        unsafe impl ::cxx::private::ImplVec for #elem {}
+        #unsafe_token impl ::cxx::private::ImplVec for #elem {}
         #[doc(hidden)]
         #[export_name = #link_new]
         unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {

From 3abed4794a0bdcd649a27700a1236289f850e916 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 22:28:38 +0000
Subject: [PATCH 1932/2232] Generate all explicit and implicit impls based on one map


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 96592b3..6679076 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,13 +3,14 @@ use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::UnorderedMap as Map;
 use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    derive, mangle, Api, Enum, ExternFn, ExternType, NamedType, Pair, Signature, Struct, Trait,
-    Type, TypeAlias, Types, Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, Signature, Struct, Trait, Type,
+    TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
 
@@ -1284,15 +1285,15 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 #[derive(Copy, Clone)]
 enum UniquePtr<'a> {
-    Ident(&'a NamedType),
-    CxxVector(&'a NamedType),
+    Ident(&'a Ident),
+    CxxVector(&'a Ident),
 }
 
 trait ToTypename {
     fn to_typename(&self, types: &Types) -> String;
 }
 
-impl ToTypename for NamedType {
+impl ToTypename for Ident {
     fn to_typename(&self, types: &Types) -> String {
         types.resolve(self).to_fully_qualified()
     }
@@ -1313,7 +1314,7 @@ trait ToMangled {
     fn to_mangled(&self, types: &Types) -> Symbol;
 }
 
-impl ToMangled for NamedType {
+impl ToMangled for Ident {
     fn to_mangled(&self, types: &Types) -> Symbol {
         types.resolve(self).to_symbol()
     }
@@ -1336,109 +1337,36 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.next_section();
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        if let Type::RustBox(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_box_extern(out, &out.types.resolve(&inner));
-                }
-            }
-        } else if let Type::RustVec(vec) = ty {
-            if let Type::Ident(inner) = &vec.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_vec_extern(out, inner);
-                }
-            }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_unique_ptr(out, inner);
-                }
-            }
-        } else if let Type::SharedPtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_shared_ptr(out, inner);
-                }
-            }
-        } else if let Type::WeakPtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_weak_ptr(out, inner);
-                }
-            }
-        } else if let Type::CxxVector(vector) = ty {
-            if let Type::Ident(inner) = &vector.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_cxx_vector(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        out.next_section();
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
+            ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
+            ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
+            ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
+            ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
         }
     }
     out.end_block(Block::ExternC);
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        if let Type::RustBox(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    write_rust_box_impl(out, &out.types.resolve(&inner));
-                }
-            }
-        } else if let Type::RustVec(vec) = ty {
-            if let Type::Ident(inner) = &vec.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    write_rust_vec_impl(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
+            _ => {}
         }
     }
     out.end_block(Block::InlineNamespace("cxxbridge1"));
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+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();
 
     writeln!(
         out,
@@ -1457,7 +1385,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1500,9 +1428,10 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
     );
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+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();
 
     writeln!(out, "template <>");
     begin_function_definition(out);
@@ -1531,7 +1460,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1608,7 +1537,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &NamedType) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     let ty = UniquePtr::Ident(ident);
     write_unique_ptr_common(out, ty);
 }
@@ -1626,17 +1555,16 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         UniquePtr::Ident(ident) => {
-            out.types.structs.contains_key(&ident.rust)
-                || out.types.enums.contains_key(&ident.rust)
-                || out.types.aliases.contains_key(&ident.rust)
+            out.types.structs.contains_key(ident)
+                || out.types.enums.contains_key(ident)
+                || out.types.aliases.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
 
     let conditional_delete = match ty {
         UniquePtr::Ident(ident) => {
-            !out.types.structs.contains_key(&ident.rust)
-                && !out.types.enums.contains_key(&ident.rust)
+            !out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
@@ -1725,7 +1653,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
+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();
@@ -1737,9 +1665,9 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
     // know at code generation time, so we generate both C++ and Rust side
     // bindings for a "new" method anyway. But the Rust code can't be called for
     // Opaque types because the 'new' method is not implemented.
-    let can_construct_from_value = out.types.structs.contains_key(&ident.rust)
-        || out.types.enums.contains_key(&ident.rust)
-        || out.types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = out.types.structs.contains_key(ident)
+        || out.types.enums.contains_key(ident)
+        || out.types.aliases.contains_key(ident);
 
     writeln!(
         out,
@@ -1797,7 +1725,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
+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();
@@ -1856,7 +1784,7 @@ fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &NamedType) {
+fn write_cxx_vector(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 90b835a..40ed5e2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,13 @@
 use crate::derive;
-use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, NamedType, Pair, Signature,
-    Struct, Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, Signature, Struct,
+    Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -79,62 +80,25 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         }
     }
 
-    for ty in types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        let explicit_impl = types.explicit_impls.get(&impl_key).copied();
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_box(ident, types, explicit_impl));
-                }
+    for (impl_key, &explicit_impl) in &types.impls {
+        match impl_key {
+            ImplKey::RustBox(ident) => {
+                hidden.extend(expand_rust_box(ident, types, explicit_impl));
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_vec(ident, types, explicit_impl));
-                }
+            ImplKey::RustVec(ident) => {
+                hidden.extend(expand_rust_vec(ident, types, explicit_impl));
             }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::UniquePtr(ident) => {
+                expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::SharedPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::SharedPtr(ident) => {
+                expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::WeakPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::WeakPtr(ident) => {
+                expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    // Generate impl for CxxVector<T> if T is a struct or opaque
-                    // C++ type. Impl for primitives is already provided by cxx
-                    // crate.
-                    expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
-                }
+            ImplKey::CxxVector(ident) => {
+                expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
             }
         }
     }
@@ -1071,14 +1035,14 @@ fn type_id(name: &Pair) -> TokenStream {
     }
 }
 
-fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+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_alloc = format!("{}alloc", link_prefix);
     let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
-    let local_prefix = format_ident!("{}__box_", &ident.rust);
+    let local_prefix = format_ident!("{}__box_", ident);
     let local_alloc = format_ident!("{}alloc", local_prefix);
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
@@ -1109,7 +1073,7 @@ fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl
     }
 }
 
-fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+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_new = format!("{}new", link_prefix);
@@ -1120,7 +1084,7 @@ fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", elem.rust);
+    let local_prefix = format_ident!("{}__vec_", elem);
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
@@ -1175,12 +1139,8 @@ fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>
     }
 }
 
-fn expand_unique_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1190,9 +1150,9 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             fn __new(value: Self) -> *mut ::std::ffi::c_void {
@@ -1261,12 +1221,8 @@ fn expand_unique_ptr(
     }
 }
 
-fn expand_shared_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1275,9 +1231,9 @@ fn expand_shared_ptr(
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
@@ -1333,8 +1289,8 @@ fn expand_shared_ptr(
     }
 }
 
-fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1390,8 +1346,8 @@ fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl
     }
 }
 
-fn expand_cxx_vector(elem: &NamedType, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
-    let name = elem.rust.to_string();
+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 link_size = format!("{}size", prefix);
diff --git a/syntax/map.rs b/syntax/map.rs
index f1ea5fc..4873409 100644
--- a/syntax/map.rs
+++ b/syntax/map.rs
@@ -29,6 +29,10 @@ mod ordered {
         pub fn iter(&self) -> Iter<K, V> {
             Iter(self.vec.iter())
         }
+
+        pub fn keys(&self) -> impl Iterator<Item = &K> {
+            self.vec.iter().map(|(k, _v)| k)
+        }
     }
 
     impl<K, V> OrderedMap<K, V>
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3a77b82..4298995 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@ mod parse;
 mod pod;
 pub mod qualified;
 pub mod report;
+mod resolve;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
new file mode 100644
index 0000000..5bb1535
--- /dev/null
+++ b/syntax/resolve.rs
@@ -0,0 +1,26 @@
+use crate::syntax::{NamedType, Pair, Types};
+use proc_macro2::Ident;
+
+impl<'a> Types<'a> {
+    pub fn resolve(&self, ident: &impl UnresolvedName) -> &Pair {
+        self.resolutions
+            .get(ident.ident())
+            .expect("Unable to resolve type")
+    }
+}
+
+pub trait UnresolvedName {
+    fn ident(&self) -> &Ident;
+}
+
+impl UnresolvedName for Ident {
+    fn ident(&self) -> &Ident {
+        self
+    }
+}
+
+impl UnresolvedName for NamedType {
+    fn ident(&self) -> &Ident {
+        &self.rust
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 54cd8f0..0eb4293 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,17 +1,15 @@
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::instantiate::ImplKey;
-use crate::syntax::map::UnorderedMap;
+use crate::syntax::map::{OrderedMap, UnorderedMap};
 use crate::syntax::report::Errors;
-use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
+use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
-use crate::syntax::{
-    toposort, Api, Enum, ExternType, Impl, NamedType, Pair, Struct, Type, TypeAlias,
-};
+use crate::syntax::{toposort, Api, Atom, Enum, ExternType, Impl, Pair, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 
 pub struct Types<'a> {
-    pub all: Set<&'a Type>,
+    pub all: OrderedSet<&'a Type>,
     pub structs: UnorderedMap<&'a Ident, &'a Struct>,
     pub enums: UnorderedMap<&'a Ident, &'a Enum>,
     pub cxx: UnorderedSet<&'a Ident>,
@@ -19,7 +17,7 @@ pub struct Types<'a> {
     pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>,
     pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>,
     pub required_trivial: UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: UnorderedMap<ImplKey<'a>, &'a Impl>,
+    pub impls: OrderedMap<ImplKey<'a>, Option<&'a Impl>>,
     pub resolutions: UnorderedMap<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
@@ -27,19 +25,19 @@ pub struct Types<'a> {
 
 impl<'a> Types<'a> {
     pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
-        let mut all = Set::new();
+        let mut all = OrderedSet::new();
         let mut structs = UnorderedMap::new();
         let mut enums = UnorderedMap::new();
         let mut cxx = UnorderedSet::new();
         let mut rust = UnorderedSet::new();
         let mut aliases = UnorderedMap::new();
         let mut untrusted = UnorderedMap::new();
-        let mut explicit_impls = UnorderedMap::new();
+        let mut impls = OrderedMap::new();
         let mut resolutions = UnorderedMap::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
 
-        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
+        fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
@@ -162,12 +160,32 @@ impl<'a> Types<'a> {
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
                     if let Some(key) = imp.ty.impl_key() {
-                        explicit_impls.insert(key, imp);
+                        impls.insert(key, Some(imp));
                     }
                 }
             }
         }
 
+        for ty in &all {
+            let impl_key = match ty.impl_key() {
+                Some(impl_key) => impl_key,
+                None => continue,
+            };
+            let implicit_impl = match impl_key {
+                ImplKey::RustBox(ident)
+                | ImplKey::RustVec(ident)
+                | ImplKey::UniquePtr(ident)
+                | ImplKey::SharedPtr(ident)
+                | ImplKey::WeakPtr(ident)
+                | ImplKey::CxxVector(ident) => {
+                    Atom::from(ident).is_none() && !aliases.contains_key(ident)
+                }
+            };
+            if implicit_impl && !impls.contains_key(&impl_key) {
+                impls.insert(impl_key, None);
+            }
+        }
+
         // All these APIs may contain types passed by value. We need to ensure
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
@@ -184,7 +202,7 @@ impl<'a> Types<'a> {
             aliases,
             untrusted,
             required_trivial,
-            explicit_impls,
+            impls,
             resolutions,
             struct_improper_ctypes,
             toposorted_structs,
@@ -239,12 +257,6 @@ impl<'a> Types<'a> {
             ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
         }
     }
-
-    pub fn resolve(&self, ident: &NamedType) -> &Pair {
-        self.resolutions
-            .get(&ident.rust)
-            .expect("Unable to resolve type")
-    }
 }
 
 impl<'t, 'a> IntoIterator for &'t Types<'a> {

From 5be7c81f4038381f91d467035035be29cc567d28 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 22:43:01 +0000
Subject: [PATCH 1933/2232] Merge pull request #630 from dtolnay/impls


Generate all explicit and implicit impls based on one map
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 96592b3..6679076 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,13 +3,14 @@ use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::UnorderedMap as Map;
 use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
-    derive, mangle, Api, Enum, ExternFn, ExternType, NamedType, Pair, Signature, Struct, Trait,
-    Type, TypeAlias, Types, Var,
+    derive, mangle, Api, Enum, ExternFn, ExternType, Pair, Signature, Struct, Trait, Type,
+    TypeAlias, Types, Var,
 };
 use proc_macro2::Ident;
 
@@ -1284,15 +1285,15 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
 
 #[derive(Copy, Clone)]
 enum UniquePtr<'a> {
-    Ident(&'a NamedType),
-    CxxVector(&'a NamedType),
+    Ident(&'a Ident),
+    CxxVector(&'a Ident),
 }
 
 trait ToTypename {
     fn to_typename(&self, types: &Types) -> String;
 }
 
-impl ToTypename for NamedType {
+impl ToTypename for Ident {
     fn to_typename(&self, types: &Types) -> String {
         types.resolve(self).to_fully_qualified()
     }
@@ -1313,7 +1314,7 @@ trait ToMangled {
     fn to_mangled(&self, types: &Types) -> Symbol;
 }
 
-impl ToMangled for NamedType {
+impl ToMangled for Ident {
     fn to_mangled(&self, types: &Types) -> Symbol {
         types.resolve(self).to_symbol()
     }
@@ -1336,109 +1337,36 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.next_section();
     out.set_namespace(Default::default());
     out.begin_block(Block::ExternC);
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        if let Type::RustBox(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_box_extern(out, &out.types.resolve(&inner));
-                }
-            }
-        } else if let Type::RustVec(vec) = ty {
-            if let Type::Ident(inner) = &vec.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_rust_vec_extern(out, inner);
-                }
-            }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_unique_ptr(out, inner);
-                }
-            }
-        } else if let Type::SharedPtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_shared_ptr(out, inner);
-                }
-            }
-        } else if let Type::WeakPtr(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_weak_ptr(out, inner);
-                }
-            }
-        } else if let Type::CxxVector(vector) = ty {
-            if let Type::Ident(inner) = &vector.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    out.next_section();
-                    write_cxx_vector(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        out.next_section();
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
+            ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
+            ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
+            ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
+            ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
         }
     }
     out.end_block(Block::ExternC);
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    for ty in out.types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        if let Type::RustBox(ptr) = ty {
-            if let Type::Ident(inner) = &ptr.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    write_rust_box_impl(out, &out.types.resolve(&inner));
-                }
-            }
-        } else if let Type::RustVec(vec) = ty {
-            if let Type::Ident(inner) = &vec.inner {
-                if Atom::from(&inner.rust).is_none()
-                    && (!out.types.aliases.contains_key(&inner.rust)
-                        || out.types.explicit_impls.contains_key(&impl_key))
-                {
-                    write_rust_vec_impl(out, inner);
-                }
-            }
+    for impl_key in out.types.impls.keys() {
+        match impl_key {
+            ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
+            ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
+            _ => {}
         }
     }
     out.end_block(Block::InlineNamespace("cxxbridge1"));
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+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();
 
     writeln!(
         out,
@@ -1457,7 +1385,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Pair) {
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1500,9 +1428,10 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &NamedType) {
     );
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
-    let inner = ident.to_fully_qualified();
-    let instance = ident.to_symbol();
+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();
 
     writeln!(out, "template <>");
     begin_function_definition(out);
@@ -1531,7 +1460,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Pair) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
+fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1608,7 +1537,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &NamedType) {
+fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
     let ty = UniquePtr::Ident(ident);
     write_unique_ptr_common(out, ty);
 }
@@ -1626,17 +1555,16 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
         // bindings for a "new" method anyway. But the Rust code can't be called
         // for Opaque types because the 'new' method is not implemented.
         UniquePtr::Ident(ident) => {
-            out.types.structs.contains_key(&ident.rust)
-                || out.types.enums.contains_key(&ident.rust)
-                || out.types.aliases.contains_key(&ident.rust)
+            out.types.structs.contains_key(ident)
+                || out.types.enums.contains_key(ident)
+                || out.types.aliases.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
 
     let conditional_delete = match ty {
         UniquePtr::Ident(ident) => {
-            !out.types.structs.contains_key(&ident.rust)
-                && !out.types.enums.contains_key(&ident.rust)
+            !out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident)
         }
         UniquePtr::CxxVector(_) => false,
     };
@@ -1725,7 +1653,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
+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();
@@ -1737,9 +1665,9 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
     // know at code generation time, so we generate both C++ and Rust side
     // bindings for a "new" method anyway. But the Rust code can't be called for
     // Opaque types because the 'new' method is not implemented.
-    let can_construct_from_value = out.types.structs.contains_key(&ident.rust)
-        || out.types.enums.contains_key(&ident.rust)
-        || out.types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = out.types.structs.contains_key(ident)
+        || out.types.enums.contains_key(ident)
+        || out.types.aliases.contains_key(ident);
 
     writeln!(
         out,
@@ -1797,7 +1725,7 @@ fn write_shared_ptr(out: &mut OutFile, ident: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
+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();
@@ -1856,7 +1784,7 @@ fn write_weak_ptr(out: &mut OutFile, ident: &NamedType) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &NamedType) {
+fn write_cxx_vector(out: &mut OutFile, element: &Ident) {
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 90b835a..40ed5e2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,12 +1,13 @@
 use crate::derive;
-use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
+use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, NamedType, Pair, Signature,
-    Struct, Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, Signature, Struct,
+    Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -79,62 +80,25 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         }
     }
 
-    for ty in types {
-        let impl_key = match ty.impl_key() {
-            Some(impl_key) => impl_key,
-            None => continue,
-        };
-        let explicit_impl = types.explicit_impls.get(&impl_key).copied();
-        if let Type::RustBox(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_box(ident, types, explicit_impl));
-                }
+    for (impl_key, &explicit_impl) in &types.impls {
+        match impl_key {
+            ImplKey::RustBox(ident) => {
+                hidden.extend(expand_rust_box(ident, types, explicit_impl));
             }
-        } else if let Type::RustVec(ty) = ty {
-            if let Type::Ident(ident) = &ty.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    hidden.extend(expand_rust_vec(ident, types, explicit_impl));
-                }
+            ImplKey::RustVec(ident) => {
+                hidden.extend(expand_rust_vec(ident, types, explicit_impl));
             }
-        } else if let Type::UniquePtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::UniquePtr(ident) => {
+                expanded.extend(expand_unique_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::SharedPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::SharedPtr(ident) => {
+                expanded.extend(expand_shared_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::WeakPtr(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
-                }
+            ImplKey::WeakPtr(ident) => {
+                expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
             }
-        } else if let Type::CxxVector(ptr) = ty {
-            if let Type::Ident(ident) = &ptr.inner {
-                if Atom::from(&ident.rust).is_none()
-                    && (explicit_impl.is_some() || !types.aliases.contains_key(&ident.rust))
-                {
-                    // Generate impl for CxxVector<T> if T is a struct or opaque
-                    // C++ type. Impl for primitives is already provided by cxx
-                    // crate.
-                    expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
-                }
+            ImplKey::CxxVector(ident) => {
+                expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
             }
         }
     }
@@ -1071,14 +1035,14 @@ fn type_id(name: &Pair) -> TokenStream {
     }
 }
 
-fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+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_alloc = format!("{}alloc", link_prefix);
     let link_dealloc = format!("{}dealloc", link_prefix);
     let link_drop = format!("{}drop", link_prefix);
 
-    let local_prefix = format_ident!("{}__box_", &ident.rust);
+    let local_prefix = format_ident!("{}__box_", ident);
     let local_alloc = format_ident!("{}alloc", local_prefix);
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
@@ -1109,7 +1073,7 @@ fn expand_rust_box(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl
     }
 }
 
-fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+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_new = format!("{}new", link_prefix);
@@ -1120,7 +1084,7 @@ fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>
     let link_reserve_total = format!("{}reserve_total", link_prefix);
     let link_set_len = format!("{}set_len", link_prefix);
 
-    let local_prefix = format_ident!("{}__vec_", elem.rust);
+    let local_prefix = format_ident!("{}__vec_", elem);
     let local_new = format_ident!("{}new", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
     let local_len = format_ident!("{}len", local_prefix);
@@ -1175,12 +1139,8 @@ fn expand_rust_vec(elem: &NamedType, types: &Types, explicit_impl: Option<&Impl>
     }
 }
 
-fn expand_unique_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1190,9 +1150,9 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             fn __new(value: Self) -> *mut ::std::ffi::c_void {
@@ -1261,12 +1221,8 @@ fn expand_unique_ptr(
     }
 }
 
-fn expand_shared_ptr(
-    ident: &NamedType,
-    types: &Types,
-    explicit_impl: Option<&Impl>,
-) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1275,9 +1231,9 @@ fn expand_shared_ptr(
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let can_construct_from_value = types.structs.contains_key(&ident.rust)
-        || types.enums.contains_key(&ident.rust)
-        || types.aliases.contains_key(&ident.rust);
+    let can_construct_from_value = types.structs.contains_key(ident)
+        || types.enums.contains_key(ident)
+        || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
             unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
@@ -1333,8 +1289,8 @@ fn expand_shared_ptr(
     }
 }
 
-fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
-    let name = ident.rust.to_string();
+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 link_null = format!("{}null", prefix);
@@ -1390,8 +1346,8 @@ fn expand_weak_ptr(ident: &NamedType, types: &Types, explicit_impl: Option<&Impl
     }
 }
 
-fn expand_cxx_vector(elem: &NamedType, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
-    let name = elem.rust.to_string();
+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 link_size = format!("{}size", prefix);
diff --git a/syntax/map.rs b/syntax/map.rs
index f1ea5fc..4873409 100644
--- a/syntax/map.rs
+++ b/syntax/map.rs
@@ -29,6 +29,10 @@ mod ordered {
         pub fn iter(&self) -> Iter<K, V> {
             Iter(self.vec.iter())
         }
+
+        pub fn keys(&self) -> impl Iterator<Item = &K> {
+            self.vec.iter().map(|(k, _v)| k)
+        }
     }
 
     impl<K, V> OrderedMap<K, V>
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3a77b82..4298995 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,6 +20,7 @@ mod parse;
 mod pod;
 pub mod qualified;
 pub mod report;
+mod resolve;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
new file mode 100644
index 0000000..5bb1535
--- /dev/null
+++ b/syntax/resolve.rs
@@ -0,0 +1,26 @@
+use crate::syntax::{NamedType, Pair, Types};
+use proc_macro2::Ident;
+
+impl<'a> Types<'a> {
+    pub fn resolve(&self, ident: &impl UnresolvedName) -> &Pair {
+        self.resolutions
+            .get(ident.ident())
+            .expect("Unable to resolve type")
+    }
+}
+
+pub trait UnresolvedName {
+    fn ident(&self) -> &Ident;
+}
+
+impl UnresolvedName for Ident {
+    fn ident(&self) -> &Ident {
+        self
+    }
+}
+
+impl UnresolvedName for NamedType {
+    fn ident(&self) -> &Ident {
+        &self.rust
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 54cd8f0..0eb4293 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,17 +1,15 @@
 use crate::syntax::improper::ImproperCtype;
 use crate::syntax::instantiate::ImplKey;
-use crate::syntax::map::UnorderedMap;
+use crate::syntax::map::{OrderedMap, UnorderedMap};
 use crate::syntax::report::Errors;
-use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
+use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::trivial::{self, TrivialReason};
-use crate::syntax::{
-    toposort, Api, Enum, ExternType, Impl, NamedType, Pair, Struct, Type, TypeAlias,
-};
+use crate::syntax::{toposort, Api, Atom, Enum, ExternType, Impl, Pair, Struct, Type, TypeAlias};
 use proc_macro2::Ident;
 use quote::ToTokens;
 
 pub struct Types<'a> {
-    pub all: Set<&'a Type>,
+    pub all: OrderedSet<&'a Type>,
     pub structs: UnorderedMap<&'a Ident, &'a Struct>,
     pub enums: UnorderedMap<&'a Ident, &'a Enum>,
     pub cxx: UnorderedSet<&'a Ident>,
@@ -19,7 +17,7 @@ pub struct Types<'a> {
     pub aliases: UnorderedMap<&'a Ident, &'a TypeAlias>,
     pub untrusted: UnorderedMap<&'a Ident, &'a ExternType>,
     pub required_trivial: UnorderedMap<&'a Ident, Vec<TrivialReason<'a>>>,
-    pub explicit_impls: UnorderedMap<ImplKey<'a>, &'a Impl>,
+    pub impls: OrderedMap<ImplKey<'a>, Option<&'a Impl>>,
     pub resolutions: UnorderedMap<&'a Ident, &'a Pair>,
     pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
     pub toposorted_structs: Vec<&'a Struct>,
@@ -27,19 +25,19 @@ pub struct Types<'a> {
 
 impl<'a> Types<'a> {
     pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
-        let mut all = Set::new();
+        let mut all = OrderedSet::new();
         let mut structs = UnorderedMap::new();
         let mut enums = UnorderedMap::new();
         let mut cxx = UnorderedSet::new();
         let mut rust = UnorderedSet::new();
         let mut aliases = UnorderedMap::new();
         let mut untrusted = UnorderedMap::new();
-        let mut explicit_impls = UnorderedMap::new();
+        let mut impls = OrderedMap::new();
         let mut resolutions = UnorderedMap::new();
         let struct_improper_ctypes = UnorderedSet::new();
         let toposorted_structs = Vec::new();
 
-        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
+        fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) {
             all.insert(ty);
             match ty {
                 Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
@@ -162,12 +160,32 @@ impl<'a> Types<'a> {
                 Api::Impl(imp) => {
                     visit(&mut all, &imp.ty);
                     if let Some(key) = imp.ty.impl_key() {
-                        explicit_impls.insert(key, imp);
+                        impls.insert(key, Some(imp));
                     }
                 }
             }
         }
 
+        for ty in &all {
+            let impl_key = match ty.impl_key() {
+                Some(impl_key) => impl_key,
+                None => continue,
+            };
+            let implicit_impl = match impl_key {
+                ImplKey::RustBox(ident)
+                | ImplKey::RustVec(ident)
+                | ImplKey::UniquePtr(ident)
+                | ImplKey::SharedPtr(ident)
+                | ImplKey::WeakPtr(ident)
+                | ImplKey::CxxVector(ident) => {
+                    Atom::from(ident).is_none() && !aliases.contains_key(ident)
+                }
+            };
+            if implicit_impl && !impls.contains_key(&impl_key) {
+                impls.insert(impl_key, None);
+            }
+        }
+
         // All these APIs may contain types passed by value. We need to ensure
         // we check that this is permissible. We do this _after_ scanning all
         // the APIs above, in case some function or struct references a type
@@ -184,7 +202,7 @@ impl<'a> Types<'a> {
             aliases,
             untrusted,
             required_trivial,
-            explicit_impls,
+            impls,
             resolutions,
             struct_improper_ctypes,
             toposorted_structs,
@@ -239,12 +257,6 @@ impl<'a> Types<'a> {
             ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
         }
     }
-
-    pub fn resolve(&self, ident: &NamedType) -> &Pair {
-        self.resolutions
-            .get(&ident.rust)
-            .expect("Unable to resolve type")
-    }
 }
 
 impl<'t, 'a> IntoIterator for &'t Types<'a> {

From b97a245c935907a033a7dbb9a864d1b318fafff9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:32:35 +0000
Subject: [PATCH 1934/2232] Avoid hashing arg names in hash of function signature


---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index fd8162f..8762652 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -296,7 +296,23 @@ impl PartialEq for Signature {
             && ret == ret2
             && throws == throws2
             && args.len() == args2.len()
-            && args.iter().zip(args2).all(|(arg, arg2)| arg == arg2)
+            && args.iter().zip(args2).all(|(arg, arg2)| {
+                let Var {
+                    doc: _,
+                    attrs: _,
+                    visibility: _,
+                    ident: _,
+                    ty,
+                } = arg;
+                let Var {
+                    doc: _,
+                    attrs: _,
+                    visibility: _,
+                    ident: _,
+                    ty: ty2,
+                } = arg2;
+                ty == ty2
+            })
     }
 }
 
@@ -316,49 +332,20 @@ impl Hash for Signature {
         unsafety.is_some().hash(state);
         receiver.hash(state);
         for arg in args {
-            arg.hash(state);
+            let Var {
+                doc: _,
+                attrs: _,
+                visibility: _,
+                ident: _,
+                ty,
+            } = arg;
+            ty.hash(state);
         }
         ret.hash(state);
         throws.hash(state);
     }
 }
 
-impl Eq for Var {}
-
-impl PartialEq for Var {
-    fn eq(&self, other: &Var) -> bool {
-        let Var {
-            doc: _,
-            attrs: _,
-            visibility: _,
-            ident,
-            ty,
-        } = self;
-        let Var {
-            doc: _,
-            attrs: _,
-            visibility: _,
-            ident: ident2,
-            ty: ty2,
-        } = other;
-        ident == ident2 && ty == ty2
-    }
-}
-
-impl Hash for Var {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        let Var {
-            doc: _,
-            attrs: _,
-            visibility: _,
-            ident,
-            ty,
-        } = self;
-        ident.hash(state);
-        ty.hash(state);
-    }
-}
-
 impl Eq for Receiver {}
 
 impl PartialEq for Receiver {

From 84ed6adda5e173948f196d42c14fd3718c188972 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:46:10 +0000
Subject: [PATCH 1935/2232] 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 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         }
         write!(out, "  ");
         write_type_space(out, &field.ty);
-        writeln!(out, "{};", field.ident);
+        writeln!(out, "{};", field.name.cxx);
     }
 
     writeln!(out);
@@ -755,28 +755,28 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         }
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
                 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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     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 @@ fn write_rust_function_shim_decl(
             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 @@ fn write_rust_function_shim_impl(
             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 @@ fn write_rust_function_shim_impl(
             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 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
     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 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     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_clone(strct: &Struct, span: Span) -> TokenStream {
 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_debug(strct: &Struct, span: Span) -> TokenStream {
 
 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_default(strct: &Struct, span: Span) -> TokenStream {
 
 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 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
             ::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 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
         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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
 
 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 @@ fn expand_function_pointer_trampoline(
         catch_unwind_label,
         None,
     );
+    let var = &var.rust;
 
     quote! {
         let #var = ::cxx::private::FatFunction {
@@ -792,7 +793,7 @@ fn expand_rust_function_shim_impl(
         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 @@ fn expand_rust_function_shim_impl(
     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 @@ fn expand_rust_function_shim_super(
         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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             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 @@ impl PartialEq for Signature {
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty,
                 } = arg;
                 let Var {
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty: ty2,
                 } = arg2;
                 ty == ty2
@@ -336,7 +336,7 @@ impl Hash for Signature {
                 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 @@ pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
 }
 
 // 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 struct Var {
     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 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
             }
         };
         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 @@ fn parse_extern_fn(
                     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 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             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 @@ impl ToTokens for Var {
             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);
     }
 }

From d357bb15cff979fdeea651c7f11fc45efd971619 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:53:47 +0000
Subject: [PATCH 1936/2232] Merge pull request #631 from dtolnay/var


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 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
         }
         write!(out, "  ");
         write_type_space(out, &field.ty);
-        writeln!(out, "{};", field.ident);
+        writeln!(out, "{};", field.name.cxx);
     }
 
     writeln!(out);
@@ -755,28 +755,28 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         }
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
                 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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     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 @@ fn write_rust_function_shim_decl(
             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 @@ fn write_rust_function_shim_impl(
             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 @@ fn write_rust_function_shim_impl(
             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 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
     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 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     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_clone(strct: &Struct, span: Span) -> TokenStream {
 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_debug(strct: &Struct, span: Span) -> TokenStream {
 
 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_default(strct: &Struct, span: Span) -> TokenStream {
 
 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 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
             ::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 @@ fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
         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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         .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_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
 
 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 @@ fn expand_function_pointer_trampoline(
         catch_unwind_label,
         None,
     );
+    let var = &var.rust;
 
     quote! {
         let #var = ::cxx::private::FatFunction {
@@ -792,7 +793,7 @@ fn expand_rust_function_shim_impl(
         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 @@ fn expand_rust_function_shim_impl(
     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 @@ fn expand_rust_function_shim_super(
         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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             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 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
             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 @@ impl PartialEq for Signature {
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty,
                 } = arg;
                 let Var {
                     doc: _,
                     attrs: _,
                     visibility: _,
-                    ident: _,
+                    name: _,
                     ty: ty2,
                 } = arg2;
                 ty == ty2
@@ -336,7 +336,7 @@ impl Hash for Signature {
                 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 @@ pub fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
 }
 
 // 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 struct Var {
     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 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
             }
         };
         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 @@ fn parse_extern_fn(
                     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 @@ fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
             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 @@ impl ToTokens for Var {
             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);
     }
 }

From 0a89256c28c6331bc96331b5b16d8640f697d1be Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:53:56 +0000
Subject: [PATCH 1937/2232] Support rename attributes on struct fields


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index fd558dc..3d2c638 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -100,11 +100,15 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     for field in named_fields.named {
         let ident = field.ident.unwrap();
         let mut doc = Doc::new();
+        let mut cxx_name = None;
+        let mut rust_name = None;
         let attrs = attrs::parse(
             cx,
             field.attrs,
             attrs::Parser {
                 doc: Some(&mut doc),
+                cxx_name: Some(&mut cxx_name),
+                rust_name: Some(&mut rust_name),
                 ..Default::default()
             },
         );
@@ -116,7 +120,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
             }
         };
         let visibility = visibility_pub(&field.vis, &ident);
-        let name = pair(Namespace::default(), &ident, None, None);
+        let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
         fields.push(Var {
             doc,
             attrs,

From 442dffdbbcfc1b0d833fbfa5d000cf6d003df9f7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:59:51 +0000
Subject: [PATCH 1938/2232] Merge pull request #632 from dtolnay/var


Support rename attributes on struct fields
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index fd558dc..3d2c638 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -100,11 +100,15 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     for field in named_fields.named {
         let ident = field.ident.unwrap();
         let mut doc = Doc::new();
+        let mut cxx_name = None;
+        let mut rust_name = None;
         let attrs = attrs::parse(
             cx,
             field.attrs,
             attrs::Parser {
                 doc: Some(&mut doc),
+                cxx_name: Some(&mut cxx_name),
+                rust_name: Some(&mut rust_name),
                 ..Default::default()
             },
         );
@@ -116,7 +120,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
             }
         };
         let visibility = visibility_pub(&field.vis, &ident);
-        let name = pair(Namespace::default(), &ident, None, None);
+        let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
         fields.push(Var {
             doc,
             attrs,

From 9f84fe8bbd6ec9891379cab2a90168b7aaf535fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 01 2021 23:59:59 +0000
Subject: [PATCH 1939/2232] Check rust idents for cxxbridge prefix


---

diff --git a/syntax/ident.rs b/syntax/ident.rs
index 076fe92..78750dc 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -2,21 +2,29 @@ use crate::syntax::check::Check;
 use crate::syntax::{error, Api, Pair};
 use proc_macro2::Ident;
 
-fn check(cx: &mut Check, ident: &Ident) {
-    let s = ident.to_string();
-    if s.starts_with("cxxbridge") {
-        cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
+fn check(cx: &mut Check, name: &Pair) {
+    for segment in &name.namespace {
+        check_cxx_ident(cx, segment);
     }
-    if s.contains("__") {
-        cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
+    check_cxx_ident(cx, &name.cxx);
+    check_rust_ident(cx, &name.rust);
+
+    fn check_cxx_ident(cx: &mut Check, ident: &Ident) {
+        let s = ident.to_string();
+        if s.starts_with("cxxbridge") {
+            cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
+        }
+        if s.contains("__") {
+            cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
+        }
     }
-}
 
-fn check_ident(cx: &mut Check, name: &Pair) {
-    for segment in &name.namespace {
-        check(cx, segment);
+    fn check_rust_ident(cx: &mut Check, ident: &Ident) {
+        let s = ident.to_string();
+        if s.starts_with("cxxbridge") {
+            cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
+        }
     }
-    check(cx, &name.cxx);
 }
 
 pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
@@ -24,28 +32,28 @@ pub(crate) fn check_all(cx: &mut Check, apis: &[Api]) {
         match api {
             Api::Include(_) | Api::Impl(_) => {}
             Api::Struct(strct) => {
-                check_ident(cx, &strct.name);
+                check(cx, &strct.name);
                 for field in &strct.fields {
-                    check_ident(cx, &field.name);
+                    check(cx, &field.name);
                 }
             }
             Api::Enum(enm) => {
-                check_ident(cx, &enm.name);
+                check(cx, &enm.name);
                 for variant in &enm.variants {
-                    check(cx, &variant.name.rust);
+                    check(cx, &variant.name);
                 }
             }
             Api::CxxType(ety) | Api::RustType(ety) => {
-                check_ident(cx, &ety.name);
+                check(cx, &ety.name);
             }
             Api::CxxFunction(efn) | Api::RustFunction(efn) => {
-                check(cx, &efn.name.rust);
+                check(cx, &efn.name);
                 for arg in &efn.args {
-                    check_ident(cx, &arg.name);
+                    check(cx, &arg.name);
                 }
             }
             Api::TypeAlias(alias) => {
-                check_ident(cx, &alias.name);
+                check(cx, &alias.name);
             }
         }
     }

From ed6ba4a63cc704982ec8334e04b62b01ab847759 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 01:57:14 +0000
Subject: [PATCH 1940/2232] Add ForeignName wrapper around non-Rust names


---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index c030717..2129d10 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -53,7 +53,7 @@ mod tests {
     use super::NamespaceEntries;
     use crate::syntax::attrs::OtherAttrs;
     use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
+    use crate::syntax::{Api, Doc, ExternType, ForeignName, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
     use std::iter::FromIterator;
     use syn::punctuated::Punctuated;
@@ -119,7 +119,7 @@ mod tests {
 
     fn assert_ident(api: &Api, expected: &str) {
         if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.name.cxx, expected);
+            assert_eq!(cxx_type.name.cxx.to_string(), expected);
         } else {
             unreachable!()
         }
@@ -127,7 +127,6 @@ mod tests {
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
         let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
-        let ident = Ident::new(ident, Span::call_site());
         Api::CxxType(ExternType {
             lang: Lang::Rust,
             doc: Doc::new(),
@@ -137,8 +136,8 @@ mod tests {
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
-                cxx: ident.clone(),
-                rust: ident,
+                cxx: ForeignName::parse(ident, Span::call_site()).unwrap(),
+                rust: Ident::new(ident, Span::call_site()),
             },
             generics: Lifetimes {
                 lt_token: None,
diff --git a/gen/src/write.rs b/gen/src/write.rs
index def0447..5e2473a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -50,10 +50,10 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
         for api in apis {
             write!(out, "{:1$}", "", indent);
             match api {
-                Api::Struct(strct) => write_struct_decl(out, &strct.name.cxx),
+                Api::Struct(strct) => write_struct_decl(out, &strct.name),
                 Api::Enum(enm) => write_enum_decl(out, enm),
                 Api::CxxType(ety) => write_struct_using(out, &ety.name),
-                Api::RustType(ety) => write_struct_decl(out, &ety.name.cxx),
+                Api::RustType(ety) => write_struct_decl(out, &ety.name),
                 _ => unreachable!(),
             }
         }
@@ -296,8 +296,8 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
     writeln!(out, "#endif // {}", guard);
 }
 
-fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "struct {};", ident);
+fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
+    writeln!(out, "struct {};", ident.cxx);
 }
 
 fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index d3e2bb0..4808f2e 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,7 +1,7 @@
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
-use crate::syntax::{Derive, Doc};
+use crate::syntax::{Derive, Doc, ForeignName};
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use syn::parse::{ParseStream, Parser as _};
@@ -31,7 +31,7 @@ pub struct Parser<'a> {
     pub derives: Option<&'a mut Vec<Derive>>,
     pub repr: Option<&'a mut Option<Atom>>,
     pub namespace: Option<&'a mut Namespace>,
-    pub cxx_name: Option<&'a mut Option<Ident>>,
+    pub cxx_name: Option<&'a mut Option<ForeignName>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
 
     // Suppress clippy needless_update lint ("struct update has no effect, all
@@ -96,7 +96,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
                 }
             }
         } else if attr.path.is_ident("cxx_name") {
-            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+            match parse_cxx_name_attribute.parse2(attr.tokens.clone()) {
                 Ok(attr) => {
                     if let Some(cxx_name) = &mut parser.cxx_name {
                         **cxx_name = Some(attr);
@@ -109,7 +109,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
                 }
             }
         } else if attr.path.is_ident("rust_name") {
-            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+            match parse_rust_name_attribute.parse2(attr.tokens.clone()) {
                 Ok(attr) => {
                     if let Some(rust_name) = &mut parser.rust_name {
                         **rust_name = Some(attr);
@@ -192,7 +192,18 @@ fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
     Ok(namespace)
 }
 
-fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
+fn parse_cxx_name_attribute(input: ParseStream) -> Result<ForeignName> {
+    input.parse::<Token![=]>()?;
+    if input.peek(LitStr) {
+        let lit: LitStr = input.parse()?;
+        ForeignName::parse(&lit.value(), lit.span())
+    } else {
+        let ident: Ident = input.parse()?;
+        ForeignName::parse(&ident.to_string(), ident.span())
+    }
+}
+
+fn parse_rust_name_attribute(input: ParseStream) -> Result<Ident> {
     input.parse::<Token![=]>()?;
     if input.peek(LitStr) {
         let lit: LitStr = input.parse()?;
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 78750dc..bb2281e 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,27 +1,24 @@
 use crate::syntax::check::Check;
 use crate::syntax::{error, Api, Pair};
-use proc_macro2::Ident;
 
 fn check(cx: &mut Check, name: &Pair) {
     for segment in &name.namespace {
-        check_cxx_ident(cx, segment);
+        check_cxx_ident(cx, &segment.to_string());
     }
-    check_cxx_ident(cx, &name.cxx);
-    check_rust_ident(cx, &name.rust);
+    check_cxx_ident(cx, &name.cxx.to_string());
+    check_rust_ident(cx, &name.rust.to_string());
 
-    fn check_cxx_ident(cx: &mut Check, ident: &Ident) {
-        let s = ident.to_string();
-        if s.starts_with("cxxbridge") {
+    fn check_cxx_ident(cx: &mut Check, ident: &str) {
+        if ident.starts_with("cxxbridge") {
             cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
         }
-        if s.contains("__") {
+        if ident.contains("__") {
             cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
         }
     }
 
-    fn check_rust_ident(cx: &mut Check, ident: &Ident) {
-        let s = ident.to_string();
-        if s.starts_with("cxxbridge") {
+    fn check_rust_ident(cx: &mut Check, ident: &str) {
+        if ident.starts_with("cxxbridge") {
             cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9b4a101..57ed4fc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -41,6 +41,7 @@ use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 pub use self::atom::Atom;
 pub use self::derive::{Derive, Trait};
 pub use self::doc::Doc;
+pub use self::names::ForeignName;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
@@ -252,7 +253,7 @@ pub enum Lang {
 #[derive(Clone)]
 pub struct Pair {
     pub namespace: Namespace,
-    pub cxx: Ident,
+    pub cxx: ForeignName,
     pub rust: Ident,
 }
 
diff --git a/syntax/names.rs b/syntax/names.rs
index c4cbcff..b2ae013 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,25 +1,37 @@
+use crate::syntax::symbol::Segment;
 use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
 use proc_macro2::{Ident, Span};
+use std::fmt::{self, Display};
 use std::iter;
+use syn::parse::Result;
 use syn::punctuated::Punctuated;
 
+#[derive(Clone)]
+pub struct ForeignName {
+    text: String,
+    span: Span,
+}
+
 impl Pair {
     pub fn to_symbol(&self) -> Symbol {
-        Symbol::from_idents(self.iter_all_segments())
+        let segments = self
+            .namespace
+            .iter()
+            .map(|ident| ident as &dyn Segment)
+            .chain(iter::once(&self.cxx as &dyn Segment));
+        Symbol::from_idents(segments)
     }
 
     pub fn to_fully_qualified(&self) -> String {
         let mut fully_qualified = String::new();
-        for segment in self.iter_all_segments() {
+        for segment in &self.namespace {
             fully_qualified += "::";
             fully_qualified += &segment.to_string();
         }
+        fully_qualified += "::";
+        fully_qualified += &self.cxx.to_string();
         fully_qualified
     }
-
-    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
-        self.namespace.iter().chain(iter::once(&self.cxx))
-    }
 }
 
 impl NamedType {
@@ -36,3 +48,19 @@ impl NamedType {
         self.rust.span()
     }
 }
+
+impl ForeignName {
+    pub fn parse(text: &str, span: Span) -> Result<Self> {
+        // TODO: support C++ names containing whitespace (`unsigned int`) or
+        // non-alphanumeric characters (`operator++`).
+        let ident: Ident = syn::parse_str(text)?;
+        let text = ident.to_string();
+        Ok(ForeignName { text, span })
+    }
+}
+
+impl Display for ForeignName {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.text)
+    }
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d2c638..795a518 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,9 +4,9 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef, Struct, Ty1,
-    Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
+    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
+    Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -1258,11 +1258,16 @@ fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
     })
 }
 
-fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
-    let default = || default.clone();
+fn pair(
+    namespace: Namespace,
+    default: &Ident,
+    cxx: Option<ForeignName>,
+    rust: Option<Ident>,
+) -> Pair {
     Pair {
         namespace,
-        cxx: cxx.unwrap_or_else(default),
-        rust: rust.unwrap_or_else(default),
+        cxx: cxx
+            .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
+        rust: rust.unwrap_or_else(|| default.clone()),
     }
 }
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 9a0a4a1..a13a4f3 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -1,5 +1,5 @@
 use crate::syntax::namespace::Namespace;
-use crate::syntax::Pair;
+use crate::syntax::{ForeignName, Pair};
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use std::fmt::{self, Display, Write};
@@ -30,7 +30,7 @@ impl Symbol {
         assert!(self.0.len() > len_before);
     }
 
-    pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
+    pub fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> Self {
         let mut symbol = Symbol(String::new());
         for segment in it {
             segment.write(&mut symbol);
@@ -55,16 +55,19 @@ impl Segment for str {
         symbol.push(&self);
     }
 }
+
 impl Segment for usize {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
+
 impl Segment for Ident {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
+
 impl Segment for Symbol {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
@@ -86,6 +89,14 @@ impl Segment for Pair {
     }
 }
 
+impl Segment for ForeignName {
+    fn write(&self, symbol: &mut Symbol) {
+        // TODO: support C++ names containing whitespace (`unsigned int`) or
+        // non-alphanumeric characters (`operator++`).
+        self.to_string().write(symbol);
+    }
+}
+
 impl<T> Segment for &'_ T
 where
     T: ?Sized + Segment + Display,

From 010b5c3c2519070d3681eaea31ba261a497c38be Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 02:03:11 +0000
Subject: [PATCH 1941/2232] Merge pull request #633 from dtolnay/foreign


Add ForeignName wrapper around non-Rust names
---

diff --git a/gen/src/nested.rs b/gen/src/nested.rs
index c030717..2129d10 100644
--- a/gen/src/nested.rs
+++ b/gen/src/nested.rs
@@ -53,7 +53,7 @@ mod tests {
     use super::NamespaceEntries;
     use crate::syntax::attrs::OtherAttrs;
     use crate::syntax::namespace::Namespace;
-    use crate::syntax::{Api, Doc, ExternType, Lang, Lifetimes, Pair};
+    use crate::syntax::{Api, Doc, ExternType, ForeignName, Lang, Lifetimes, Pair};
     use proc_macro2::{Ident, Span};
     use std::iter::FromIterator;
     use syn::punctuated::Punctuated;
@@ -119,7 +119,7 @@ mod tests {
 
     fn assert_ident(api: &Api, expected: &str) {
         if let Api::CxxType(cxx_type) = api {
-            assert_eq!(cxx_type.name.cxx, expected);
+            assert_eq!(cxx_type.name.cxx.to_string(), expected);
         } else {
             unreachable!()
         }
@@ -127,7 +127,6 @@ mod tests {
 
     fn make_api(ns: Option<&str>, ident: &str) -> Api {
         let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
-        let ident = Ident::new(ident, Span::call_site());
         Api::CxxType(ExternType {
             lang: Lang::Rust,
             doc: Doc::new(),
@@ -137,8 +136,8 @@ mod tests {
             type_token: Token![type](Span::call_site()),
             name: Pair {
                 namespace: ns,
-                cxx: ident.clone(),
-                rust: ident,
+                cxx: ForeignName::parse(ident, Span::call_site()).unwrap(),
+                rust: Ident::new(ident, Span::call_site()),
             },
             generics: Lifetimes {
                 lt_token: None,
diff --git a/gen/src/write.rs b/gen/src/write.rs
index def0447..5e2473a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -50,10 +50,10 @@ fn write_forward_declarations(out: &mut OutFile, apis: &[Api]) {
         for api in apis {
             write!(out, "{:1$}", "", indent);
             match api {
-                Api::Struct(strct) => write_struct_decl(out, &strct.name.cxx),
+                Api::Struct(strct) => write_struct_decl(out, &strct.name),
                 Api::Enum(enm) => write_enum_decl(out, enm),
                 Api::CxxType(ety) => write_struct_using(out, &ety.name),
-                Api::RustType(ety) => write_struct_decl(out, &ety.name.cxx),
+                Api::RustType(ety) => write_struct_decl(out, &ety.name),
                 _ => unreachable!(),
             }
         }
@@ -296,8 +296,8 @@ fn write_struct<'a>(out: &mut OutFile<'a>, strct: &'a Struct, methods: &[&Extern
     writeln!(out, "#endif // {}", guard);
 }
 
-fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
-    writeln!(out, "struct {};", ident);
+fn write_struct_decl(out: &mut OutFile, ident: &Pair) {
+    writeln!(out, "struct {};", ident.cxx);
 }
 
 fn write_enum_decl(out: &mut OutFile, enm: &Enum) {
diff --git a/syntax/attrs.rs b/syntax/attrs.rs
index d3e2bb0..4808f2e 100644
--- a/syntax/attrs.rs
+++ b/syntax/attrs.rs
@@ -1,7 +1,7 @@
 use crate::syntax::namespace::Namespace;
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::{self, *};
-use crate::syntax::{Derive, Doc};
+use crate::syntax::{Derive, Doc, ForeignName};
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use syn::parse::{ParseStream, Parser as _};
@@ -31,7 +31,7 @@ pub struct Parser<'a> {
     pub derives: Option<&'a mut Vec<Derive>>,
     pub repr: Option<&'a mut Option<Atom>>,
     pub namespace: Option<&'a mut Namespace>,
-    pub cxx_name: Option<&'a mut Option<Ident>>,
+    pub cxx_name: Option<&'a mut Option<ForeignName>>,
     pub rust_name: Option<&'a mut Option<Ident>>,
 
     // Suppress clippy needless_update lint ("struct update has no effect, all
@@ -96,7 +96,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
                 }
             }
         } else if attr.path.is_ident("cxx_name") {
-            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+            match parse_cxx_name_attribute.parse2(attr.tokens.clone()) {
                 Ok(attr) => {
                     if let Some(cxx_name) = &mut parser.cxx_name {
                         **cxx_name = Some(attr);
@@ -109,7 +109,7 @@ pub fn parse(cx: &mut Errors, attrs: Vec<Attribute>, mut parser: Parser) -> Othe
                 }
             }
         } else if attr.path.is_ident("rust_name") {
-            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
+            match parse_rust_name_attribute.parse2(attr.tokens.clone()) {
                 Ok(attr) => {
                     if let Some(rust_name) = &mut parser.rust_name {
                         **rust_name = Some(attr);
@@ -192,7 +192,18 @@ fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
     Ok(namespace)
 }
 
-fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
+fn parse_cxx_name_attribute(input: ParseStream) -> Result<ForeignName> {
+    input.parse::<Token![=]>()?;
+    if input.peek(LitStr) {
+        let lit: LitStr = input.parse()?;
+        ForeignName::parse(&lit.value(), lit.span())
+    } else {
+        let ident: Ident = input.parse()?;
+        ForeignName::parse(&ident.to_string(), ident.span())
+    }
+}
+
+fn parse_rust_name_attribute(input: ParseStream) -> Result<Ident> {
     input.parse::<Token![=]>()?;
     if input.peek(LitStr) {
         let lit: LitStr = input.parse()?;
diff --git a/syntax/ident.rs b/syntax/ident.rs
index 78750dc..bb2281e 100644
--- a/syntax/ident.rs
+++ b/syntax/ident.rs
@@ -1,27 +1,24 @@
 use crate::syntax::check::Check;
 use crate::syntax::{error, Api, Pair};
-use proc_macro2::Ident;
 
 fn check(cx: &mut Check, name: &Pair) {
     for segment in &name.namespace {
-        check_cxx_ident(cx, segment);
+        check_cxx_ident(cx, &segment.to_string());
     }
-    check_cxx_ident(cx, &name.cxx);
-    check_rust_ident(cx, &name.rust);
+    check_cxx_ident(cx, &name.cxx.to_string());
+    check_rust_ident(cx, &name.rust.to_string());
 
-    fn check_cxx_ident(cx: &mut Check, ident: &Ident) {
-        let s = ident.to_string();
-        if s.starts_with("cxxbridge") {
+    fn check_cxx_ident(cx: &mut Check, ident: &str) {
+        if ident.starts_with("cxxbridge") {
             cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
         }
-        if s.contains("__") {
+        if ident.contains("__") {
             cx.error(ident, error::DOUBLE_UNDERSCORE.msg);
         }
     }
 
-    fn check_rust_ident(cx: &mut Check, ident: &Ident) {
-        let s = ident.to_string();
-        if s.starts_with("cxxbridge") {
+    fn check_rust_ident(cx: &mut Check, ident: &str) {
+        if ident.starts_with("cxxbridge") {
             cx.error(ident, error::CXXBRIDGE_RESERVED.msg);
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 9b4a101..57ed4fc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -41,6 +41,7 @@ use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
 pub use self::atom::Atom;
 pub use self::derive::{Derive, Trait};
 pub use self::doc::Doc;
+pub use self::names::ForeignName;
 pub use self::parse::parse_items;
 pub use self::types::Types;
 
@@ -252,7 +253,7 @@ pub enum Lang {
 #[derive(Clone)]
 pub struct Pair {
     pub namespace: Namespace,
-    pub cxx: Ident,
+    pub cxx: ForeignName,
     pub rust: Ident,
 }
 
diff --git a/syntax/names.rs b/syntax/names.rs
index c4cbcff..b2ae013 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -1,25 +1,37 @@
+use crate::syntax::symbol::Segment;
 use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
 use proc_macro2::{Ident, Span};
+use std::fmt::{self, Display};
 use std::iter;
+use syn::parse::Result;
 use syn::punctuated::Punctuated;
 
+#[derive(Clone)]
+pub struct ForeignName {
+    text: String,
+    span: Span,
+}
+
 impl Pair {
     pub fn to_symbol(&self) -> Symbol {
-        Symbol::from_idents(self.iter_all_segments())
+        let segments = self
+            .namespace
+            .iter()
+            .map(|ident| ident as &dyn Segment)
+            .chain(iter::once(&self.cxx as &dyn Segment));
+        Symbol::from_idents(segments)
     }
 
     pub fn to_fully_qualified(&self) -> String {
         let mut fully_qualified = String::new();
-        for segment in self.iter_all_segments() {
+        for segment in &self.namespace {
             fully_qualified += "::";
             fully_qualified += &segment.to_string();
         }
+        fully_qualified += "::";
+        fully_qualified += &self.cxx.to_string();
         fully_qualified
     }
-
-    fn iter_all_segments(&self) -> impl Iterator<Item = &Ident> {
-        self.namespace.iter().chain(iter::once(&self.cxx))
-    }
 }
 
 impl NamedType {
@@ -36,3 +48,19 @@ impl NamedType {
         self.rust.span()
     }
 }
+
+impl ForeignName {
+    pub fn parse(text: &str, span: Span) -> Result<Self> {
+        // TODO: support C++ names containing whitespace (`unsigned int`) or
+        // non-alphanumeric characters (`operator++`).
+        let ident: Ident = syn::parse_str(text)?;
+        let text = ident.to_string();
+        Ok(ForeignName { text, span })
+    }
+}
+
+impl Display for ForeignName {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str(&self.text)
+    }
+}
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3d2c638..795a518 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -4,9 +4,9 @@ use crate::syntax::file::{Item, ItemForeignMod};
 use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
-    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, Impl, Include, IncludeKind,
-    Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef, Struct, Ty1,
-    Type, TypeAlias, Var, Variant,
+    attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
+    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
+    Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
@@ -1258,11 +1258,16 @@ fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
     })
 }
 
-fn pair(namespace: Namespace, default: &Ident, cxx: Option<Ident>, rust: Option<Ident>) -> Pair {
-    let default = || default.clone();
+fn pair(
+    namespace: Namespace,
+    default: &Ident,
+    cxx: Option<ForeignName>,
+    rust: Option<Ident>,
+) -> Pair {
     Pair {
         namespace,
-        cxx: cxx.unwrap_or_else(default),
-        rust: rust.unwrap_or_else(default),
+        cxx: cxx
+            .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
+        rust: rust.unwrap_or_else(|| default.clone()),
     }
 }
diff --git a/syntax/symbol.rs b/syntax/symbol.rs
index 9a0a4a1..a13a4f3 100644
--- a/syntax/symbol.rs
+++ b/syntax/symbol.rs
@@ -1,5 +1,5 @@
 use crate::syntax::namespace::Namespace;
-use crate::syntax::Pair;
+use crate::syntax::{ForeignName, Pair};
 use proc_macro2::{Ident, TokenStream};
 use quote::ToTokens;
 use std::fmt::{self, Display, Write};
@@ -30,7 +30,7 @@ impl Symbol {
         assert!(self.0.len() > len_before);
     }
 
-    pub fn from_idents<'a, T: Iterator<Item = &'a Ident>>(it: T) -> Self {
+    pub fn from_idents<'a>(it: impl Iterator<Item = &'a dyn Segment>) -> Self {
         let mut symbol = Symbol(String::new());
         for segment in it {
             segment.write(&mut symbol);
@@ -55,16 +55,19 @@ impl Segment for str {
         symbol.push(&self);
     }
 }
+
 impl Segment for usize {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
+
 impl Segment for Ident {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
     }
 }
+
 impl Segment for Symbol {
     fn write(&self, symbol: &mut Symbol) {
         symbol.push(&self);
@@ -86,6 +89,14 @@ impl Segment for Pair {
     }
 }
 
+impl Segment for ForeignName {
+    fn write(&self, symbol: &mut Symbol) {
+        // TODO: support C++ names containing whitespace (`unsigned int`) or
+        // non-alphanumeric characters (`operator++`).
+        self.to_string().write(symbol);
+    }
+}
+
 impl<T> Segment for &'_ T
 where
     T: ?Sized + Segment + Display,

From 038b29a0244f983534597fdd5774f34708ad4816 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 02:26:26 +0000
Subject: [PATCH 1942/2232] Add place for struct and enum lifetime parameters


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 57ed4fc..73952e1 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -95,6 +95,7 @@ pub struct Struct {
     pub visibility: Token![pub],
     pub struct_token: Token![struct],
     pub name: Pair,
+    pub generics: Lifetimes,
     pub brace_token: Brace,
     pub fields: Vec<Var>,
 }
@@ -106,6 +107,7 @@ pub struct Enum {
     pub visibility: Token![pub],
     pub enum_token: Token![enum],
     pub name: Pair,
+    pub generics: Lifetimes,
     pub brace_token: Brace,
     pub variants: Vec<Variant>,
     pub repr: Atom,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 795a518..db46dc4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -133,6 +133,11 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
+    let generics = Lifetimes {
+        lt_token: None,
+        lifetimes: Punctuated::new(),
+        gt_token: None,
+    };
     let brace_token = named_fields.brace_token;
 
     Ok(Api::Struct(Struct {
@@ -142,6 +147,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         visibility,
         struct_token,
         name,
+        generics,
         brace_token,
         fields,
     }))
@@ -207,6 +213,11 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
     let repr_type = Type::Ident(NamedType::new(repr_ident));
+    let generics = Lifetimes {
+        lt_token: None,
+        lifetimes: Punctuated::new(),
+        gt_token: None,
+    };
 
     Ok(Api::Enum(Enum {
         doc,
@@ -215,6 +226,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         visibility,
         enum_token,
         name,
+        generics,
         brace_token,
         variants,
         repr,

From 1e5fe237d81eb2d01cbd8e10bb67bffc36fd409b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 02:28:28 +0000
Subject: [PATCH 1943/2232] 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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_rust_function_decl_impl(
         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 @@ fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     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 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     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 @@ trait ToTypename {
 
 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 @@ trait ToMangled {
 
 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_generic_instantiations(out: &mut OutFile) {
 
 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_vec_extern(out: &mut OutFile, element: &Ident) {
 
 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 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     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_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
 
 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_shared_ptr(out: &mut OutFile, ident: &Ident) {
 
 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 type_id(name: &Pair) -> TokenStream {
 
 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_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
 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_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
 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_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 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_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 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_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 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 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
             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::improper::ImproperCtype;
 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 struct Types<'a> {
     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 @@ impl<'a> Types<'a> {
             }
         }
 
-        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 @@ impl<'a> Types<'a> {
                     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 @@ impl<'a> Types<'a> {
                         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 @@ impl<'a> Types<'a> {
                     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 @@ impl<'a> Types<'a> {
                         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 @@ impl<'a> Types<'a> {
                     }
                     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);

From 43d8e4295dc4a0f1d9e7313a0972de80f3f35449 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 03:05:20 +0000
Subject: [PATCH 1944/2232] Merge pull request #634 from dtolnay/resolve


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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         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 @@ fn write_rust_function_decl_impl(
         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 @@ fn write_rust_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     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 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     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 @@ trait ToTypename {
 
 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 @@ trait ToMangled {
 
 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_generic_instantiations(out: &mut OutFile) {
 
 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_vec_extern(out: &mut OutFile, element: &Ident) {
 
 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 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     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_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
 
 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_shared_ptr(out: &mut OutFile, ident: &Ident) {
 
 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 type_id(name: &Pair) -> TokenStream {
 
 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_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
 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_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
 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_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 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_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 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_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 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 @@ pub fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
             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::improper::ImproperCtype;
 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 struct Types<'a> {
     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 @@ impl<'a> Types<'a> {
             }
         }
 
-        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 @@ impl<'a> Types<'a> {
                     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 @@ impl<'a> Types<'a> {
                         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 @@ impl<'a> Types<'a> {
                     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 @@ impl<'a> Types<'a> {
                         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 @@ impl<'a> Types<'a> {
                     }
                     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);

From 1d5ffbb4c91405bf1058ecf6ed3508a4fe09486b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 03:28:34 +0000
Subject: [PATCH 1945/2232] Fix span placement on ForeignName parse error


---

diff --git a/syntax/names.rs b/syntax/names.rs
index b2ae013..cb6ace5 100644
--- a/syntax/names.rs
+++ b/syntax/names.rs
@@ -3,7 +3,7 @@ use crate::syntax::{Lifetimes, NamedType, Pair, Symbol};
 use proc_macro2::{Ident, Span};
 use std::fmt::{self, Display};
 use std::iter;
-use syn::parse::Result;
+use syn::parse::{Error, Result};
 use syn::punctuated::Punctuated;
 
 #[derive(Clone)]
@@ -53,9 +53,13 @@ impl ForeignName {
     pub fn parse(text: &str, span: Span) -> Result<Self> {
         // TODO: support C++ names containing whitespace (`unsigned int`) or
         // non-alphanumeric characters (`operator++`).
-        let ident: Ident = syn::parse_str(text)?;
-        let text = ident.to_string();
-        Ok(ForeignName { text, span })
+        match syn::parse_str::<Ident>(text) {
+            Ok(ident) => {
+                let text = ident.to_string();
+                Ok(ForeignName { text, span })
+            }
+            Err(err) => Err(Error::new(span, err)),
+        }
     }
 }
 

From eb472ad8374de83fcec8d7899a554c7372ec1853 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 03:40:19 +0000
Subject: [PATCH 1946/2232] Remove unused Impl hashing impls


These used to be for a HashSet<&Impl> held by Types, which has since
been refactored into a different data structure.

---

diff --git a/syntax/impls.rs b/syntax/impls.rs
index ae4a77d..3a0b3e0 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,5 +1,5 @@
 use crate::syntax::{
-    Array, ExternFn, Impl, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
+    Array, ExternFn, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::hash::{Hash, Hasher};
 use std::mem;
@@ -395,45 +395,3 @@ impl Hash for Receiver {
         ty.hash(state);
     }
 }
-
-impl Hash for Impl {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        let Impl {
-            impl_token: _,
-            generics,
-            negative,
-            ty,
-            brace_token: _,
-            negative_token: _,
-        } = self;
-        generics.hash(state);
-        if *negative {
-            negative.hash(state);
-        }
-        ty.hash(state);
-    }
-}
-
-impl Eq for Impl {}
-
-impl PartialEq for Impl {
-    fn eq(&self, other: &Impl) -> bool {
-        let Impl {
-            impl_token: _,
-            generics,
-            negative,
-            ty,
-            brace_token: _,
-            negative_token: _,
-        } = self;
-        let Impl {
-            impl_token: _,
-            generics: generics2,
-            negative: negative2,
-            ty: ty2,
-            brace_token: _,
-            negative_token: _,
-        } = other;
-        generics == generics2 && negative == negative2 && ty == ty2
-    }
-}

From c417977d27cc5a74e757119aebde59b28ac6868f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 03:51:13 +0000
Subject: [PATCH 1947/2232] Distinguish Impl's impl generics vs generics on the Self type


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 73952e1..30faccc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -141,13 +141,15 @@ pub struct TypeAlias {
 
 pub struct Impl {
     pub impl_token: Token![impl],
-    pub generics: Lifetimes,
+    pub impl_generics: Lifetimes,
     pub negative: bool,
     pub ty: Type,
+    pub ty_generics: Lifetimes,
     pub brace_token: Brace,
     pub negative_token: Option<Token![!]>,
 }
 
+#[derive(Clone, Default)]
 pub struct Lifetimes {
     pub lt_token: Option<Token![<]>,
     pub lifetimes: Punctuated<Lifetime, Token![,]>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index db46dc4..8bd8907 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -868,7 +868,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
             "where-clause on an impl is not supported yet",
         ));
     }
-    let mut generics = Lifetimes {
+    let mut impl_generics = Lifetimes {
         lt_token: imp.generics.lt_token,
         lifetimes: Punctuated::new(),
         gt_token: imp.generics.gt_token,
@@ -877,13 +877,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         let (param, punct) = pair.into_tuple();
         match param {
             GenericParam::Lifetime(def) if def.bounds.is_empty() => {
-                generics.lifetimes.push_value(def.lifetime);
+                impl_generics.lifetimes.push_value(def.lifetime);
                 if let Some(punct) = punct {
-                    generics.lifetimes.push_punct(punct);
+                    impl_generics.lifetimes.push_punct(punct);
                 }
             }
             _ => {
-                let span = quote!(#impl_token #generics);
+                let span = quote!(#impl_token #impl_generics);
                 return Err(Error::new_spanned(
                     span,
                     "generic parameter on an impl is not supported yet",
@@ -907,15 +907,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         }
     }
 
-    let negative = negative_token.is_some();
     let ty = parse_type(&self_ty)?;
+    let ty_generics = match &ty {
+        Type::RustBox(ty)
+        | Type::RustVec(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
+        | Type::CxxVector(ty) => match &ty.inner {
+            Type::Ident(ident) => ident.generics.clone(),
+            _ => Lifetimes::default(),
+        },
+        Type::Ident(_)
+        | Type::Ref(_)
+        | Type::Str(_)
+        | Type::Fn(_)
+        | Type::Void(_)
+        | Type::SliceRef(_)
+        | Type::Array(_) => Lifetimes::default(),
+    };
+
+    let negative = negative_token.is_some();
     let brace_token = imp.brace_token;
 
     Ok(Api::Impl(Impl {
         impl_token,
-        generics,
+        impl_generics,
         negative,
         ty,
+        ty_generics,
         brace_token,
         negative_token,
     }))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index aec21ae..757673d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -192,14 +192,15 @@ impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let Impl {
             impl_token,
-            generics,
+            impl_generics,
             negative: _,
             ty,
+            ty_generics: _,
             brace_token,
             negative_token,
         } = self;
         impl_token.to_tokens(tokens);
-        generics.to_tokens(tokens);
+        impl_generics.to_tokens(tokens);
         negative_token.to_tokens(tokens);
         ty.to_tokens(tokens);
         brace_token.surround(tokens, |_tokens| {});

From dc79f24aadaef10f5d4a5d1a44dffe11bb59ff18 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 03:59:22 +0000
Subject: [PATCH 1948/2232] Parameterize shim trait impl blocks over lifetimes


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8149d5d..980ba3f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1048,6 +1048,12 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
@@ -1055,20 +1061,20 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #[doc(hidden)]
-        #unsafe_token impl ::cxx::private::ImplBox for #ident {}
+        #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
         #[doc(hidden)]
         #[export_name = #link_alloc]
-        unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
+        unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::std::mem::MaybeUninit<#ident #ty_generics> {
             ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
         #[export_name = #link_dealloc]
-        unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
+        unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::std::mem::MaybeUninit<#ident #ty_generics>) {
             ::std::boxed::Box::from_raw(ptr);
         }
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
+        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::std::boxed::Box<#ident #ty_generics>) {
             ::std::ptr::drop_in_place(this);
         }
     }
@@ -1094,6 +1100,12 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
@@ -1101,40 +1113,40 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
 
     quote_spanned! {end_span=>
         #[doc(hidden)]
-        #unsafe_token impl ::cxx::private::ImplVec for #elem {}
+        #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
         #[doc(hidden)]
         #[export_name = #link_new]
-        unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
+        unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
             ::std::ptr::write(this, ::cxx::private::RustVec::new());
         }
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
+        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
             ::std::ptr::drop_in_place(this);
         }
         #[doc(hidden)]
         #[export_name = #link_len]
-        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+        unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
             (*this).len()
         }
         #[doc(hidden)]
         #[export_name = #link_capacity]
-        unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+        unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
             (*this).capacity()
         }
         #[doc(hidden)]
         #[export_name = #link_data]
-        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
+        unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
             (*this).as_ptr()
         }
         #[doc(hidden)]
         #[export_name = #link_reserve_total]
-        unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
+        unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, cap: usize) {
             (*this).reserve_total(cap);
         }
         #[doc(hidden)]
         #[export_name = #link_set_len]
-        unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
+        unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
             (*this).set_len(len);
         }
     }
@@ -1151,6 +1163,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
         || types.aliases.contains_key(ident);
@@ -1162,7 +1180,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                     fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __uninit(&mut repr).cast::<#ident>().write(value) }
+                unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) }
                 repr
             }
         })
@@ -1176,7 +1194,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::UniquePtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -1232,6 +1250,12 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
         || types.aliases.contains_key(ident);
@@ -1242,7 +1266,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                     #[link_name = #link_uninit]
                     fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
-                __uninit(new).cast::<#ident>().write(value);
+                __uninit(new).cast::<#ident #ty_generics>().write(value);
             }
         })
     } else {
@@ -1255,7 +1279,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::SharedPtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
@@ -1300,13 +1324,19 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::WeakPtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
@@ -1363,25 +1393,31 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::VectorElement for #elem {
+        #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
-                    fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
+                    fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
                 }
                 unsafe { __vector_size(v) }
             }
             unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
+                    fn __get_unchecked #impl_generics(_: *mut ::cxx::CxxVector<#elem #ty_generics>, _: usize) -> *mut #elem #ty_generics;
                 }
                 __get_unchecked(v, pos)
             }
@@ -1397,7 +1433,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
             unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_raw]
-                    fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
+                    fn __unique_ptr_raw #impl_generics(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __unique_ptr_raw(&mut repr, raw);
@@ -1406,14 +1442,14 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
             unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_get]
-                    fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
+                    fn __unique_ptr_get #impl_generics(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem #ty_generics>;
                 }
                 __unique_ptr_get(&repr)
             }
             unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_release]
-                    fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
+                    fn __unique_ptr_release #impl_generics(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
                 }
                 __unique_ptr_release(&mut repr)
             }

From dc415ccf8eb969da33bb38b84350610698c5bd7f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 04:09:14 +0000
Subject: [PATCH 1949/2232] Merge pull request #635 from dtolnay/lifetimes


Parameterize shim trait impl blocks over lifetimes
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 8149d5d..980ba3f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1048,6 +1048,12 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
@@ -1055,20 +1061,20 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #[doc(hidden)]
-        #unsafe_token impl ::cxx::private::ImplBox for #ident {}
+        #unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
         #[doc(hidden)]
         #[export_name = #link_alloc]
-        unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
+        unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::std::mem::MaybeUninit<#ident #ty_generics> {
             ::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
         }
         #[doc(hidden)]
         #[export_name = #link_dealloc]
-        unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
+        unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::std::mem::MaybeUninit<#ident #ty_generics>) {
             ::std::boxed::Box::from_raw(ptr);
         }
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
+        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::std::boxed::Box<#ident #ty_generics>) {
             ::std::ptr::drop_in_place(this);
         }
     }
@@ -1094,6 +1100,12 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
@@ -1101,40 +1113,40 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
 
     quote_spanned! {end_span=>
         #[doc(hidden)]
-        #unsafe_token impl ::cxx::private::ImplVec for #elem {}
+        #unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
         #[doc(hidden)]
         #[export_name = #link_new]
-        unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
+        unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
             ::std::ptr::write(this, ::cxx::private::RustVec::new());
         }
         #[doc(hidden)]
         #[export_name = #link_drop]
-        unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
+        unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
             ::std::ptr::drop_in_place(this);
         }
         #[doc(hidden)]
         #[export_name = #link_len]
-        unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+        unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
             (*this).len()
         }
         #[doc(hidden)]
         #[export_name = #link_capacity]
-        unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
+        unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
             (*this).capacity()
         }
         #[doc(hidden)]
         #[export_name = #link_data]
-        unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
+        unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
             (*this).as_ptr()
         }
         #[doc(hidden)]
         #[export_name = #link_reserve_total]
-        unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
+        unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, cap: usize) {
             (*this).reserve_total(cap);
         }
         #[doc(hidden)]
         #[export_name = #link_set_len]
-        unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
+        unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
             (*this).set_len(len);
         }
     }
@@ -1151,6 +1163,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
         || types.aliases.contains_key(ident);
@@ -1162,7 +1180,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                     fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
-                unsafe { __uninit(&mut repr).cast::<#ident>().write(value) }
+                unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) }
                 repr
             }
         })
@@ -1176,7 +1194,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::UniquePtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
@@ -1232,6 +1250,12 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
         || types.aliases.contains_key(ident);
@@ -1242,7 +1266,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                     #[link_name = #link_uninit]
                     fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
                 }
-                __uninit(new).cast::<#ident>().write(value);
+                __uninit(new).cast::<#ident #ty_generics>().write(value);
             }
         })
     } else {
@@ -1255,7 +1279,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::SharedPtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
@@ -1300,13 +1324,19 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::WeakPtrTarget for #ident {
+        #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
@@ -1363,25 +1393,31 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
+    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
+        (&imp.impl_generics, &imp.ty_generics)
+    } else {
+        (resolve.generics, resolve.generics)
+    };
+
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
     let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
-        #unsafe_token impl ::cxx::private::VectorElement for #elem {
+        #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
             const __NAME: &'static dyn ::std::fmt::Display = &#name;
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
-                    fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
+                    fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
                 }
                 unsafe { __vector_size(v) }
             }
             unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
-                    fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
+                    fn __get_unchecked #impl_generics(_: *mut ::cxx::CxxVector<#elem #ty_generics>, _: usize) -> *mut #elem #ty_generics;
                 }
                 __get_unchecked(v, pos)
             }
@@ -1397,7 +1433,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
             unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_raw]
-                    fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
+                    fn __unique_ptr_raw #impl_generics(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
                 }
                 let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
                 __unique_ptr_raw(&mut repr, raw);
@@ -1406,14 +1442,14 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
             unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_get]
-                    fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
+                    fn __unique_ptr_get #impl_generics(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem #ty_generics>;
                 }
                 __unique_ptr_get(&repr)
             }
             unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_release]
-                    fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
+                    fn __unique_ptr_release #impl_generics(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
                 }
                 __unique_ptr_release(&mut repr)
             }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 73952e1..30faccc 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -141,13 +141,15 @@ pub struct TypeAlias {
 
 pub struct Impl {
     pub impl_token: Token![impl],
-    pub generics: Lifetimes,
+    pub impl_generics: Lifetimes,
     pub negative: bool,
     pub ty: Type,
+    pub ty_generics: Lifetimes,
     pub brace_token: Brace,
     pub negative_token: Option<Token![!]>,
 }
 
+#[derive(Clone, Default)]
 pub struct Lifetimes {
     pub lt_token: Option<Token![<]>,
     pub lifetimes: Punctuated<Lifetime, Token![,]>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index db46dc4..8bd8907 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -868,7 +868,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
             "where-clause on an impl is not supported yet",
         ));
     }
-    let mut generics = Lifetimes {
+    let mut impl_generics = Lifetimes {
         lt_token: imp.generics.lt_token,
         lifetimes: Punctuated::new(),
         gt_token: imp.generics.gt_token,
@@ -877,13 +877,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         let (param, punct) = pair.into_tuple();
         match param {
             GenericParam::Lifetime(def) if def.bounds.is_empty() => {
-                generics.lifetimes.push_value(def.lifetime);
+                impl_generics.lifetimes.push_value(def.lifetime);
                 if let Some(punct) = punct {
-                    generics.lifetimes.push_punct(punct);
+                    impl_generics.lifetimes.push_punct(punct);
                 }
             }
             _ => {
-                let span = quote!(#impl_token #generics);
+                let span = quote!(#impl_token #impl_generics);
                 return Err(Error::new_spanned(
                     span,
                     "generic parameter on an impl is not supported yet",
@@ -907,15 +907,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         }
     }
 
-    let negative = negative_token.is_some();
     let ty = parse_type(&self_ty)?;
+    let ty_generics = match &ty {
+        Type::RustBox(ty)
+        | Type::RustVec(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
+        | Type::CxxVector(ty) => match &ty.inner {
+            Type::Ident(ident) => ident.generics.clone(),
+            _ => Lifetimes::default(),
+        },
+        Type::Ident(_)
+        | Type::Ref(_)
+        | Type::Str(_)
+        | Type::Fn(_)
+        | Type::Void(_)
+        | Type::SliceRef(_)
+        | Type::Array(_) => Lifetimes::default(),
+    };
+
+    let negative = negative_token.is_some();
     let brace_token = imp.brace_token;
 
     Ok(Api::Impl(Impl {
         impl_token,
-        generics,
+        impl_generics,
         negative,
         ty,
+        ty_generics,
         brace_token,
         negative_token,
     }))
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index aec21ae..757673d 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -192,14 +192,15 @@ impl ToTokens for Impl {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let Impl {
             impl_token,
-            generics,
+            impl_generics,
             negative: _,
             ty,
+            ty_generics: _,
             brace_token,
             negative_token,
         } = self;
         impl_token.to_tokens(tokens);
-        generics.to_tokens(tokens);
+        impl_generics.to_tokens(tokens);
         negative_token.to_tokens(tokens);
         ty.to_tokens(tokens);
         brace_token.surround(tokens, |_tokens| {});

From dc09c52a3ddef2e1ec93ad6fcefae4c40f5da522 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 05:52:08 +0000
Subject: [PATCH 1950/2232] Tweak enum generics error handling


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8bd8907..acf969d 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -174,16 +174,15 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         },
     );
 
-    let generics = &item.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
+    if !item.generics.params.is_empty() {
+        let vis = &item.vis;
         let enum_token = item.enum_token;
         let ident = &item.ident;
-        let where_clause = &generics.where_clause;
-        let span = quote!(#enum_token #ident #generics #where_clause);
-        return Err(Error::new_spanned(
-            span,
-            "enums with generic parameters are not allowed",
-        ));
+        let generics = &item.generics;
+        let span = quote!(#vis #enum_token #ident #generics);
+        cx.error(span, "enum with generic parameters is not supported");
+    } else if let Some(where_clause) = &item.generics.where_clause {
+        cx.error(where_clause, "enum with where-clause is not supported");
     }
 
     let mut variants = Vec::new();
diff --git a/tests/ui/generic_enum.rs b/tests/ui/generic_enum.rs
index 808856e..feeb94b 100644
--- a/tests/ui/generic_enum.rs
+++ b/tests/ui/generic_enum.rs
@@ -3,6 +3,14 @@ mod ffi {
     enum A<T> {
         Field,
     }
+
+    enum B<T> where T: Copy {
+        Field,
+    }
+
+    enum C where void: Copy {
+        Field,
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/generic_enum.stderr b/tests/ui/generic_enum.stderr
index bf267f7..ea83d7c 100644
--- a/tests/ui/generic_enum.stderr
+++ b/tests/ui/generic_enum.stderr
@@ -1,5 +1,17 @@
-error: enums with generic parameters are not allowed
+error: enum with generic parameters is not supported
  --> $DIR/generic_enum.rs:3:5
   |
 3 |     enum A<T> {
   |     ^^^^^^^^^
+
+error: enum with generic parameters is not supported
+ --> $DIR/generic_enum.rs:7:5
+  |
+7 |     enum B<T> where T: Copy {
+  |     ^^^^^^^^^
+
+error: enum with where-clause is not supported
+  --> $DIR/generic_enum.rs:11:12
+   |
+11 |     enum C where void: Copy {
+   |            ^^^^^^^^^^^^^^^^

From 233e60e231c33b3e3a082016f3e72a34cf69cf0c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 06:12:50 +0000
Subject: [PATCH 1951/2232] Resolve unnecessary_wraps clippy lint


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index acf969d..9d84799 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -39,10 +39,7 @@ pub fn parse_items(
                 Ok(strct) => apis.push(strct),
                 Err(err) => cx.push(err),
             },
-            Item::Enum(item) => match parse_enum(cx, item, namespace) {
-                Ok(enm) => apis.push(enm),
-                Err(err) => cx.push(err),
-            },
+            Item::Enum(item) => apis.push(parse_enum(cx, item, namespace)),
             Item::ForeignMod(foreign_mod) => {
                 parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
             }
@@ -153,7 +150,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     }))
 }
 
-fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<Api> {
+fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
     let mut doc = Doc::new();
     let mut derives = Vec::new();
     let mut repr = None;
@@ -218,7 +215,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         gt_token: None,
     };
 
-    Ok(Api::Enum(Enum {
+    Api::Enum(Enum {
         doc,
         derives,
         attrs,
@@ -231,7 +228,7 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Result<
         repr,
         repr_type,
         explicit_repr,
-    }))
+    })
 }
 
 fn parse_variant(

From 2b4f07d8d84f7460e0042a1618ed5f212965f61b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:06:59 +0000
Subject: [PATCH 1952/2232] Explicit instantiations for easy typecheck coverage in test suite


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 50a11da..827acc6 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -819,3 +819,23 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
   return std::unique_ptr<I>(new I());
 }
 } // namespace I
+
+// Instantiate any remaining class member functions not already covered above.
+// This is an easy way to at least typecheck anything missed by unit tests.
+// https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation
+// > When an explicit instantiation names a class template specialization, it
+// > serves as an explicit instantiation of the same kind (declaration or
+// > definition) of each of its non-inherited non-template members that has not
+// > been previously explicitly specialized in the translation unit.
+template struct rust::Box<tests::Shared>;
+template struct rust::Slice<const char>;
+template struct rust::Slice<const uint8_t>;
+template struct rust::Slice<uint8_t>;
+template struct rust::Slice<const tests::Shared>;
+template struct rust::Slice<tests::Shared>;
+template struct rust::Slice<const tests::R>;
+template struct rust::Slice<tests::R>;
+template struct rust::Vec<uint8_t>;
+template struct rust::Vec<rust::String>;
+template struct rust::Vec<tests::Shared>;
+template struct rust::Fn<size_t(rust::String)>;

From 7f59a693e4d058ba0abdf3d5f81ab0e215418227 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:07:41 +0000
Subject: [PATCH 1953/2232] Fix a wrong cast in Slice<T>::iterator::operator[]


    cxx-test-suite-2b81d5f39edd0bcf/out/cxxbridge/include/rust/cxx.h:559:11: error: invalid static_cast from type ‘char*’ to type ‘const unsigned char*’
      559 |   return *static_cast<T *>(pos);
          |           ^~~~~~~~~~~~~~~~~~~~~

Doing a reinterpret_cast<> instead matches what is done a few lines
above by Slice<T>::operator[].

---

diff --git a/include/cxx.h b/include/cxx.h
index 38261b7..7274a5c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -556,7 +556,7 @@ template <typename T>
 typename Slice<T>::iterator::reference Slice<T>::iterator::operator[](
     typename Slice<T>::iterator::difference_type n) const noexcept {
   auto pos = static_cast<char *>(this->pos) + this->stride * n;
-  return *static_cast<T *>(pos);
+  return *reinterpret_cast<T *>(pos);
 }
 
 template <typename T>

From 440e24a29a1226a1de05a1fa3656d50b9a1a5f5f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:27:15 +0000
Subject: [PATCH 1954/2232] MSVC workaround for "C linkage function cannot return C++ class"


MSVC fails to compile code like the following unless there is an
explicit instantiation of the class template:

    template <typename T>
    class slice {};

    //template class slice<int>;

    extern "C" slice<int> repro() { return {}; }

Error:

    <source>(6): error C2526: 'repro': C linkage function cannot return C++ class 'slice<int>'
    <source>(6): note: see declaration of 'slice<int>'
    <source>(6): error C2562: 'repro': 'void' function returning a value
    <source>(6): note: see declaration of 'repro'
    Compiler returned: 2

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 73a4b8c..3e79548 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -119,6 +119,22 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    out.set_namespace(Default::default());
+
+    out.next_section();
+    for ty in out.types {
+        // MSVC workaround for "C linkage function cannot return C++ class"
+        // error. Apparently the compiler fails to perform implicit
+        // instantiations as part of an extern declaration. Instead we
+        // instantiate explicitly.
+        // See https://stackoverflow.com/a/57429504/6086311.
+        if let Type::SliceRef(_) = ty {
+            write!(out, "template struct ");
+            write_type(out, ty);
+            writeln!(out, ";");
+        }
+    }
+
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 827acc6..3841cb2 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -828,13 +828,6 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
 template struct rust::Box<tests::Shared>;
-template struct rust::Slice<const char>;
-template struct rust::Slice<const uint8_t>;
-template struct rust::Slice<uint8_t>;
-template struct rust::Slice<const tests::Shared>;
-template struct rust::Slice<tests::Shared>;
-template struct rust::Slice<const tests::R>;
-template struct rust::Slice<tests::R>;
 template struct rust::Vec<uint8_t>;
 template struct rust::Vec<rust::String>;
 template struct rust::Vec<tests::Shared>;

From 7f65e7cda73edd27c785519234754310ad90f4cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:34:19 +0000
Subject: [PATCH 1955/2232] Remove rust::Str repr conversion on the C++ side


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index b5c6e4d..ddfd7f6 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -20,8 +20,6 @@ pub struct Builtins<'a> {
     pub maybe_uninit: bool,
     pub trycatch: bool,
     pub ptr_len: bool,
-    pub rust_str_new_unchecked: bool,
-    pub rust_str_repr: bool,
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
     pub exception: bool,
@@ -234,33 +232,6 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Str> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_str_new_unchecked {
-            writeln!(
-                out,
-                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    Str str;");
-            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
-            writeln!(out, "    str.len = repr.len;");
-            writeln!(out, "    return str;");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_str_repr {
-            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(
-                out,
-                "    return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
-            );
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
     if builtin.rust_slice_new || builtin.rust_slice_repr {
         out.next_section();
         writeln!(out, "template <typename T>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 73a4b8c..ff63f9f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -733,10 +733,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => {
-            out.builtin.rust_str_repr = true;
-            write!(out, "::rust::impl<::rust::Str>::repr(");
-        }
         Some(ty @ Type::SliceRef(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
             write!(out, "::rust::impl<");
@@ -759,13 +755,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         } else if let Type::UniquePtr(_) = &arg.ty {
             write_type(out, &arg.ty);
             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.name.cxx,
-            );
         } else if arg.ty == RustString {
             out.builtin.unsafe_bitcopy = true;
             write!(
@@ -796,7 +785,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -995,10 +984,6 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::Str(_) => {
-                out.builtin.rust_str_new_unchecked = true;
-                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
-            }
             Type::SliceRef(_) => {
                 out.builtin.rust_slice_new = true;
                 write!(out, "::rust::impl<");
@@ -1023,10 +1008,6 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => {
-                out.builtin.rust_str_repr = true;
-                write!(out, "::rust::impl<::rust::Str>::repr(");
-            }
             Type::SliceRef(_) => {
                 out.builtin.rust_slice_repr = true;
                 write!(out, "::rust::impl<");
@@ -1040,7 +1021,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRef(_) => write!(out, ")"),
+            Type::SliceRef(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -1062,7 +1043,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::SliceRef(_) = ret {
                 write!(out, ")");
             }
         }
@@ -1133,7 +1114,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
+        Some(Type::SliceRef(_)) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
@@ -1148,7 +1129,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) | Type::SliceRef(_) => {
+        Type::SliceRef(_) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index d33092c..e91675d 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -20,7 +20,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
 }
 
 #[test]
@@ -30,5 +30,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
 }

From 113108931bb5b6a3dac5c18a97e231685986a3ef Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:45:54 +0000
Subject: [PATCH 1956/2232] Merge pull request #638 from dtolnay/podstr


Remove rust::Str repr conversion in C++
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index b5c6e4d..ddfd7f6 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -20,8 +20,6 @@ pub struct Builtins<'a> {
     pub maybe_uninit: bool,
     pub trycatch: bool,
     pub ptr_len: bool,
-    pub rust_str_new_unchecked: bool,
-    pub rust_str_repr: bool,
     pub rust_slice_new: bool,
     pub rust_slice_repr: bool,
     pub exception: bool,
@@ -234,33 +232,6 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
-        out.next_section();
-        writeln!(out, "template <>");
-        writeln!(out, "class impl<Str> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_str_new_unchecked {
-            writeln!(
-                out,
-                "  static Str new_unchecked(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    Str str;");
-            writeln!(out, "    str.ptr = static_cast<const char *>(repr.ptr);");
-            writeln!(out, "    str.len = repr.len;");
-            writeln!(out, "    return str;");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_str_repr {
-            writeln!(out, "  static repr::PtrLen repr(Str str) noexcept {{");
-            writeln!(
-                out,
-                "    return repr::PtrLen{{const_cast<char *>(str.ptr), str.len}};",
-            );
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
     if builtin.rust_slice_new || builtin.rust_slice_repr {
         out.next_section();
         writeln!(out, "template <typename T>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 73a4b8c..ff63f9f 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -733,10 +733,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) if !indirect_return => {
-            out.builtin.rust_str_repr = true;
-            write!(out, "::rust::impl<::rust::Str>::repr(");
-        }
         Some(ty @ Type::SliceRef(_)) if !indirect_return => {
             out.builtin.rust_slice_repr = true;
             write!(out, "::rust::impl<");
@@ -759,13 +755,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
         } else if let Type::UniquePtr(_) = &arg.ty {
             write_type(out, &arg.ty);
             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.name.cxx,
-            );
         } else if arg.ty == RustString {
             out.builtin.unsafe_bitcopy = true;
             write!(
@@ -796,7 +785,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
+        Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -995,10 +984,6 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::Str(_) => {
-                out.builtin.rust_str_new_unchecked = true;
-                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
-            }
             Type::SliceRef(_) => {
                 out.builtin.rust_slice_new = true;
                 write!(out, "::rust::impl<");
@@ -1023,10 +1008,6 @@ fn write_rust_function_shim_impl(
             write!(out, ", ");
         }
         match &arg.ty {
-            Type::Str(_) => {
-                out.builtin.rust_str_repr = true;
-                write!(out, "::rust::impl<::rust::Str>::repr(");
-            }
             Type::SliceRef(_) => {
                 out.builtin.rust_slice_repr = true;
                 write!(out, "::rust::impl<");
@@ -1040,7 +1021,7 @@ fn write_rust_function_shim_impl(
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::Str(_) | Type::SliceRef(_) => write!(out, ")"),
+            Type::SliceRef(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -1062,7 +1043,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::SliceRef(_) = ret {
                 write!(out, ")");
             }
         }
@@ -1133,7 +1114,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
+        Some(Type::SliceRef(_)) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
@@ -1148,7 +1129,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::Str(_) | Type::SliceRef(_) => {
+        Type::SliceRef(_) => {
             out.builtin.ptr_len = true;
             write!(out, "::rust::repr::PtrLen ");
         }
diff --git a/tests/cxx_gen.rs b/tests/cxx_gen.rs
index d33092c..e91675d 100644
--- a/tests/cxx_gen.rs
+++ b/tests/cxx_gen.rs
@@ -20,7 +20,7 @@ fn test_extern_c_function() {
     let output = str::from_utf8(&generated.implementation).unwrap();
     // To avoid continual breakage we won't test every byte.
     // Let's look for the major features.
-    assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
 }
 
 #[test]
@@ -30,5 +30,5 @@ fn test_impl_annotation() {
     let source = BRIDGE0.parse().unwrap();
     let generated = generate_header_and_cc(source, &opt).unwrap();
     let output = str::from_utf8(&generated.implementation).unwrap();
-    assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::repr::PtrLen foo)"));
+    assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
 }

From c45b6766f57c9c586919fc6f6dc217d5a864c8a5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:46:05 +0000
Subject: [PATCH 1957/2232] Merge pull request #637 from dtolnay/msvc


MSVC workaround for "C linkage function cannot return C++ class"
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index ff63f9f..5b67e09 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -119,6 +119,22 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    out.set_namespace(Default::default());
+
+    out.next_section();
+    for ty in out.types {
+        // MSVC workaround for "C linkage function cannot return C++ class"
+        // error. Apparently the compiler fails to perform implicit
+        // instantiations as part of an extern declaration. Instead we
+        // instantiate explicitly.
+        // See https://stackoverflow.com/a/57429504/6086311.
+        if let Type::SliceRef(_) = ty {
+            write!(out, "template struct ");
+            write_type(out, ty);
+            writeln!(out, ";");
+        }
+    }
+
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 827acc6..3841cb2 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -828,13 +828,6 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
 template struct rust::Box<tests::Shared>;
-template struct rust::Slice<const char>;
-template struct rust::Slice<const uint8_t>;
-template struct rust::Slice<uint8_t>;
-template struct rust::Slice<const tests::Shared>;
-template struct rust::Slice<tests::Shared>;
-template struct rust::Slice<const tests::R>;
-template struct rust::Slice<tests::R>;
 template struct rust::Vec<uint8_t>;
 template struct rust::Vec<rust::String>;
 template struct rust::Vec<tests::Shared>;

From 681f5c82cd7b3c763f1bef134032aab0eaf6ee99 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:46:49 +0000
Subject: [PATCH 1958/2232] Remove rust::Slice repr conversion on the C++ side


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index ddfd7f6..7b15b61 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -20,8 +20,6 @@ pub struct Builtins<'a> {
     pub maybe_uninit: bool,
     pub trycatch: bool,
     pub ptr_len: bool,
-    pub rust_slice_new: bool,
-    pub rust_slice_repr: bool,
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
@@ -232,31 +230,6 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.rust_slice_new || builtin.rust_slice_repr {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl<Slice<T>> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_slice_new {
-            writeln!(
-                out,
-                "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    return {{static_cast<T *>(repr.ptr), repr.len}};");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_slice_repr {
-            include.type_traits = true;
-            writeln!(
-                out,
-                "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
-            );
-            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
     if builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5b67e09..489d85a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -747,15 +747,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     } else if efn.ret.is_some() {
         write!(out, "return ");
     }
-    match &efn.ret {
-        Some(Type::Ref(_)) => write!(out, "&"),
-        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
-            out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<");
-            write_type(out, ty);
-            write!(out, ">::repr(");
-        }
-        _ => {}
+    if let Some(Type::Ref(_)) = efn.ret {
+        write!(out, "&");
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.name.rust),
@@ -782,14 +775,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             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<");
-            if slice.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type_space(out, &slice.inner);
-            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.name.cxx);
@@ -801,7 +786,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -1000,12 +984,6 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::SliceRef(_) => {
-                out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<");
-                write_type(out, ret);
-                write!(out, ">::slice(");
-            }
             _ => {}
         }
     }
@@ -1023,21 +1001,13 @@ fn write_rust_function_shim_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        match &arg.ty {
-            Type::SliceRef(_) => {
-                out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<");
-                write_type(out, &arg.ty);
-                write!(out, ">::repr(");
-            }
-            ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
-            _ => {}
+        if out.types.needs_indirect_abi(&arg.ty) {
+            write!(out, "&");
         }
         write!(out, "{}", arg.name.cxx);
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::SliceRef(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -1059,7 +1029,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::SliceRef(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
                 write!(out, ")");
             }
         }
@@ -1130,10 +1100,6 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::SliceRef(_)) => {
-            out.builtin.ptr_len = true;
-            write!(out, "::rust::repr::PtrLen ");
-        }
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -1145,10 +1111,6 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::SliceRef(_) => {
-            out.builtin.ptr_len = true;
-            write!(out, "::rust::repr::PtrLen ");
-        }
         _ => write_type_space(out, &arg.ty),
     }
     if out.types.needs_indirect_abi(&arg.ty) {
diff --git a/include/cxx.h b/include/cxx.h
index 7274a5c..d50045a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -120,7 +120,6 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -174,7 +173,6 @@ public:
   iterator end() const noexcept;
 
 private:
-  friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;

From b4ea5b094328dcc100868f759223481a23469f8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 08:52:40 +0000
Subject: [PATCH 1959/2232] Merge pull request #636 from dtolnay/pod


Remove rust::Slice repr conversion in C++
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index ddfd7f6..7b15b61 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -20,8 +20,6 @@ pub struct Builtins<'a> {
     pub maybe_uninit: bool,
     pub trycatch: bool,
     pub ptr_len: bool,
-    pub rust_slice_new: bool,
-    pub rust_slice_repr: bool,
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
@@ -232,31 +230,6 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.rust_slice_new || builtin.rust_slice_repr {
-        out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl<Slice<T>> final {{");
-        writeln!(out, "public:");
-        if builtin.rust_slice_new {
-            writeln!(
-                out,
-                "  static Slice<T> slice(repr::PtrLen repr) noexcept {{",
-            );
-            writeln!(out, "    return {{static_cast<T *>(repr.ptr), repr.len}};");
-            writeln!(out, "  }}");
-        }
-        if builtin.rust_slice_repr {
-            include.type_traits = true;
-            writeln!(
-                out,
-                "  static repr::PtrLen repr(Slice<T> slice) noexcept {{",
-            );
-            writeln!(out, "    return repr::PtrLen{{slice.ptr, slice.len}};");
-            writeln!(out, "  }}");
-        }
-        writeln!(out, "}};");
-    }
-
     if builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index 5b67e09..489d85a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -747,15 +747,8 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     } else if efn.ret.is_some() {
         write!(out, "return ");
     }
-    match &efn.ret {
-        Some(Type::Ref(_)) => write!(out, "&"),
-        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
-            out.builtin.rust_slice_repr = true;
-            write!(out, "::rust::impl<");
-            write_type(out, ty);
-            write!(out, ">::repr(");
-        }
-        _ => {}
+    if let Some(Type::Ref(_)) = efn.ret {
+        write!(out, "&");
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.name.rust),
@@ -782,14 +775,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
             out.builtin.unsafe_bitcopy = true;
             write_type(out, &arg.ty);
             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<");
-            if slice.mutability.is_none() {
-                write!(out, "const ");
-            }
-            write_type_space(out, &slice.inner);
-            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.name.cxx);
@@ -801,7 +786,6 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -1000,12 +984,6 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
-            Type::SliceRef(_) => {
-                out.builtin.rust_slice_new = true;
-                write!(out, "::rust::impl<");
-                write_type(out, ret);
-                write!(out, ">::slice(");
-            }
             _ => {}
         }
     }
@@ -1023,21 +1001,13 @@ fn write_rust_function_shim_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        match &arg.ty {
-            Type::SliceRef(_) => {
-                out.builtin.rust_slice_repr = true;
-                write!(out, "::rust::impl<");
-                write_type(out, &arg.ty);
-                write!(out, ">::repr(");
-            }
-            ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
-            _ => {}
+        if out.types.needs_indirect_abi(&arg.ty) {
+            write!(out, "&");
         }
         write!(out, "{}", arg.name.cxx);
         match &arg.ty {
             Type::RustBox(_) => write!(out, ".into_raw()"),
             Type::UniquePtr(_) => write!(out, ".release()"),
-            Type::SliceRef(_) => write!(out, ")"),
             ty if ty != RustString && out.types.needs_indirect_abi(ty) => write!(out, "$.value"),
             _ => {}
         }
@@ -1059,7 +1029,7 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::SliceRef(_) = ret {
+            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
                 write!(out, ")");
             }
         }
@@ -1130,10 +1100,6 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(Type::SliceRef(_)) => {
-            out.builtin.ptr_len = true;
-            write!(out, "::rust::repr::PtrLen ");
-        }
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }
@@ -1145,10 +1111,6 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var) {
             write_type_space(out, &ty.inner);
             write!(out, "*");
         }
-        Type::SliceRef(_) => {
-            out.builtin.ptr_len = true;
-            write!(out, "::rust::repr::PtrLen ");
-        }
         _ => write_type_space(out, &arg.ty),
     }
     if out.types.needs_indirect_abi(&arg.ty) {
diff --git a/include/cxx.h b/include/cxx.h
index 7274a5c..d50045a 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -120,7 +120,6 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  friend impl<Str>;
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -174,7 +173,6 @@ public:
   iterator end() const noexcept;
 
 private:
-  friend impl<Slice>;
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;

From 14dc7929808297726e32d45e1b2d0205ae4b5abe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 09:14:44 +0000
Subject: [PATCH 1960/2232] Restrict MSVC instantiation workaround to return positions only


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 489d85a..97610a4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::UnorderedMap as Map;
-use crate::syntax::set::UnorderedSet;
+use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
@@ -121,19 +121,24 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     out.set_namespace(Default::default());
 
+    // MSVC workaround for "C linkage function cannot return C++ class" error.
+    // Apparently the compiler fails to perform implicit instantiations as part
+    // of an extern declaration. Instead we instantiate explicitly.
+    // See https://stackoverflow.com/a/57429504/6086311.
     out.next_section();
-    for ty in out.types {
-        // MSVC workaround for "C linkage function cannot return C++ class"
-        // error. Apparently the compiler fails to perform implicit
-        // instantiations as part of an extern declaration. Instead we
-        // instantiate explicitly.
-        // See https://stackoverflow.com/a/57429504/6086311.
-        if let Type::SliceRef(_) = ty {
-            write!(out, "template struct ");
-            write_type(out, ty);
-            writeln!(out, ";");
+    let mut slice_in_return_position = OrderedSet::new();
+    for api in apis {
+        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
+            if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+                slice_in_return_position.insert(ty);
+            }
         }
     }
+    for ty in &slice_in_return_position {
+        write!(out, "template struct ");
+        write_type(out, ty);
+        writeln!(out, ";");
+    }
 
     out.next_section();
     for api in apis {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3841cb2..f043d81 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -828,6 +828,10 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
 template struct rust::Box<tests::Shared>;
+template struct rust::Slice<const tests::Shared>;
+template struct rust::Slice<tests::Shared>;
+template struct rust::Slice<const tests::R>;
+template struct rust::Slice<tests::R>;
 template struct rust::Vec<uint8_t>;
 template struct rust::Vec<rust::String>;
 template struct rust::Vec<tests::Shared>;

From d00bc40aa796d670a5ead765998b748d3b98213e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 09:29:43 +0000
Subject: [PATCH 1961/2232] Merge pull request #639 from dtolnay/msvc


Restrict MSVC instantiation workaround to return positions only
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 489d85a..97610a4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::UnorderedMap as Map;
-use crate::syntax::set::UnorderedSet;
+use crate::syntax::set::{OrderedSet, UnorderedSet};
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
@@ -121,19 +121,24 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     out.set_namespace(Default::default());
 
+    // MSVC workaround for "C linkage function cannot return C++ class" error.
+    // Apparently the compiler fails to perform implicit instantiations as part
+    // of an extern declaration. Instead we instantiate explicitly.
+    // See https://stackoverflow.com/a/57429504/6086311.
     out.next_section();
-    for ty in out.types {
-        // MSVC workaround for "C linkage function cannot return C++ class"
-        // error. Apparently the compiler fails to perform implicit
-        // instantiations as part of an extern declaration. Instead we
-        // instantiate explicitly.
-        // See https://stackoverflow.com/a/57429504/6086311.
-        if let Type::SliceRef(_) = ty {
-            write!(out, "template struct ");
-            write_type(out, ty);
-            writeln!(out, ";");
+    let mut slice_in_return_position = OrderedSet::new();
+    for api in apis {
+        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
+            if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+                slice_in_return_position.insert(ty);
+            }
         }
     }
+    for ty in &slice_in_return_position {
+        write!(out, "template struct ");
+        write_type(out, ty);
+        writeln!(out, ";");
+    }
 
     out.next_section();
     for api in apis {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3841cb2..f043d81 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -828,6 +828,10 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
 template struct rust::Box<tests::Shared>;
+template struct rust::Slice<const tests::Shared>;
+template struct rust::Slice<tests::Shared>;
+template struct rust::Slice<const tests::R>;
+template struct rust::Slice<tests::R>;
 template struct rust::Vec<uint8_t>;
 template struct rust::Vec<rust::String>;
 template struct rust::Vec<tests::Shared>;

From 3351bc7898e222d494562f3d7a6fb7e4d40b5665 Mon Sep 17 00:00:00 2001
From: Cameron Pickett <pickett.cj@gmail.com>
Date: Jan 02 2021 12:21:24 +0000
Subject: [PATCH 1962/2232] Fix warning mismatching struct and class


Fix for warning when running cargo test.

```
warning: /Users/pickett/Documents/GitHub/cxx/target/debug/build/cxx-test-suite-de711daed7f2e46d/out/cxxbridge/sources/tests/ffi/lib.rs.cc:1256:10: warning: struct template 'Slice' was previously declared as a class template; this is valid, but may result in linker errors under the Microsoft C++ ABI [-Wmismatched-tags]
warning: template struct ::rust::Slice<const char>;
warning:          ^
warning: /Users/pickett/Documents/GitHub/cxx/target/debug/build/cxx-test-suite-de711daed7f2e46d/out/cxxbridge/include/rust/cxx.h:146:7: note: previous use is here
warning: class Slice final
warning:       ^
warning: /Users/pickett/Documents/GitHub/cxx/target/debug/build/cxx-test-suite-de711daed7f2e46d/out/cxxbridge/sources/tests/ffi/lib.rs.cc:1256:10: note: did you mean class here?
warning: template struct ::rust::Slice<const char>;
warning:          ^~~~~~
warning:          class
```

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 97610a4..609814c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -135,7 +135,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
     for ty in &slice_in_return_position {
-        write!(out, "template struct ");
+        write!(out, "template class ");
         write_type(out, ty);
         writeln!(out, ";");
     }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f043d81..96c5cab 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -827,12 +827,12 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > serves as an explicit instantiation of the same kind (declaration or
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
-template struct rust::Box<tests::Shared>;
-template struct rust::Slice<const tests::Shared>;
-template struct rust::Slice<tests::Shared>;
-template struct rust::Slice<const tests::R>;
-template struct rust::Slice<tests::R>;
-template struct rust::Vec<uint8_t>;
-template struct rust::Vec<rust::String>;
-template struct rust::Vec<tests::Shared>;
-template struct rust::Fn<size_t(rust::String)>;
+template class rust::Box<tests::Shared>;
+template class rust::Slice<const tests::Shared>;
+template class rust::Slice<tests::Shared>;
+template class rust::Slice<const tests::R>;
+template class rust::Slice<tests::R>;
+template class rust::Vec<uint8_t>;
+template class rust::Vec<rust::String>;
+template class rust::Vec<tests::Shared>;
+template class rust::Fn<size_t(rust::String)>;

From f91e4731a8f61c71285f2867cc7819c47fec7d62 Mon Sep 17 00:00:00 2001
From: Cameron Pickett <pickett.cj@gmail.com>
Date: Jan 02 2021 14:31:19 +0000
Subject: [PATCH 1963/2232] Include a launch config for cargo tests


First time using VS Code to develop and I found this config made it easier to jump into breakpoint debugging the cargo tests

---

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 244f5c4..429949b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,6 +12,18 @@
                     "kind": "bin"
                 }
             }
-        }
+        },
+        {
+            "name": "Debug cargo tests",
+            "type": "lldb",
+            "request": "launch",
+            "cargo": {
+                "args": ["test", "--no-run"],
+                "filter": {
+                    "name": "test",
+                    "kind": "test"
+                }
+            }
+        },
     ]
 }

From f45f899cd043a0cbce13513a18b5f9d67d0e17ea Mon Sep 17 00:00:00 2001
From: Cameron Pickett <pickett.cj@gmail.com>
Date: Jan 02 2021 18:38:05 +0000
Subject: [PATCH 1964/2232] Add swap members + ADL functions


Addresses #58.

Adds `swap` members to each of `Slice`, `Str`, `Vec`, `Box`, and `String`. Also adds private friend functions so that Argument Dependent Lookup may function via the `using std::swap;` idiom.

---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 91ccda4..5f2644b 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -25,6 +25,8 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
+  void swap(Box &) noexcept;
+
   Box &operator=(const Box &);
   Box &operator=(Box &&) noexcept;
 
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fe1691e..2354f53 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -32,6 +32,8 @@ public:
   size_t length() const noexcept;
   bool empty() const noexcept;
 
+  void swap(Slice & rhs) noexcept;
+
   T &operator[](size_t n) const noexcept;
   T &at(size_t n) const;
   T &front() const noexcept;
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 999727c..bc85909 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -31,6 +31,8 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  void swap(Str & rhs) noexcept;
+
   using iterator = const char *;
   using const_iterator = const char *;
   const_iterator begin() const noexcept;
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 8dc1ee4..02790c3 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -35,6 +35,8 @@ public:
 
   const char *c_str() noexcept;
 
+  void swap(String & rhs) noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 39c1da1..e2af25c 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -31,6 +31,8 @@ public:
   const T *data() const noexcept;
   T *data() noexcept;
   size_t capacity() const noexcept;
+  
+  void swap(Vec & rhs) noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/include/cxx.h b/include/cxx.h
index d50045a..8b47b96 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,6 +56,8 @@ public:
 
   const char *c_str() noexcept;
 
+  void swap(String & rhs) noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
@@ -77,9 +79,14 @@ public:
   String(unsafe_bitcopy_t, const String &) noexcept;
 
 private:
+  friend void swap(String& lhs, String& rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Size and alignment statically verified by rust_string.rs.
   std::array<std::uintptr_t, 3> repr;
 };
+
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR
@@ -101,6 +108,8 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
+  void swap(Str & rhs) noexcept;
+
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
@@ -120,6 +129,10 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
+  friend void swap(Str & lhs, Str & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -159,6 +172,8 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
+  void swap(Slice & rhs) noexcept;
+
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
   T &front() const noexcept;
@@ -173,6 +188,10 @@ public:
   iterator end() const noexcept;
 
 private:
+  friend void swap(Slice<T> & lhs, Slice<T> & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;
@@ -235,6 +254,8 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
+  void swap(Box & rhs) noexcept;
+
   Box &operator=(const Box &);
   Box &operator=(Box &&) noexcept;
 
@@ -259,6 +280,11 @@ private:
   class allocation;
   Box(uninit) noexcept;
   void drop() noexcept;
+
+  friend void swap(Box & lhs, Box & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   T *ptr;
 };
 #endif // CXXBRIDGE1_RUST_BOX
@@ -285,6 +311,8 @@ public:
   T *data() noexcept;
   std::size_t capacity() const noexcept;
 
+  void swap(Vec & rhs) noexcept;
+
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
   const T &front() const noexcept;
@@ -319,6 +347,10 @@ private:
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
 
+  friend void swap(Vec<T> & lhs, Vec<T> & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
 };
@@ -507,6 +539,13 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
+void Slice<T>::swap(Slice<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+  swap(this->len, rhs.len);
+}
+
+template <typename T>
 bool Slice<T>::empty() const noexcept {
   return this->len == 0;
 }
@@ -712,6 +751,12 @@ Box<T>::Box(T &&val) {
 }
 
 template <typename T>
+void Box<T>::swap(Box<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+}
+
+template <typename T>
 Box<T>::~Box() noexcept {
   if (this->ptr) {
     this->drop();
@@ -843,6 +888,12 @@ T *Vec<T>::data() noexcept {
 }
 
 template <typename T>
+void Vec<T>::swap(Vec<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
+template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
diff --git a/src/cxx.cc b/src/cxx.cc
index 6b71656..a23fd8c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -130,6 +130,11 @@ const char *String::c_str() noexcept {
   return ptr;
 }
 
+void String::swap(String& rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
 }
@@ -210,6 +215,12 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+void Str::swap(Str& rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+  swap(this->len, rhs.len);
+}
+
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f043d81..67463d6 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -752,8 +752,12 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r->get() == 2020);
   ASSERT(r->set(2021) == 2021);
   ASSERT(r->get() == 2021);
-  ASSERT(r->set(2020) == 2020);
+  auto r2 = r_return_box();
+  swap(r, r2);
   ASSERT(r->get() == 2020);
+  ASSERT(r2->get() == 2021);
+
+
   ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
@@ -786,6 +790,23 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(strncmp(cstring.c_str(), "test", 5) == 0);
   ASSERT(cstring.length() == 4);
 
+  rust::String other_cstring = "foo";
+  swap(cstring, other_cstring);
+  ASSERT(cstring == "foo");
+  ASSERT(other_cstring == "test");
+
+  rust::Str cstr = "test";
+  rust::Str other_cstr = "foo";
+  swap(cstr, other_cstr);
+  ASSERT(cstr == "foo");
+  ASSERT(other_cstr == "test");
+
+  rust::Vec<int> vec1{1, 2};
+  rust::Vec<int> vec2{3, 4};
+  swap(vec1, vec2);
+  ASSERT(vec1[0] == 3 && vec1[1] == 4);
+  ASSERT(vec2[0] == 1 && vec2[1] == 2);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 3b338886fc713a11c7af8bd1578fa55e44a5ee30 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 19:29:59 +0000
Subject: [PATCH 1965/2232] Merge pull request #640 from capickett/abi


Fix warning mismatching struct and class
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 97610a4..609814c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -135,7 +135,7 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
     for ty in &slice_in_return_position {
-        write!(out, "template struct ");
+        write!(out, "template class ");
         write_type(out, ty);
         writeln!(out, ";");
     }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index f043d81..96c5cab 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -827,12 +827,12 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > serves as an explicit instantiation of the same kind (declaration or
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
-template struct rust::Box<tests::Shared>;
-template struct rust::Slice<const tests::Shared>;
-template struct rust::Slice<tests::Shared>;
-template struct rust::Slice<const tests::R>;
-template struct rust::Slice<tests::R>;
-template struct rust::Vec<uint8_t>;
-template struct rust::Vec<rust::String>;
-template struct rust::Vec<tests::Shared>;
-template struct rust::Fn<size_t(rust::String)>;
+template class rust::Box<tests::Shared>;
+template class rust::Slice<const tests::Shared>;
+template class rust::Slice<tests::Shared>;
+template class rust::Slice<const tests::R>;
+template class rust::Slice<tests::R>;
+template class rust::Vec<uint8_t>;
+template class rust::Vec<rust::String>;
+template class rust::Vec<tests::Shared>;
+template class rust::Fn<size_t(rust::String)>;

From 958f875178eddd5ed1074f58a51e134501b4f31c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 19:33:58 +0000
Subject: [PATCH 1966/2232] Merge pull request #641 from capickett/cargo_tests


Include a launch config for cargo tests
---

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 244f5c4..429949b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,6 +12,18 @@
                     "kind": "bin"
                 }
             }
-        }
+        },
+        {
+            "name": "Debug cargo tests",
+            "type": "lldb",
+            "request": "launch",
+            "cargo": {
+                "args": ["test", "--no-run"],
+                "filter": {
+                    "name": "test",
+                    "kind": "test"
+                }
+            }
+        },
     ]
 }

From 357d9ed5e418d97600edeb84d75fec9230a96cca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 19:34:23 +0000
Subject: [PATCH 1967/2232] Fix invalid json in vscode launch.json


---

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 429949b..0218f47 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -24,6 +24,6 @@
                     "kind": "test"
                 }
             }
-        },
+        }
     ]
 }

From 672c464c72b7fef40c9f83f1f0532b13e35347c9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 19:55:25 +0000
Subject: [PATCH 1968/2232] Remove implicit Box copy operations to match unique_ptr


---

diff --git a/include/cxx.h b/include/cxx.h
index d50045a..d32e17f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -228,14 +228,12 @@ public:
   using pointer = typename std::add_pointer<T>::type;
 
   Box() = delete;
-  Box(const Box &);
   Box(Box &&) noexcept;
   ~Box() noexcept;
 
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(const Box &);
   Box &operator=(Box &&) noexcept;
 
   const T *operator->() const noexcept;
@@ -688,9 +686,6 @@ public:
 };
 
 template <typename T>
-Box<T>::Box(const Box &other) : Box(*other) {}
-
-template <typename T>
 Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) {
   other.ptr = nullptr;
 }
@@ -719,19 +714,6 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(const Box &other) {
-  if (this->ptr) {
-    **this = *other;
-  } else {
-    allocation alloc;
-    ::new (alloc.ptr) T(*other);
-    this->ptr = alloc.ptr;
-    alloc.ptr = nullptr;
-  }
-  return *this;
-}
-
-template <typename T>
 Box<T> &Box<T>::operator=(Box &&other) noexcept {
   if (this->ptr) {
     this->drop();
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 96c5cab..39d97bd 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -64,9 +64,8 @@ rust::Box<R> c_return_box() {
   Shared shared{0};
   rust::Box<Shared> box{shared}; // explicit constructor from const T&
   rust::Box<Shared> other{std::move(shared)}; // explicit constructor from T&&
-  box = other;                                // copy assignment
   box = std::move(other);                     // move assignment
-  rust::Box<Shared> box2(box);                // copy constructor
+  rust::Box<Shared> box2(*box);               // copy from another Box
   rust::Box<Shared> other2(std::move(other)); // move constructor
   rust::Box<Shared>::in_place(shared.z);      // placement static factory
   rust::Box<Shared>::in_place<size_t>(0);

From 756556e23c56632e1a28fac67debed1b008d1fd3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:04:19 +0000
Subject: [PATCH 1969/2232] Merge pull request 642 from capickett/swap


---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 91ccda4..5f2644b 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -25,6 +25,8 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
+  void swap(Box &) noexcept;
+
   Box &operator=(const Box &);
   Box &operator=(Box &&) noexcept;
 
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fe1691e..2354f53 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -32,6 +32,8 @@ public:
   size_t length() const noexcept;
   bool empty() const noexcept;
 
+  void swap(Slice & rhs) noexcept;
+
   T &operator[](size_t n) const noexcept;
   T &at(size_t n) const;
   T &front() const noexcept;
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 999727c..bc85909 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -31,6 +31,8 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
+  void swap(Str & rhs) noexcept;
+
   using iterator = const char *;
   using const_iterator = const char *;
   const_iterator begin() const noexcept;
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 8dc1ee4..02790c3 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -35,6 +35,8 @@ public:
 
   const char *c_str() noexcept;
 
+  void swap(String & rhs) noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 39c1da1..e2af25c 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -31,6 +31,8 @@ public:
   const T *data() const noexcept;
   T *data() noexcept;
   size_t capacity() const noexcept;
+  
+  void swap(Vec & rhs) noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/include/cxx.h b/include/cxx.h
index d32e17f..f441280 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,6 +56,8 @@ public:
 
   const char *c_str() noexcept;
 
+  void swap(String & rhs) noexcept;
+
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
@@ -77,9 +79,14 @@ public:
   String(unsafe_bitcopy_t, const String &) noexcept;
 
 private:
+  friend void swap(String& lhs, String& rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Size and alignment statically verified by rust_string.rs.
   std::array<std::uintptr_t, 3> repr;
 };
+
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR
@@ -101,6 +108,8 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
+  void swap(Str & rhs) noexcept;
+
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
@@ -120,6 +129,10 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
+  friend void swap(Str & lhs, Str & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -159,6 +172,8 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
+  void swap(Slice & rhs) noexcept;
+
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
   T &front() const noexcept;
@@ -173,6 +188,10 @@ public:
   iterator end() const noexcept;
 
 private:
+  friend void swap(Slice<T> & lhs, Slice<T> & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;
@@ -234,6 +253,8 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
+  void swap(Box & rhs) noexcept;
+
   Box &operator=(Box &&) noexcept;
 
   const T *operator->() const noexcept;
@@ -257,6 +278,11 @@ private:
   class allocation;
   Box(uninit) noexcept;
   void drop() noexcept;
+
+  friend void swap(Box & lhs, Box & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   T *ptr;
 };
 #endif // CXXBRIDGE1_RUST_BOX
@@ -283,6 +309,8 @@ public:
   T *data() noexcept;
   std::size_t capacity() const noexcept;
 
+  void swap(Vec & rhs) noexcept;
+
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
   const T &front() const noexcept;
@@ -317,6 +345,10 @@ private:
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
 
+  friend void swap(Vec<T> & lhs, Vec<T> & rhs) noexcept {
+    lhs.swap(rhs);
+  }
+
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
 };
@@ -505,6 +537,13 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
+void Slice<T>::swap(Slice<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+  swap(this->len, rhs.len);
+}
+
+template <typename T>
 bool Slice<T>::empty() const noexcept {
   return this->len == 0;
 }
@@ -707,6 +746,12 @@ Box<T>::Box(T &&val) {
 }
 
 template <typename T>
+void Box<T>::swap(Box<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+}
+
+template <typename T>
 Box<T>::~Box() noexcept {
   if (this->ptr) {
     this->drop();
@@ -825,6 +870,12 @@ T *Vec<T>::data() noexcept {
 }
 
 template <typename T>
+void Vec<T>::swap(Vec<T> & rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
+template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
diff --git a/src/cxx.cc b/src/cxx.cc
index 6b71656..a23fd8c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -130,6 +130,11 @@ const char *String::c_str() noexcept {
   return ptr;
 }
 
+void String::swap(String& rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
 }
@@ -210,6 +215,12 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+void Str::swap(Str& rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+  swap(this->len, rhs.len);
+}
+
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 39d97bd..d200617 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -751,8 +751,12 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r->get() == 2020);
   ASSERT(r->set(2021) == 2021);
   ASSERT(r->get() == 2021);
-  ASSERT(r->set(2020) == 2020);
+  auto r2 = r_return_box();
+  swap(r, r2);
   ASSERT(r->get() == 2020);
+  ASSERT(r2->get() == 2021);
+
+
   ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");
@@ -785,6 +789,23 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(strncmp(cstring.c_str(), "test", 5) == 0);
   ASSERT(cstring.length() == 4);
 
+  rust::String other_cstring = "foo";
+  swap(cstring, other_cstring);
+  ASSERT(cstring == "foo");
+  ASSERT(other_cstring == "test");
+
+  rust::Str cstr = "test";
+  rust::Str other_cstr = "foo";
+  swap(cstr, other_cstr);
+  ASSERT(cstr == "foo");
+  ASSERT(other_cstr == "test");
+
+  rust::Vec<int> vec1{1, 2};
+  rust::Vec<int> vec2{3, 4};
+  swap(vec1, vec2);
+  ASSERT(vec1[0] == 3 && vec1[1] == 4);
+  ASSERT(vec2[0] == 1 && vec2[1] == 2);
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 1ca730e0a1b5c2f55e3e6e81e9187a840797ef84 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:14:03 +0000
Subject: [PATCH 1970/2232] Update Box website page to match header


---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 5f2644b..417af8f 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -18,7 +18,6 @@ public:
       typename std::add_pointer<typename std::add_const<T>::type>::type;
   using pointer = typename std::add_pointer<T>::type;
 
-  Box(const Box &);
   Box(Box &&) noexcept;
   ~Box() noexcept;
 
@@ -27,7 +26,6 @@ public:
 
   void swap(Box &) noexcept;
 
-  Box &operator=(const Box &);
   Box &operator=(Box &&) noexcept;
 
   const T *operator->() const noexcept;

From c9e597e938a9efe7f2384d80ddbdabfeae74b453 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:15:11 +0000
Subject: [PATCH 1971/2232] Format PR 642 with clang-format 10


---

diff --git a/include/cxx.h b/include/cxx.h
index f441280..54ed175 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,7 +56,7 @@ public:
 
   const char *c_str() noexcept;
 
-  void swap(String & rhs) noexcept;
+  void swap(String &rhs) noexcept;
 
   using iterator = char *;
   iterator begin() noexcept;
@@ -79,9 +79,7 @@ public:
   String(unsafe_bitcopy_t, const String &) noexcept;
 
 private:
-  friend void swap(String& lhs, String& rhs) noexcept {
-    lhs.swap(rhs);
-  }
+  friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); }
 
   // Size and alignment statically verified by rust_string.rs.
   std::array<std::uintptr_t, 3> repr;
@@ -108,7 +106,7 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
-  void swap(Str & rhs) noexcept;
+  void swap(Str &rhs) noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
@@ -129,9 +127,7 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  friend void swap(Str & lhs, Str & rhs) noexcept {
-    lhs.swap(rhs);
-  }
+  friend void swap(Str &lhs, Str &rhs) noexcept { lhs.swap(rhs); }
 
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
@@ -172,7 +168,7 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice & rhs) noexcept;
+  void swap(Slice &rhs) noexcept;
 
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
@@ -188,9 +184,7 @@ public:
   iterator end() const noexcept;
 
 private:
-  friend void swap(Slice<T> & lhs, Slice<T> & rhs) noexcept {
-    lhs.swap(rhs);
-  }
+  friend void swap(Slice<T> &lhs, Slice<T> &rhs) noexcept { lhs.swap(rhs); }
 
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
@@ -253,7 +247,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  void swap(Box & rhs) noexcept;
+  void swap(Box &rhs) noexcept;
 
   Box &operator=(Box &&) noexcept;
 
@@ -279,9 +273,7 @@ private:
   Box(uninit) noexcept;
   void drop() noexcept;
 
-  friend void swap(Box & lhs, Box & rhs) noexcept {
-    lhs.swap(rhs);
-  }
+  friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); }
 
   T *ptr;
 };
@@ -309,7 +301,7 @@ public:
   T *data() noexcept;
   std::size_t capacity() const noexcept;
 
-  void swap(Vec & rhs) noexcept;
+  void swap(Vec &rhs) noexcept;
 
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
@@ -345,9 +337,7 @@ private:
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
 
-  friend void swap(Vec<T> & lhs, Vec<T> & rhs) noexcept {
-    lhs.swap(rhs);
-  }
+  friend void swap(Vec<T> &lhs, Vec<T> &rhs) noexcept { lhs.swap(rhs); }
 
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
@@ -537,7 +527,7 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
-void Slice<T>::swap(Slice<T> & rhs) noexcept {
+void Slice<T>::swap(Slice<T> &rhs) noexcept {
   using std::swap;
   swap(this->ptr, rhs.ptr);
   swap(this->len, rhs.len);
@@ -746,7 +736,7 @@ Box<T>::Box(T &&val) {
 }
 
 template <typename T>
-void Box<T>::swap(Box<T> & rhs) noexcept {
+void Box<T>::swap(Box<T> &rhs) noexcept {
   using std::swap;
   swap(this->ptr, rhs.ptr);
 }
@@ -870,7 +860,7 @@ T *Vec<T>::data() noexcept {
 }
 
 template <typename T>
-void Vec<T>::swap(Vec<T> & rhs) noexcept {
+void Vec<T>::swap(Vec<T> &rhs) noexcept {
   using std::swap;
   swap(this->repr, rhs.repr);
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index a23fd8c..269027a 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -130,7 +130,7 @@ const char *String::c_str() noexcept {
   return ptr;
 }
 
-void String::swap(String& rhs) noexcept {
+void String::swap(String &rhs) noexcept {
   using std::swap;
   swap(this->repr, rhs.repr);
 }
@@ -215,7 +215,7 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-void Str::swap(Str& rhs) noexcept {
+void Str::swap(Str &rhs) noexcept {
   using std::swap;
   swap(this->ptr, rhs.ptr);
   swap(this->len, rhs.len);

From bc44ebf5207094f344938df4e665c81d08bdf86b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:23:37 +0000
Subject: [PATCH 1972/2232] Touch up PR 642


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 2354f53..31a1f53 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -32,7 +32,7 @@ public:
   size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice & rhs) noexcept;
+  void swap(Slice &) noexcept;
 
   T &operator[](size_t n) const noexcept;
   T &at(size_t n) const;
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index bc85909..811e0a1 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -31,7 +31,7 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
-  void swap(Str & rhs) noexcept;
+  void swap(Str &) noexcept;
 
   using iterator = const char *;
   using const_iterator = const char *;
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 02790c3..68c85b8 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -35,7 +35,7 @@ public:
 
   const char *c_str() noexcept;
 
-  void swap(String & rhs) noexcept;
+  void swap(String &) noexcept;
 
   using iterator = char *;
   iterator begin() noexcept;
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index e2af25c..56518aa 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -32,7 +32,7 @@ public:
   T *data() noexcept;
   size_t capacity() const noexcept;
   
-  void swap(Vec & rhs) noexcept;
+  void swap(Vec &) noexcept;
 
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
diff --git a/include/cxx.h b/include/cxx.h
index 54ed175..6c9a3a0 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,7 +56,7 @@ public:
 
   const char *c_str() noexcept;
 
-  void swap(String &rhs) noexcept;
+  void swap(String &) noexcept;
 
   using iterator = char *;
   iterator begin() noexcept;
@@ -106,7 +106,7 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
-  void swap(Str &rhs) noexcept;
+  void swap(Str &) noexcept;
 
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
@@ -168,7 +168,7 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice &rhs) noexcept;
+  void swap(Slice &) noexcept;
 
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
@@ -247,7 +247,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  void swap(Box &rhs) noexcept;
+  void swap(Box &) noexcept;
 
   Box &operator=(Box &&) noexcept;
 
@@ -301,7 +301,7 @@ public:
   T *data() noexcept;
   std::size_t capacity() const noexcept;
 
-  void swap(Vec &rhs) noexcept;
+  void swap(Vec &) noexcept;
 
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d200617..7eaee48 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -756,7 +756,6 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r->get() == 2020);
   ASSERT(r2->get() == 2021);
 
-
   ASSERT(std::string(Shared{0}.r_method_on_shared()) == "2020");
 
   ASSERT(std::string(rAliasedFunction(2020)) == "2020");

From d835ac6cadf7cf1cee76f2e108248e083e4236ea Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:26:20 +0000
Subject: [PATCH 1973/2232] Omit swap member functions from website


I feel it's sufficient that std::swap "does the right thing". These do
not need to be explicitly presented as part of the API.

---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 417af8f..3b2b9ff 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -24,8 +24,6 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  void swap(Box &) noexcept;
-
   Box &operator=(Box &&) noexcept;
 
   const T *operator->() const noexcept;
diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index 31a1f53..fe1691e 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -32,8 +32,6 @@ public:
   size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice &) noexcept;
-
   T &operator[](size_t n) const noexcept;
   T &at(size_t n) const;
   T &front() const noexcept;
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 811e0a1..999727c 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -31,8 +31,6 @@ public:
   size_t size() const noexcept;
   size_t length() const noexcept;
 
-  void swap(Str &) noexcept;
-
   using iterator = const char *;
   using const_iterator = const char *;
   const_iterator begin() const noexcept;
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 68c85b8..8dc1ee4 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -35,8 +35,6 @@ public:
 
   const char *c_str() noexcept;
 
-  void swap(String &) noexcept;
-
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 56518aa..4c9c939 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -32,8 +32,6 @@ public:
   T *data() noexcept;
   size_t capacity() const noexcept;
   
-  void swap(Vec &) noexcept;
-
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
   const T &front() const;

From 2ae80499c114c08167d230521c81d870b32e9aec Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:28:02 +0000
Subject: [PATCH 1974/2232] Clean up trailing whitespaces


---

diff --git a/book/diagram/overview.svg b/book/diagram/overview.svg
index c551687..e515466 100644
--- a/book/diagram/overview.svg
+++ b/book/diagram/overview.svg
@@ -68,7 +68,7 @@
                             marker-start: url(#big_open_circle);
                          }
 
-                         
+
                         </style>
     <defs>
         <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
diff --git a/book/src/binding/sharedptr.md b/book/src/binding/sharedptr.md
index 8f494ae..a3b7070 100644
--- a/book/src/binding/sharedptr.md
+++ b/book/src/binding/sharedptr.md
@@ -37,7 +37,7 @@ fn main() {
     {
         // Create a second shared_ptr holding shared ownership of the same
         // object. There is still only one Object but two SharedPtr<Object>.
-        // Both pointers point to the same object on the heap. 
+        // Both pointers point to the same object on the heap.
         let ptr2 = ptr1.clone();
         assert!(ptr::eq(ptr1.deref(), ptr2.deref()));
 
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 4c9c939..39c1da1 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -31,7 +31,7 @@ public:
   const T *data() const noexcept;
   T *data() noexcept;
   size_t capacity() const noexcept;
-  
+
   const T &operator[](size_t n) const noexcept;
   const T &at(size_t n) const;
   const T &front() const;

From 8f68939ae9ed577aaac84902de3aba9ebdacd6cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:34:12 +0000
Subject: [PATCH 1975/2232] Remove Str and Slice swaps


---

diff --git a/include/cxx.h b/include/cxx.h
index 6c9a3a0..bb24b10 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -106,8 +106,6 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
-  void swap(Str &) noexcept;
-
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
@@ -127,8 +125,6 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  friend void swap(Str &lhs, Str &rhs) noexcept { lhs.swap(rhs); }
-
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -168,8 +164,6 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice &) noexcept;
-
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
   T &front() const noexcept;
@@ -184,8 +178,6 @@ public:
   iterator end() const noexcept;
 
 private:
-  friend void swap(Slice<T> &lhs, Slice<T> &rhs) noexcept { lhs.swap(rhs); }
-
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;
@@ -527,13 +519,6 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
-void Slice<T>::swap(Slice<T> &rhs) noexcept {
-  using std::swap;
-  swap(this->ptr, rhs.ptr);
-  swap(this->len, rhs.len);
-}
-
-template <typename T>
 bool Slice<T>::empty() const noexcept {
   return this->len == 0;
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index 269027a..0498655 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -215,12 +215,6 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-void Str::swap(Str &rhs) noexcept {
-  using std::swap;
-  swap(this->ptr, rhs.ptr);
-  swap(this->len, rhs.len);
-}
-
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7eaee48..548ad13 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -751,6 +751,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r->get() == 2020);
   ASSERT(r->set(2021) == 2021);
   ASSERT(r->get() == 2021);
+
+  using std::swap;
   auto r2 = r_return_box();
   swap(r, r2);
   ASSERT(r->get() == 2020);

From 4f2b30e1a6548ce65228d353f7994c858a2ae87d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:44:09 +0000
Subject: [PATCH 1976/2232] Merge pull request #643 from dtolnay/swap


Remove Str and Slice swaps
---

diff --git a/include/cxx.h b/include/cxx.h
index 6c9a3a0..bb24b10 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -106,8 +106,6 @@ public:
   std::size_t size() const noexcept;
   std::size_t length() const noexcept;
 
-  void swap(Str &) noexcept;
-
   // Important in order for System V ABI to pass in registers.
   Str(const Str &) noexcept = default;
   ~Str() noexcept = default;
@@ -127,8 +125,6 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  friend void swap(Str &lhs, Str &rhs) noexcept { lhs.swap(rhs); }
-
   // Not necessarily ABI compatible with &str. Codegen will translate to
   // cxx::rust_str::RustStr which matches this layout.
   const char *ptr;
@@ -168,8 +164,6 @@ public:
   std::size_t length() const noexcept;
   bool empty() const noexcept;
 
-  void swap(Slice &) noexcept;
-
   T &operator[](std::size_t n) const noexcept;
   T &at(std::size_t n) const;
   T &front() const noexcept;
@@ -184,8 +178,6 @@ public:
   iterator end() const noexcept;
 
 private:
-  friend void swap(Slice<T> &lhs, Slice<T> &rhs) noexcept { lhs.swap(rhs); }
-
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
   void *ptr;
@@ -527,13 +519,6 @@ std::size_t Slice<T>::length() const noexcept {
 }
 
 template <typename T>
-void Slice<T>::swap(Slice<T> &rhs) noexcept {
-  using std::swap;
-  swap(this->ptr, rhs.ptr);
-  swap(this->len, rhs.len);
-}
-
-template <typename T>
 bool Slice<T>::empty() const noexcept {
   return this->len == 0;
 }
diff --git a/src/cxx.cc b/src/cxx.cc
index 269027a..0498655 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -215,12 +215,6 @@ Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
-void Str::swap(Str &rhs) noexcept {
-  using std::swap;
-  swap(this->ptr, rhs.ptr);
-  swap(this->len, rhs.len);
-}
-
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 7eaee48..548ad13 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -751,6 +751,8 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(r->get() == 2020);
   ASSERT(r->set(2021) == 2021);
   ASSERT(r->get() == 2021);
+
+  using std::swap;
   auto r2 = r_return_box();
   swap(r, r2);
   ASSERT(r->get() == 2020);

From fec1715ad6db71eef049e7d4d6fafcac54daa4f8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 20:51:31 +0000
Subject: [PATCH 1977/2232] Move swap member functions below less-niche functions


The swap member functions are going to be infrequently used (relative to
things like operator==, Box's operator->) so let's present it lower down
in the API.

---

diff --git a/include/cxx.h b/include/cxx.h
index bb24b10..5b4b24f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -56,8 +56,6 @@ public:
 
   const char *c_str() noexcept;
 
-  void swap(String &) noexcept;
-
   using iterator = char *;
   iterator begin() noexcept;
   iterator end() noexcept;
@@ -75,6 +73,8 @@ public:
   bool operator>(const String &) const noexcept;
   bool operator>=(const String &) const noexcept;
 
+  void swap(String &) noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   String(unsafe_bitcopy_t, const String &) noexcept;
 
@@ -239,8 +239,6 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  void swap(Box &) noexcept;
-
   Box &operator=(Box &&) noexcept;
 
   const T *operator->() const noexcept;
@@ -251,6 +249,8 @@ public:
   template <typename... Fields>
   static Box in_place(Fields &&...);
 
+  void swap(Box &) noexcept;
+
   // Important: requires that `raw` came from an into_raw call. Do not pass a
   // pointer from `new` or any other source.
   static Box from_raw(T *) noexcept;
@@ -293,8 +293,6 @@ public:
   T *data() noexcept;
   std::size_t capacity() const noexcept;
 
-  void swap(Vec &) noexcept;
-
   const T &operator[](std::size_t n) const noexcept;
   const T &at(std::size_t n) const;
   const T &front() const noexcept;
@@ -321,6 +319,8 @@ public:
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
 
+  void swap(Vec &) noexcept;
+
   // Internal API only intended for the cxxbridge code generator.
   Vec(unsafe_bitcopy_t, const Vec &) noexcept;
 
@@ -721,12 +721,6 @@ Box<T>::Box(T &&val) {
 }
 
 template <typename T>
-void Box<T>::swap(Box<T> &rhs) noexcept {
-  using std::swap;
-  swap(this->ptr, rhs.ptr);
-}
-
-template <typename T>
 Box<T>::~Box() noexcept {
   if (this->ptr) {
     this->drop();
@@ -774,6 +768,12 @@ Box<T> Box<T>::in_place(Fields &&... fields) {
 }
 
 template <typename T>
+void Box<T>::swap(Box<T> &rhs) noexcept {
+  using std::swap;
+  swap(this->ptr, rhs.ptr);
+}
+
+template <typename T>
 Box<T> Box<T>::from_raw(T *raw) noexcept {
   Box box = uninit{};
   box.ptr = raw;
@@ -845,12 +845,6 @@ T *Vec<T>::data() noexcept {
 }
 
 template <typename T>
-void Vec<T>::swap(Vec<T> &rhs) noexcept {
-  using std::swap;
-  swap(this->repr, rhs.repr);
-}
-
-template <typename T>
 const T &Vec<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
   auto data = reinterpret_cast<const char *>(this->data());
@@ -960,6 +954,12 @@ typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
   return Slice<const T>(this->data(), this->size()).end();
 }
 
+template <typename T>
+void Vec<T>::swap(Vec<T> &rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
 // Internal API only intended for the cxxbridge code generator.
 template <typename T>
 Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {}
diff --git a/src/cxx.cc b/src/cxx.cc
index 0498655..f9d7fad 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -130,11 +130,6 @@ const char *String::c_str() noexcept {
   return ptr;
 }
 
-void String::swap(String &rhs) noexcept {
-  using std::swap;
-  swap(this->repr, rhs.repr);
-}
-
 String::iterator String::begin() noexcept {
   return const_cast<char *>(this->data());
 }
@@ -177,6 +172,11 @@ bool String::operator>=(const String &rhs) const noexcept {
   return rust::Str(*this) >= rust::Str(rhs);
 }
 
+void String::swap(String &rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
+
 String::String(unsafe_bitcopy_t, const String &bits) noexcept
     : repr(bits.repr) {}
 

From cf7bb9ba76d74baa9642074b0960cae536c2d787 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:03:28 +0000
Subject: [PATCH 1978/2232] Elide template parameters in swaps where unneeded


---

diff --git a/include/cxx.h b/include/cxx.h
index 5b4b24f..0c56848 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -329,7 +329,7 @@ private:
   void set_len(std::size_t len) noexcept;
   void drop() noexcept;
 
-  friend void swap(Vec<T> &lhs, Vec<T> &rhs) noexcept { lhs.swap(rhs); }
+  friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); }
 
   // Size and alignment statically verified by rust_vec.rs.
   std::array<std::uintptr_t, 3> repr;
@@ -768,7 +768,7 @@ Box<T> Box<T>::in_place(Fields &&... fields) {
 }
 
 template <typename T>
-void Box<T>::swap(Box<T> &rhs) noexcept {
+void Box<T>::swap(Box &rhs) noexcept {
   using std::swap;
   swap(this->ptr, rhs.ptr);
 }
@@ -955,7 +955,7 @@ typename Vec<T>::const_iterator Vec<T>::cend() const noexcept {
 }
 
 template <typename T>
-void Vec<T>::swap(Vec<T> &rhs) noexcept {
+void Vec<T>::swap(Vec &rhs) noexcept {
   using std::swap;
   swap(this->repr, rhs.repr);
 }

From 8ce57ec900824471bfac716c9b6f79e06d929baf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:04:40 +0000
Subject: [PATCH 1979/2232] Decouple C++ exception representation from Rust str


---

diff --git a/src/result.rs b/src/result.rs
index 29c5d67..7927c20 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,16 +1,22 @@
 use crate::exception::Exception;
-use crate::rust_str::RustStr;
 use alloc::boxed::Box;
 use alloc::string::{String, ToString};
 use core::fmt::Display;
-use core::ptr;
+use core::ptr::{self, NonNull};
 use core::result::Result as StdResult;
 use core::slice;
 use core::str;
 
 #[repr(C)]
+#[derive(Copy, Clone)]
+struct PtrLen {
+    ptr: NonNull<u8>,
+    len: usize,
+}
+
+#[repr(C)]
 pub union Result {
-    err: RustStr,
+    err: PtrLen,
     ok: *const u8, // null
 }
 
@@ -41,7 +47,10 @@ unsafe fn to_c_error(msg: String) -> Result {
     let copy = error(ptr, len);
     let slice = slice::from_raw_parts(copy, len);
     let string = str::from_utf8_unchecked(slice);
-    let err = RustStr::from(string);
+    let err = PtrLen {
+        ptr: NonNull::from(string).cast::<u8>(),
+        len: string.len(),
+    };
     Result { err }
 }
 

From aec3f24fb1241ae4dbccacd01b069d0510b18b2b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:14:58 +0000
Subject: [PATCH 1980/2232] Merge pull request #644 from dtolnay/result


Decouple C++ exception representation from Rust str
---

diff --git a/src/result.rs b/src/result.rs
index 29c5d67..7927c20 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,16 +1,22 @@
 use crate::exception::Exception;
-use crate::rust_str::RustStr;
 use alloc::boxed::Box;
 use alloc::string::{String, ToString};
 use core::fmt::Display;
-use core::ptr;
+use core::ptr::{self, NonNull};
 use core::result::Result as StdResult;
 use core::slice;
 use core::str;
 
 #[repr(C)]
+#[derive(Copy, Clone)]
+struct PtrLen {
+    ptr: NonNull<u8>,
+    len: usize,
+}
+
+#[repr(C)]
 pub union Result {
-    err: RustStr,
+    err: PtrLen,
     ok: *const u8, // null
 }
 
@@ -41,7 +47,10 @@ unsafe fn to_c_error(msg: String) -> Result {
     let copy = error(ptr, len);
     let slice = slice::from_raw_parts(copy, len);
     let string = str::from_utf8_unchecked(slice);
-    let err = RustStr::from(string);
+    let err = PtrLen {
+        ptr: NonNull::from(string).cast::<u8>(),
+        len: string.len(),
+    };
     Result { err }
 }
 

From 1202de50b7b64e6e7fba21852185d08a612ded45 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:15:08 +0000
Subject: [PATCH 1981/2232] Preserve &str's original Rust representation in C++


---

diff --git a/include/cxx.h b/include/cxx.h
index 0c56848..ee4de41 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -88,6 +88,7 @@ private:
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR
+#define CXXBRIDGE1_RUST_STR
 // https://cxx.rs/binding/str.html
 class Str final {
 public:
@@ -125,10 +126,7 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  // Not necessarily ABI compatible with &str. Codegen will translate to
-  // cxx::rust_str::RustStr which matches this layout.
-  const char *ptr;
-  std::size_t len;
+  std::array<std::uintptr_t, 2> repr;
 };
 #endif // CXXBRIDGE1_RUST_STR
 
@@ -484,15 +482,6 @@ struct unsafe_bitcopy_t final {
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE1_RUST_BITCOPY
 
-#ifndef CXXBRIDGE1_RUST_STR
-#define CXXBRIDGE1_RUST_STR
-inline const char *Str::data() const noexcept { return this->ptr; }
-
-inline std::size_t Str::size() const noexcept { return this->len; }
-
-inline std::size_t Str::length() const noexcept { return this->len; }
-#endif // CXXBRIDGE1_RUST_STR
-
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
diff --git a/src/cxx.cc b/src/cxx.cc
index f9d7fad..5d38966 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -39,7 +39,12 @@ std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
 void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
 
 // rust::Str
-bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
+void cxxbridge1$str$new(rust::Str *self) noexcept;
+void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
+bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
+                         std::size_t len) noexcept;
+const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
+std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
 } // extern "C"
 
 namespace rust {
@@ -185,46 +190,52 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
+Str::Str() noexcept { cxxbridge1$str$new(this); }
 
-Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
+Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
 
-static void initStr(const char *ptr, std::size_t len) {
-  if (!cxxbridge1$str$valid(ptr, len)) {
+static void initStr(Str *self, const char *ptr, std::size_t len) {
+  if (!cxxbridge1$str$from(self, ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
-  initStr(this->ptr, this->len);
-}
+Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
 
-Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
+Str::Str(const char *s) {
   assert(s != nullptr);
-  initStr(this->ptr, this->len);
+  initStr(this, s, std::strlen(s));
 }
 
-Str::Str(const char *s, std::size_t len)
-    : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
-      len(len) {
+Str::Str(const char *s, std::size_t len) {
   assert(s != nullptr || len == 0);
-  initStr(this->ptr, this->len);
+  initStr(this,
+          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+          len);
 }
 
 Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
+
+std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
+
+std::size_t Str::length() const noexcept { return this->size(); }
+
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
 
-Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
+Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
 
-Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
+Str::const_iterator Str::cend() const noexcept {
+  return this->data() + this->size();
+}
 
 bool Str::operator==(const Str &rhs) const noexcept {
-  return this->len == rhs.len &&
+  return this->size() == rhs.size() &&
          std::equal(this->begin(), this->end(), rhs.begin());
 }
 
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 38e5cab..9bc2614 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -1,27 +1,20 @@
 use core::mem;
 use core::ptr::NonNull;
-use core::slice;
 use core::str;
 
-// Not necessarily ABI compatible with &str. Codegen performs the translation.
 #[repr(C)]
-#[derive(Copy, Clone)]
 pub struct RustStr {
-    pub(crate) ptr: NonNull<u8>,
-    pub(crate) len: usize,
+    repr: NonNull<str>,
 }
 
 impl RustStr {
-    pub fn from(s: &str) -> Self {
-        RustStr {
-            ptr: NonNull::from(s).cast::<u8>(),
-            len: s.len(),
-        }
+    pub fn from(repr: &str) -> Self {
+        let repr = NonNull::from(repr);
+        RustStr { repr }
     }
 
     pub unsafe fn as_str<'a>(self) -> &'a str {
-        let slice = slice::from_raw_parts(self.ptr.as_ptr(), self.len);
-        str::from_utf8_unchecked(slice)
+        &*self.repr.as_ptr()
     }
 }
 
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 041147d..a9e84ef 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,8 +1,37 @@
+use alloc::string::String;
+use core::mem::MaybeUninit;
+use core::ptr;
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge1$str$valid"]
-unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
+#[export_name = "cxxbridge1$str$new"]
+unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) {
+    ptr::write(this.as_mut_ptr(), "");
+}
+
+#[export_name = "cxxbridge1$str$ref"]
+unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) {
+    ptr::write(this.as_mut_ptr(), string.as_str());
+}
+
+#[export_name = "cxxbridge1$str$from"]
+unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
-    str::from_utf8(slice).is_ok()
+    match str::from_utf8(slice) {
+        Ok(s) => {
+            ptr::write(this.as_mut_ptr(), s);
+            true
+        }
+        Err(_) => false,
+    }
+}
+
+#[export_name = "cxxbridge1$str$ptr"]
+unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 {
+    this.as_ptr()
+}
+
+#[export_name = "cxxbridge1$str$len"]
+unsafe extern "C" fn str_len(this: &&str) -> usize {
+    this.len()
 }

From d1812baec0c533c46e48d20dbad6cb0a4ab873f5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:22:28 +0000
Subject: [PATCH 1982/2232] Merge pull request #645 from dtolnay/str


Preserve &str's original Rust representation in C++
---

diff --git a/include/cxx.h b/include/cxx.h
index 0c56848..ee4de41 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -88,6 +88,7 @@ private:
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR
+#define CXXBRIDGE1_RUST_STR
 // https://cxx.rs/binding/str.html
 class Str final {
 public:
@@ -125,10 +126,7 @@ public:
   bool operator>=(const Str &) const noexcept;
 
 private:
-  // Not necessarily ABI compatible with &str. Codegen will translate to
-  // cxx::rust_str::RustStr which matches this layout.
-  const char *ptr;
-  std::size_t len;
+  std::array<std::uintptr_t, 2> repr;
 };
 #endif // CXXBRIDGE1_RUST_STR
 
@@ -484,15 +482,6 @@ struct unsafe_bitcopy_t final {
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE1_RUST_BITCOPY
 
-#ifndef CXXBRIDGE1_RUST_STR
-#define CXXBRIDGE1_RUST_STR
-inline const char *Str::data() const noexcept { return this->ptr; }
-
-inline std::size_t Str::size() const noexcept { return this->len; }
-
-inline std::size_t Str::length() const noexcept { return this->len; }
-#endif // CXXBRIDGE1_RUST_STR
-
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
diff --git a/src/cxx.cc b/src/cxx.cc
index f9d7fad..5d38966 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -39,7 +39,12 @@ std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
 void cxxbridge1$string$reserve_total(rust::String *self, size_t cap) noexcept;
 
 // rust::Str
-bool cxxbridge1$str$valid(const char *ptr, std::size_t len) noexcept;
+void cxxbridge1$str$new(rust::Str *self) noexcept;
+void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept;
+bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
+                         std::size_t len) noexcept;
+const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
+std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
 } // extern "C"
 
 namespace rust {
@@ -185,46 +190,52 @@ std::ostream &operator<<(std::ostream &os, const String &s) {
   return os;
 }
 
-Str::Str() noexcept : ptr(reinterpret_cast<const char *>(1)), len(0) {}
+Str::Str() noexcept { cxxbridge1$str$new(this); }
 
-Str::Str(const String &s) noexcept : ptr(s.data()), len(s.length()) {}
+Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); }
 
-static void initStr(const char *ptr, std::size_t len) {
-  if (!cxxbridge1$str$valid(ptr, len)) {
+static void initStr(Str *self, const char *ptr, std::size_t len) {
+  if (!cxxbridge1$str$from(self, ptr, len)) {
     panic<std::invalid_argument>("data for rust::Str is not utf-8");
   }
 }
 
-Str::Str(const std::string &s) : ptr(s.data()), len(s.length()) {
-  initStr(this->ptr, this->len);
-}
+Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); }
 
-Str::Str(const char *s) : ptr(s), len(std::strlen(s)) {
+Str::Str(const char *s) {
   assert(s != nullptr);
-  initStr(this->ptr, this->len);
+  initStr(this, s, std::strlen(s));
 }
 
-Str::Str(const char *s, std::size_t len)
-    : ptr(s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s),
-      len(len) {
+Str::Str(const char *s, std::size_t len) {
   assert(s != nullptr || len == 0);
-  initStr(this->ptr, this->len);
+  initStr(this,
+          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+          len);
 }
 
 Str::operator std::string() const {
   return std::string(this->data(), this->size());
 }
 
+const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); }
+
+std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); }
+
+std::size_t Str::length() const noexcept { return this->size(); }
+
 Str::const_iterator Str::begin() const noexcept { return this->cbegin(); }
 
 Str::const_iterator Str::end() const noexcept { return this->cend(); }
 
-Str::const_iterator Str::cbegin() const noexcept { return this->ptr; }
+Str::const_iterator Str::cbegin() const noexcept { return this->data(); }
 
-Str::const_iterator Str::cend() const noexcept { return this->ptr + this->len; }
+Str::const_iterator Str::cend() const noexcept {
+  return this->data() + this->size();
+}
 
 bool Str::operator==(const Str &rhs) const noexcept {
-  return this->len == rhs.len &&
+  return this->size() == rhs.size() &&
          std::equal(this->begin(), this->end(), rhs.begin());
 }
 
diff --git a/src/rust_str.rs b/src/rust_str.rs
index 38e5cab..9bc2614 100644
--- a/src/rust_str.rs
+++ b/src/rust_str.rs
@@ -1,27 +1,20 @@
 use core::mem;
 use core::ptr::NonNull;
-use core::slice;
 use core::str;
 
-// Not necessarily ABI compatible with &str. Codegen performs the translation.
 #[repr(C)]
-#[derive(Copy, Clone)]
 pub struct RustStr {
-    pub(crate) ptr: NonNull<u8>,
-    pub(crate) len: usize,
+    repr: NonNull<str>,
 }
 
 impl RustStr {
-    pub fn from(s: &str) -> Self {
-        RustStr {
-            ptr: NonNull::from(s).cast::<u8>(),
-            len: s.len(),
-        }
+    pub fn from(repr: &str) -> Self {
+        let repr = NonNull::from(repr);
+        RustStr { repr }
     }
 
     pub unsafe fn as_str<'a>(self) -> &'a str {
-        let slice = slice::from_raw_parts(self.ptr.as_ptr(), self.len);
-        str::from_utf8_unchecked(slice)
+        &*self.repr.as_ptr()
     }
 }
 
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 041147d..a9e84ef 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,8 +1,37 @@
+use alloc::string::String;
+use core::mem::MaybeUninit;
+use core::ptr;
 use core::slice;
 use core::str;
 
-#[export_name = "cxxbridge1$str$valid"]
-unsafe extern "C" fn str_valid(ptr: *const u8, len: usize) -> bool {
+#[export_name = "cxxbridge1$str$new"]
+unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) {
+    ptr::write(this.as_mut_ptr(), "");
+}
+
+#[export_name = "cxxbridge1$str$ref"]
+unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) {
+    ptr::write(this.as_mut_ptr(), string.as_str());
+}
+
+#[export_name = "cxxbridge1$str$from"]
+unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: usize) -> bool {
     let slice = slice::from_raw_parts(ptr, len);
-    str::from_utf8(slice).is_ok()
+    match str::from_utf8(slice) {
+        Ok(s) => {
+            ptr::write(this.as_mut_ptr(), s);
+            true
+        }
+        Err(_) => false,
+    }
+}
+
+#[export_name = "cxxbridge1$str$ptr"]
+unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 {
+    this.as_ptr()
+}
+
+#[export_name = "cxxbridge1$str$len"]
+unsafe extern "C" fn str_len(this: &&str) -> usize {
+    this.len()
 }

From 815ca8cafceda746073a0409faa6f8677ee9cc6c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:57:30 +0000
Subject: [PATCH 1983/2232] Revert "Omit swap member functions from website"


This reverts commit d835ac6cadf7cf1cee76f2e108248e083e4236ea.

---

diff --git a/book/src/binding/box.md b/book/src/binding/box.md
index 3b2b9ff..7df1959 100644
--- a/book/src/binding/box.md
+++ b/book/src/binding/box.md
@@ -34,6 +34,8 @@ public:
   template <typename... Fields>
   static Box in_place(Fields &&...);
 
+  void swap(Box &) noexcept;
+
   // Important: requires that `raw` came from an into_raw call. Do not
   // pass a pointer from `new` or any other source.
   static Box from_raw(T *) noexcept;
diff --git a/book/src/binding/string.md b/book/src/binding/string.md
index 8dc1ee4..a7d0790 100644
--- a/book/src/binding/string.md
+++ b/book/src/binding/string.md
@@ -51,6 +51,8 @@ public:
   bool operator<=(const String &) const noexcept;
   bool operator>(const String &) const noexcept;
   bool operator>=(const String &) const noexcept;
+
+  void swap(String &) noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const String &);
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 39c1da1..092e364 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -57,6 +57,8 @@ public:
   const_iterator end() const noexcept;
   const_iterator cbegin() const noexcept;
   const_iterator cend() const noexcept;
+
+  void swap(Vec &) noexcept;
 };
 #
 # template <typename T>

From 0413ee270951ee06a806424e85cbb83967819ed1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 21:57:48 +0000
Subject: [PATCH 1984/2232] Restore swapping Str and Slice in member function form only


---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fe1691e..803277b 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -40,6 +40,8 @@ public:
   class iterator;
   iterator begin() const noexcept;
   iterator end() const noexcept;
+
+  void swap(Slice &) noexcept;
 };
 #
 # template <typename T>
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 999727c..a4820aa 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -44,6 +44,8 @@ public:
   bool operator<=(const Str &) const noexcept;
   bool operator>(const Str &) const noexcept;
   bool operator>=(const Str &) const noexcept;
+
+  void swap(Str &) noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/include/cxx.h b/include/cxx.h
index ee4de41..03f719f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -125,6 +125,8 @@ public:
   bool operator>(const Str &) const noexcept;
   bool operator>=(const Str &) const noexcept;
 
+  void swap(Str &) noexcept;
+
 private:
   std::array<std::uintptr_t, 2> repr;
 };
@@ -175,6 +177,8 @@ public:
   iterator begin() const noexcept;
   iterator end() const noexcept;
 
+  void swap(Slice &) noexcept;
+
 private:
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
@@ -666,6 +670,11 @@ typename Slice<T>::iterator Slice<T>::end() const noexcept {
   it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
   return it;
 }
+
+template <typename T>
+void Slice<T>::swap(Slice &rhs) noexcept {
+  std::swap(*this, rhs);
+}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
diff --git a/src/cxx.cc b/src/cxx.cc
index 5d38966..605845e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -267,6 +267,8 @@ bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
 
 bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
 
+void Str::swap(Str &rhs) noexcept { std::swap(*this, rhs); }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From 2a58a8afdf2b9fabcc9721dd598b7c7f9f011dbe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 22:05:11 +0000
Subject: [PATCH 1985/2232] Merge pull request #646 from dtolnay/swap


Restore swapping Str and Slice in member function form only
---

diff --git a/book/src/binding/slice.md b/book/src/binding/slice.md
index fe1691e..803277b 100644
--- a/book/src/binding/slice.md
+++ b/book/src/binding/slice.md
@@ -40,6 +40,8 @@ public:
   class iterator;
   iterator begin() const noexcept;
   iterator end() const noexcept;
+
+  void swap(Slice &) noexcept;
 };
 #
 # template <typename T>
diff --git a/book/src/binding/str.md b/book/src/binding/str.md
index 999727c..a4820aa 100644
--- a/book/src/binding/str.md
+++ b/book/src/binding/str.md
@@ -44,6 +44,8 @@ public:
   bool operator<=(const Str &) const noexcept;
   bool operator>(const Str &) const noexcept;
   bool operator>=(const Str &) const noexcept;
+
+  void swap(Str &) noexcept;
 };
 
 std::ostream &operator<<(std::ostream &, const Str &);
diff --git a/include/cxx.h b/include/cxx.h
index ee4de41..03f719f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -125,6 +125,8 @@ public:
   bool operator>(const Str &) const noexcept;
   bool operator>=(const Str &) const noexcept;
 
+  void swap(Str &) noexcept;
+
 private:
   std::array<std::uintptr_t, 2> repr;
 };
@@ -175,6 +177,8 @@ public:
   iterator begin() const noexcept;
   iterator end() const noexcept;
 
+  void swap(Slice &) noexcept;
+
 private:
   // Not necessarily ABI compatible with &[T]. Codegen will translate to
   // cxx::rust_slice::RustSlice which matches this layout.
@@ -666,6 +670,11 @@ typename Slice<T>::iterator Slice<T>::end() const noexcept {
   it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
   return it;
 }
+
+template <typename T>
+void Slice<T>::swap(Slice &rhs) noexcept {
+  std::swap(*this, rhs);
+}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
diff --git a/src/cxx.cc b/src/cxx.cc
index 5d38966..605845e 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -267,6 +267,8 @@ bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
 
 bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
 
+void Str::swap(Str &rhs) noexcept { std::swap(*this, rhs); }
+
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());
   return os;

From 9bffb93783035dcdc073d562fc23d5f33f913751 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 23:01:59 +0000
Subject: [PATCH 1986/2232] Preserve &[T]'s Rust representation in rust::Slice


---

diff --git a/include/cxx.h b/include/cxx.h
index 03f719f..a81fc21 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,10 +180,9 @@ public:
   void swap(Slice &) noexcept;
 
 private:
-  // Not necessarily ABI compatible with &[T]. Codegen will translate to
-  // cxx::rust_slice::RustSlice which matches this layout.
-  void *ptr;
-  std::size_t len;
+  void *ptr() const noexcept;
+
+  std::array<std::uintptr_t, 2> repr;
 };
 
 template <typename T>
@@ -489,37 +488,42 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept
-    : ptr(reinterpret_cast<void *>(align_of<T>())), len(0) {}
+Slice<T>::Slice() noexcept {
+  void sliceInit(void *, const void *, std::size_t) noexcept;
+  sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0);
+}
 
 template <typename T>
-Slice<T>::Slice(T *s, std::size_t count) noexcept
-    : ptr(const_cast<typename std::remove_const<T>::type *>(s)), len(count) {}
+Slice<T>::Slice(T *s, std::size_t count) noexcept {
+  void sliceInit(void *, const void *, std::size_t) noexcept;
+  sliceInit(this, const_cast<typename std::remove_const<T>::type *>(s), count);
+}
 
 template <typename T>
 T *Slice<T>::data() const noexcept {
-  return reinterpret_cast<T *>(this->ptr);
+  return reinterpret_cast<T *>(this->ptr());
 }
 
 template <typename T>
 std::size_t Slice<T>::size() const noexcept {
-  return this->len;
+  std::size_t sliceLen(const void *) noexcept;
+  return sliceLen(this);
 }
 
 template <typename T>
 std::size_t Slice<T>::length() const noexcept {
-  return this->len;
+  return this->size();
 }
 
 template <typename T>
 bool Slice<T>::empty() const noexcept {
-  return this->len == 0;
+  return this->size() == 0;
 }
 
 template <typename T>
 T &Slice<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
-  auto pos = static_cast<char *>(this->ptr) + size_of<T>() * n;
+  auto pos = static_cast<char *>(this->ptr()) + size_of<T>() * n;
   return *reinterpret_cast<T *>(pos);
 }
 
@@ -540,7 +544,7 @@ T &Slice<T>::front() const noexcept {
 template <typename T>
 T &Slice<T>::back() const noexcept {
   assert(!this->empty());
-  return (*this)[this->len - 1];
+  return (*this)[this->size() - 1];
 }
 
 template <typename T>
@@ -659,7 +663,7 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = this->ptr;
+  it.pos = this->ptr();
   it.stride = size_of<T>();
   return it;
 }
@@ -667,7 +671,7 @@ typename Slice<T>::iterator Slice<T>::begin() const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::end() const noexcept {
   iterator it = this->begin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
   return it;
 }
 
@@ -675,6 +679,12 @@ template <typename T>
 void Slice<T>::swap(Slice &rhs) noexcept {
   std::swap(*this, rhs);
 }
+
+template <typename T>
+void *Slice<T>::ptr() const noexcept {
+  void *slicePtr(const void *) noexcept;
+  return slicePtr(this);
+}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX
diff --git a/src/cxx.cc b/src/cxx.cc
index 605845e..ccf44b2 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -45,6 +45,12 @@ bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
                          std::size_t len) noexcept;
 const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
 std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
+
+// rust::Slice
+void cxxbridge1$slice$new(void *self, const void *ptr,
+                          std::size_t len) noexcept;
+void *cxxbridge1$slice$ptr(const void *self) noexcept;
+std::size_t cxxbridge1$slice$len(const void *self) noexcept;
 } // extern "C"
 
 namespace rust {
@@ -274,6 +280,16 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
+  cxxbridge1$slice$new(self, ptr, len);
+}
+
+void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
+
+std::size_t sliceLen(const void *self) noexcept {
+  return cxxbridge1$slice$len(self);
+}
+
 // Rust specifies that usize is ABI compatible with C's uintptr_t.
 // https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
 // However there is no direct Rust equivalent for size_t. C does not guarantee
diff --git a/src/rust_slice.rs b/src/rust_slice.rs
index 8a5e74b..b4b5f2c 100644
--- a/src/rust_slice.rs
+++ b/src/rust_slice.rs
@@ -1,36 +1,37 @@
 use core::mem;
-use core::ptr::NonNull;
+use core::ptr::{self, NonNull};
 use core::slice;
 
-// Not necessarily ABI compatible with &[T]. Codegen performs the translation.
 #[repr(C)]
-#[derive(Copy, Clone)]
 pub struct RustSlice {
-    pub(crate) ptr: NonNull<()>,
-    pub(crate) len: usize,
+    pub(crate) repr: NonNull<[()]>,
 }
 
 impl RustSlice {
-    pub fn from_ref<T>(s: &[T]) -> Self {
+    pub fn from_ref<T>(slice: &[T]) -> Self {
+        let ptr = ptr::slice_from_raw_parts::<()>(slice.as_ptr().cast(), slice.len());
         RustSlice {
-            ptr: NonNull::from(s).cast::<()>(),
-            len: s.len(),
+            repr: unsafe { NonNull::new_unchecked(ptr as *mut _) },
         }
     }
 
-    pub fn from_mut<T>(s: &mut [T]) -> Self {
+    pub fn from_mut<T>(slice: &mut [T]) -> Self {
+        let ptr = ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len());
         RustSlice {
-            len: s.len(),
-            ptr: NonNull::from(s).cast::<()>(),
+            repr: unsafe { NonNull::new_unchecked(ptr) },
         }
     }
 
     pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
-        slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), self.len)
+        let ptr = self.repr.as_ptr();
+        let len = self.repr.as_ref().len();
+        slice::from_raw_parts(ptr.cast(), len)
     }
 
     pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
-        slice::from_raw_parts_mut(self.ptr.as_ptr().cast::<T>(), self.len)
+        let ptr = self.repr.as_ptr();
+        let len = self.repr.as_ref().len();
+        slice::from_raw_parts_mut(ptr.cast(), len)
     }
 }
 
diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs
index a9d158d..e00bb55 100644
--- a/src/symbols/mod.rs
+++ b/src/symbols/mod.rs
@@ -1,4 +1,5 @@
 mod exception;
+mod rust_slice;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
diff --git a/src/symbols/rust_slice.rs b/src/symbols/rust_slice.rs
new file mode 100644
index 0000000..055b4de
--- /dev/null
+++ b/src/symbols/rust_slice.rs
@@ -0,0 +1,22 @@
+use crate::rust_slice::RustSlice;
+use core::mem::MaybeUninit;
+use core::ptr::{self, NonNull};
+
+#[export_name = "cxxbridge1$slice$new"]
+unsafe extern "C" fn slice_new(this: &mut MaybeUninit<RustSlice>, ptr: *const (), len: usize) {
+    let ptr = ptr::slice_from_raw_parts(ptr, len);
+    let rust_slice = RustSlice {
+        repr: NonNull::new_unchecked(ptr as *mut _),
+    };
+    ptr::write(this.as_mut_ptr(), rust_slice);
+}
+
+#[export_name = "cxxbridge1$slice$ptr"]
+unsafe extern "C" fn slice_ptr(this: &RustSlice) -> *const () {
+    this.repr.as_ptr().cast()
+}
+
+#[export_name = "cxxbridge1$slice$len"]
+unsafe extern "C" fn slice_len(this: &RustSlice) -> usize {
+    this.repr.as_ref().len()
+}

From 0e3f77636279b5cb14da142d7757c50de72fbacf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 23:08:09 +0000
Subject: [PATCH 1987/2232] Fix slice compilation on MSVC


    cxxbridge-demo.lib(blobstore.o) : error LNK2019: unresolved external symbol "void __cdecl sliceInit(void *,void const *,unsigned __int64)" (?sliceInit@@YAXPEAXPEBX_K@Z) referenced in function "public: __cdecl rust::cxxbridge1::Slice<unsigned char const >::Slice<unsigned char const >(unsigned char const *,unsigned __int64)" (??0?$Slice@$$CBE@cxxbridge1@rust@@QEAA@PEBE_K@Z)
    cxxbridge-demo.lib(blobstore.o) : error LNK2001: unresolved external symbol "void __cdecl sliceInit(void *,void const *,unsigned __int64)" (?sliceInit@@YAXPEAXPEBX_K@Z)
    cxxbridge-demo.lib(main.rs.o) : error LNK2001: unresolved external symbol "void __cdecl sliceInit(void *,void const *,unsigned __int64)" (?sliceInit@@YAXPEAXPEBX_K@Z)
    cxxbridge-demo.lib(main.rs.o) : error LNK2001: unresolved external symbol "void __cdecl sliceInit(void *,void const *,unsigned __int64)" (?sliceInit@@YAXPEAXPEBX_K@Z)
      Hint on symbols that are defined and could potentially match:
        "void __cdecl rust::cxxbridge1::sliceInit(void *,void const *,unsigned __int64)" (?sliceInit@cxxbridge1@rust@@YAXPEAXPEBX_K@Z)
    cxxbridge-demo.lib(blobstore.o) : error LNK2019: unresolved external symbol "unsigned __int64 __cdecl sliceLen(void const *)" (?sliceLen@@YA_KPEBX@Z) referenced in function "public: unsigned __int64 __cdecl rust::cxxbridge1::Slice<unsigned char const >::size(void)const " (?size@?$Slice@$$CBE@cxxbridge1@rust@@QEBA_KXZ)
    cxxbridge-demo.lib(main.rs.o) : error LNK2001: unresolved external symbol "unsigned __int64 __cdecl sliceLen(void const *)" (?sliceLen@@YA_KPEBX@Z)
      Hint on symbols that are defined and could potentially match:
        "unsigned __int64 __cdecl rust::cxxbridge1::sliceLen(void const *)" (?sliceLen@cxxbridge1@rust@@YA_KPEBX@Z)
    cxxbridge-demo.lib(blobstore.o) : error LNK2019: unresolved external symbol "void * __cdecl slicePtr(void const *)" (?slicePtr@@YAPEAXPEBX@Z) referenced in function "private: void * __cdecl rust::cxxbridge1::Slice<unsigned char const >::ptr(void)const " (?ptr@?$Slice@$$CBE@cxxbridge1@rust@@AEBAPEAXXZ)
    cxxbridge-demo.lib(main.rs.o) : error LNK2001: unresolved external symbol "void * __cdecl slicePtr(void const *)" (?slicePtr@@YAPEAXPEBX@Z)
      Hint on symbols that are defined and could potentially match:
        "void * __cdecl rust::cxxbridge1::slicePtr(void const *)" (?slicePtr@cxxbridge1@rust@@YAPEAXPEBX@Z)
    D:\a\cxx\cxx\target\debug\deps\demo.exe : fatal error LNK1120: 3 unresolved externals

---

diff --git a/include/cxx.h b/include/cxx.h
index a81fc21..acf2b1b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,8 +180,6 @@ public:
   void swap(Slice &) noexcept;
 
 private:
-  void *ptr() const noexcept;
-
   std::array<std::uintptr_t, 2> repr;
 };
 
@@ -487,26 +485,27 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
+void sliceInit(void *, const void *, std::size_t) noexcept;
+void *slicePtr(const void *) noexcept;
+std::size_t sliceLen(const void *) noexcept;
+
 template <typename T>
 Slice<T>::Slice() noexcept {
-  void sliceInit(void *, const void *, std::size_t) noexcept;
   sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0);
 }
 
 template <typename T>
 Slice<T>::Slice(T *s, std::size_t count) noexcept {
-  void sliceInit(void *, const void *, std::size_t) noexcept;
   sliceInit(this, const_cast<typename std::remove_const<T>::type *>(s), count);
 }
 
 template <typename T>
 T *Slice<T>::data() const noexcept {
-  return reinterpret_cast<T *>(this->ptr());
+  return reinterpret_cast<T *>(slicePtr(this));
 }
 
 template <typename T>
 std::size_t Slice<T>::size() const noexcept {
-  std::size_t sliceLen(const void *) noexcept;
   return sliceLen(this);
 }
 
@@ -523,7 +522,7 @@ bool Slice<T>::empty() const noexcept {
 template <typename T>
 T &Slice<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
-  auto pos = static_cast<char *>(this->ptr()) + size_of<T>() * n;
+  auto pos = static_cast<char *>(slicePtr(this)) + size_of<T>() * n;
   return *reinterpret_cast<T *>(pos);
 }
 
@@ -663,7 +662,7 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = this->ptr();
+  it.pos = slicePtr(this);
   it.stride = size_of<T>();
   return it;
 }
@@ -679,12 +678,6 @@ template <typename T>
 void Slice<T>::swap(Slice &rhs) noexcept {
   std::swap(*this, rhs);
 }
-
-template <typename T>
-void *Slice<T>::ptr() const noexcept {
-  void *slicePtr(const void *) noexcept;
-  return slicePtr(this);
-}
 #endif // CXXBRIDGE1_RUST_SLICE
 
 #ifndef CXXBRIDGE1_RUST_BOX

From 0e1cc3da8c58e7dfe6db4e97cae9aa8e6c4bc893 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 23:09:03 +0000
Subject: [PATCH 1988/2232] Hide slice implementation details from name lookup


---

diff --git a/include/cxx.h b/include/cxx.h
index acf2b1b..41138c8 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,6 +180,10 @@ public:
   void swap(Slice &) noexcept;
 
 private:
+  friend void sliceInit(void *, const void *, std::size_t) noexcept;
+  friend void *slicePtr(const void *) noexcept;
+  friend std::size_t sliceLen(const void *) noexcept;
+
   std::array<std::uintptr_t, 2> repr;
 };
 
@@ -485,10 +489,6 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
-void sliceInit(void *, const void *, std::size_t) noexcept;
-void *slicePtr(const void *) noexcept;
-std::size_t sliceLen(const void *) noexcept;
-
 template <typename T>
 Slice<T>::Slice() noexcept {
   sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0);

From 0194dc59471bc197742747db2a732accbfe6507c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 02 2021 23:28:21 +0000
Subject: [PATCH 1989/2232] Merge pull request #647 from dtolnay/slice


Preserve &[T]'s Rust representation in rust::Slice
---

diff --git a/include/cxx.h b/include/cxx.h
index 03f719f..41138c8 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -180,10 +180,11 @@ public:
   void swap(Slice &) noexcept;
 
 private:
-  // Not necessarily ABI compatible with &[T]. Codegen will translate to
-  // cxx::rust_slice::RustSlice which matches this layout.
-  void *ptr;
-  std::size_t len;
+  friend void sliceInit(void *, const void *, std::size_t) noexcept;
+  friend void *slicePtr(const void *) noexcept;
+  friend std::size_t sliceLen(const void *) noexcept;
+
+  std::array<std::uintptr_t, 2> repr;
 };
 
 template <typename T>
@@ -489,37 +490,39 @@ constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #ifndef CXXBRIDGE1_RUST_SLICE
 #define CXXBRIDGE1_RUST_SLICE
 template <typename T>
-Slice<T>::Slice() noexcept
-    : ptr(reinterpret_cast<void *>(align_of<T>())), len(0) {}
+Slice<T>::Slice() noexcept {
+  sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0);
+}
 
 template <typename T>
-Slice<T>::Slice(T *s, std::size_t count) noexcept
-    : ptr(const_cast<typename std::remove_const<T>::type *>(s)), len(count) {}
+Slice<T>::Slice(T *s, std::size_t count) noexcept {
+  sliceInit(this, const_cast<typename std::remove_const<T>::type *>(s), count);
+}
 
 template <typename T>
 T *Slice<T>::data() const noexcept {
-  return reinterpret_cast<T *>(this->ptr);
+  return reinterpret_cast<T *>(slicePtr(this));
 }
 
 template <typename T>
 std::size_t Slice<T>::size() const noexcept {
-  return this->len;
+  return sliceLen(this);
 }
 
 template <typename T>
 std::size_t Slice<T>::length() const noexcept {
-  return this->len;
+  return this->size();
 }
 
 template <typename T>
 bool Slice<T>::empty() const noexcept {
-  return this->len == 0;
+  return this->size() == 0;
 }
 
 template <typename T>
 T &Slice<T>::operator[](std::size_t n) const noexcept {
   assert(n < this->size());
-  auto pos = static_cast<char *>(this->ptr) + size_of<T>() * n;
+  auto pos = static_cast<char *>(slicePtr(this)) + size_of<T>() * n;
   return *reinterpret_cast<T *>(pos);
 }
 
@@ -540,7 +543,7 @@ T &Slice<T>::front() const noexcept {
 template <typename T>
 T &Slice<T>::back() const noexcept {
   assert(!this->empty());
-  return (*this)[this->len - 1];
+  return (*this)[this->size() - 1];
 }
 
 template <typename T>
@@ -659,7 +662,7 @@ bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::begin() const noexcept {
   iterator it;
-  it.pos = this->ptr;
+  it.pos = slicePtr(this);
   it.stride = size_of<T>();
   return it;
 }
@@ -667,7 +670,7 @@ typename Slice<T>::iterator Slice<T>::begin() const noexcept {
 template <typename T>
 typename Slice<T>::iterator Slice<T>::end() const noexcept {
   iterator it = this->begin();
-  it.pos = static_cast<char *>(it.pos) + it.stride * this->len;
+  it.pos = static_cast<char *>(it.pos) + it.stride * this->size();
   return it;
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index 605845e..ccf44b2 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -45,6 +45,12 @@ bool cxxbridge1$str$from(rust::Str *self, const char *ptr,
                          std::size_t len) noexcept;
 const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept;
 std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept;
+
+// rust::Slice
+void cxxbridge1$slice$new(void *self, const void *ptr,
+                          std::size_t len) noexcept;
+void *cxxbridge1$slice$ptr(const void *self) noexcept;
+std::size_t cxxbridge1$slice$len(const void *self) noexcept;
 } // extern "C"
 
 namespace rust {
@@ -274,6 +280,16 @@ std::ostream &operator<<(std::ostream &os, const Str &s) {
   return os;
 }
 
+void sliceInit(void *self, const void *ptr, std::size_t len) noexcept {
+  cxxbridge1$slice$new(self, ptr, len);
+}
+
+void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); }
+
+std::size_t sliceLen(const void *self) noexcept {
+  return cxxbridge1$slice$len(self);
+}
+
 // Rust specifies that usize is ABI compatible with C's uintptr_t.
 // https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize
 // However there is no direct Rust equivalent for size_t. C does not guarantee
diff --git a/src/rust_slice.rs b/src/rust_slice.rs
index 8a5e74b..b4b5f2c 100644
--- a/src/rust_slice.rs
+++ b/src/rust_slice.rs
@@ -1,36 +1,37 @@
 use core::mem;
-use core::ptr::NonNull;
+use core::ptr::{self, NonNull};
 use core::slice;
 
-// Not necessarily ABI compatible with &[T]. Codegen performs the translation.
 #[repr(C)]
-#[derive(Copy, Clone)]
 pub struct RustSlice {
-    pub(crate) ptr: NonNull<()>,
-    pub(crate) len: usize,
+    pub(crate) repr: NonNull<[()]>,
 }
 
 impl RustSlice {
-    pub fn from_ref<T>(s: &[T]) -> Self {
+    pub fn from_ref<T>(slice: &[T]) -> Self {
+        let ptr = ptr::slice_from_raw_parts::<()>(slice.as_ptr().cast(), slice.len());
         RustSlice {
-            ptr: NonNull::from(s).cast::<()>(),
-            len: s.len(),
+            repr: unsafe { NonNull::new_unchecked(ptr as *mut _) },
         }
     }
 
-    pub fn from_mut<T>(s: &mut [T]) -> Self {
+    pub fn from_mut<T>(slice: &mut [T]) -> Self {
+        let ptr = ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len());
         RustSlice {
-            len: s.len(),
-            ptr: NonNull::from(s).cast::<()>(),
+            repr: unsafe { NonNull::new_unchecked(ptr) },
         }
     }
 
     pub unsafe fn as_slice<'a, T>(self) -> &'a [T] {
-        slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), self.len)
+        let ptr = self.repr.as_ptr();
+        let len = self.repr.as_ref().len();
+        slice::from_raw_parts(ptr.cast(), len)
     }
 
     pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] {
-        slice::from_raw_parts_mut(self.ptr.as_ptr().cast::<T>(), self.len)
+        let ptr = self.repr.as_ptr();
+        let len = self.repr.as_ref().len();
+        slice::from_raw_parts_mut(ptr.cast(), len)
     }
 }
 
diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs
index a9d158d..e00bb55 100644
--- a/src/symbols/mod.rs
+++ b/src/symbols/mod.rs
@@ -1,4 +1,5 @@
 mod exception;
+mod rust_slice;
 mod rust_str;
 mod rust_string;
 mod rust_vec;
diff --git a/src/symbols/rust_slice.rs b/src/symbols/rust_slice.rs
new file mode 100644
index 0000000..055b4de
--- /dev/null
+++ b/src/symbols/rust_slice.rs
@@ -0,0 +1,22 @@
+use crate::rust_slice::RustSlice;
+use core::mem::MaybeUninit;
+use core::ptr::{self, NonNull};
+
+#[export_name = "cxxbridge1$slice$new"]
+unsafe extern "C" fn slice_new(this: &mut MaybeUninit<RustSlice>, ptr: *const (), len: usize) {
+    let ptr = ptr::slice_from_raw_parts(ptr, len);
+    let rust_slice = RustSlice {
+        repr: NonNull::new_unchecked(ptr as *mut _),
+    };
+    ptr::write(this.as_mut_ptr(), rust_slice);
+}
+
+#[export_name = "cxxbridge1$slice$ptr"]
+unsafe extern "C" fn slice_ptr(this: &RustSlice) -> *const () {
+    this.repr.as_ptr().cast()
+}
+
+#[export_name = "cxxbridge1$slice$len"]
+unsafe extern "C" fn slice_len(this: &RustSlice) -> usize {
+    this.repr.as_ref().len()
+}

From dc2d4c37473be3848dfcf33e480b964cb4dd099d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:14:31 +0000
Subject: [PATCH 1990/2232] Mark error conversion function noexcept


This prevents a std::bad_alloc exception from operator new[] from
potentially propagating into Rust, which would be UB.

---

diff --git a/src/cxx.cc b/src/cxx.cc
index ccf44b2..9b4357c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -351,7 +351,7 @@ static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
               "Vec<T>::const_iterator != Vec<T>::iterator");
 
 extern "C" {
-const char *cxxbridge1$error(const char *ptr, std::size_t len) {
+const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
   char *copy = new char[len];
   std::strncpy(copy, ptr, len);
   return copy;

From ba750b626d05820a0464e7754dab6bd94330a12a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:24:00 +0000
Subject: [PATCH 1991/2232] Silence -Wunused-private-field warning on macOS


    In file included from src/cxx.cc:1:
    src/../include/cxx.h:131:33: error: private field 'repr' is not used [-Werror,-Wunused-private-field]
      std::array<std::uintptr_t, 2> repr;
                                    ^

---

diff --git a/src/cxx.cc b/src/cxx.cc
index 9b4357c..15dc998 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -273,7 +273,10 @@ bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; }
 
 bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; }
 
-void Str::swap(Str &rhs) noexcept { std::swap(*this, rhs); }
+void Str::swap(Str &rhs) noexcept {
+  using std::swap;
+  swap(this->repr, rhs.repr);
+}
 
 std::ostream &operator<<(std::ostream &os, const Str &s) {
   os.write(s.data(), s.size());

From 6c125208364863a80fb38f26eac85255e46f21f5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:24:00 +0000
Subject: [PATCH 1992/2232] Clean some unneeded string manipulation from exception conversion


These used to be needed prior to #644.

---

diff --git a/src/result.rs b/src/result.rs
index 7927c20..ecc3a41 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -45,11 +45,9 @@ unsafe fn to_c_error(msg: String) -> Result {
     }
 
     let copy = error(ptr, len);
-    let slice = slice::from_raw_parts(copy, len);
-    let string = str::from_utf8_unchecked(slice);
     let err = PtrLen {
-        ptr: NonNull::from(string).cast::<u8>(),
-        len: string.len(),
+        ptr: NonNull::new_unchecked(copy as *mut u8),
+        len,
     };
     Result { err }
 }

From 837eefee5e73d94c793be1ff8181b2f6b0ced582 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:24:00 +0000
Subject: [PATCH 1993/2232] Simplify to_c_error by using NonNull inline


---

diff --git a/src/result.rs b/src/result.rs
index ecc3a41..f41639a 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -41,14 +41,11 @@ unsafe fn to_c_error(msg: String) -> Result {
 
     extern "C" {
         #[link_name = "cxxbridge1$error"]
-        fn error(ptr: *const u8, len: usize) -> *const u8;
+        fn error(ptr: *const u8, len: usize) -> NonNull<u8>;
     }
 
     let copy = error(ptr, len);
-    let err = PtrLen {
-        ptr: NonNull::new_unchecked(copy as *mut u8),
-        len,
-    };
+    let err = PtrLen { ptr: copy, len };
     Result { err }
 }
 

From 10c48f5904077748f3531a8c7062862cda5e0b49 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:40:08 +0000
Subject: [PATCH 1994/2232] Resolve msvc warning on strncpy by replacing with memcpy


    src/cxx.cc(356): error C2220: the following warning is treated as an error
    src/cxx.cc(356): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

---

diff --git a/src/cxx.cc b/src/cxx.cc
index 15dc998..56c3696 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -355,9 +355,8 @@ static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
 
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
-  char *copy = new char[len];
-  std::strncpy(copy, ptr, len);
-  return copy;
+  return ptr ? static_cast<char *>(std::memcpy(new char[len], ptr, len))
+             : nullptr;
 }
 } // extern "C"
 

From 4ddae80e7d9ef26959067c671ec935e0e64ac498 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 00:48:50 +0000
Subject: [PATCH 1995/2232] Allow through bad_alloc from Error(const Error &) and operator=


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 56c3696..9983fba 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -353,15 +353,21 @@ static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator,
                             Vec<std::uint8_t>::iterator>::value,
               "Vec<T>::const_iterator != Vec<T>::iterator");
 
+static const char *errorCopy(const char *ptr, std::size_t len) {
+  char *copy = new char[len];
+  std::memcpy(copy, ptr, len);
+  return copy;
+}
+
 extern "C" {
 const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept {
-  return ptr ? static_cast<char *>(std::memcpy(new char[len], ptr, len))
-             : nullptr;
+  return errorCopy(ptr, len);
 }
 } // extern "C"
 
 Error::Error(const Error &other)
-    : std::exception(other), msg(cxxbridge1$error(other.msg, other.len)),
+    : std::exception(other),
+      msg(other.msg ? errorCopy(other.msg, other.len) : nullptr),
       len(other.len) {}
 
 Error::Error(Error &&other) noexcept
@@ -377,8 +383,10 @@ Error &Error::operator=(const Error &other) {
     std::exception::operator=(other);
     delete[] this->msg;
     this->msg = nullptr;
-    this->msg = cxxbridge1$error(other.msg, other.len);
-    this->len = other.len;
+    if (other.msg) {
+      this->msg = errorCopy(other.msg, other.len);
+      this->len = other.len;
+    }
   }
   return *this;
 }

From bf6731a13b9c450aa1c57c4f4b9466806f7bceef Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 01:31:34 +0000
Subject: [PATCH 1996/2232] Clean up stray whitespace from PR 642


---

diff --git a/include/cxx.h b/include/cxx.h
index 41138c8..4a1316f 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -84,7 +84,6 @@ private:
   // Size and alignment statically verified by rust_string.rs.
   std::array<std::uintptr_t, 3> repr;
 };
-
 #endif // CXXBRIDGE1_RUST_STRING
 
 #ifndef CXXBRIDGE1_RUST_STR

From e05de8796e16da8c388f8353b7f9c41978ef9355 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:21:06 +0000
Subject: [PATCH 1997/2232] Move template class workaround to implementation files only


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 609814c..c7c9dc7 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -121,23 +121,25 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     out.set_namespace(Default::default());
 
-    // MSVC workaround for "C linkage function cannot return C++ class" error.
-    // Apparently the compiler fails to perform implicit instantiations as part
-    // of an extern declaration. Instead we instantiate explicitly.
-    // See https://stackoverflow.com/a/57429504/6086311.
-    out.next_section();
-    let mut slice_in_return_position = OrderedSet::new();
-    for api in apis {
-        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
-                slice_in_return_position.insert(ty);
+    if !out.header {
+        // MSVC workaround for "C linkage function cannot return C++ class" error.
+        // Apparently the compiler fails to perform implicit instantiations as part
+        // of an extern declaration return type. Instead we instantiate explicitly.
+        // See https://stackoverflow.com/a/57429504/6086311.
+        out.next_section();
+        let mut slice_in_return_position = OrderedSet::new();
+        for api in apis {
+            if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
+                if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+                    slice_in_return_position.insert(ty);
+                }
             }
         }
-    }
-    for ty in &slice_in_return_position {
-        write!(out, "template class ");
-        write_type(out, ty);
-        writeln!(out, ";");
+        for ty in &slice_in_return_position {
+            write!(out, "template class ");
+            write_type(out, ty);
+            writeln!(out, ";");
+        }
     }
 
     out.next_section();
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 548ad13..302944a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -849,6 +849,9 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
 template class rust::Box<tests::Shared>;
+template class rust::Slice<const char>;
+template class rust::Slice<const uint8_t>;
+template class rust::Slice<uint8_t>;
 template class rust::Slice<const tests::Shared>;
 template class rust::Slice<tests::Shared>;
 template class rust::Slice<const tests::R>;

From 36614d60d4b7fb277e3ab1b381009dcee7f8fa50 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:30:15 +0000
Subject: [PATCH 1998/2232] Move triviality static assertions to implementation files only


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index c7c9dc7..370dac4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -140,13 +140,13 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
             write_type(out, ty);
             writeln!(out, ";");
         }
-    }
 
-    out.next_section();
-    for api in apis {
-        if let Api::TypeAlias(ety) = api {
-            if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
-                check_trivial_extern_type(out, ety, reasons)
+        out.next_section();
+        for api in apis {
+            if let Api::TypeAlias(ety) = api {
+                if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
+                    check_trivial_extern_type(out, ety, reasons)
+                }
             }
         }
     }

From 8b22953347a4a2e5ed882927ff06b0ade645acf2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:30:45 +0000
Subject: [PATCH 1999/2232] Reduce indentation in write_data_structures


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 370dac4..dcb7850 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -119,34 +119,36 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
         }
     }
 
+    if out.header {
+        return;
+    }
+
     out.set_namespace(Default::default());
 
-    if !out.header {
-        // MSVC workaround for "C linkage function cannot return C++ class" error.
-        // Apparently the compiler fails to perform implicit instantiations as part
-        // of an extern declaration return type. Instead we instantiate explicitly.
-        // See https://stackoverflow.com/a/57429504/6086311.
-        out.next_section();
-        let mut slice_in_return_position = OrderedSet::new();
-        for api in apis {
-            if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-                if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
-                    slice_in_return_position.insert(ty);
-                }
+    // MSVC workaround for "C linkage function cannot return C++ class" error.
+    // Apparently the compiler fails to perform implicit instantiations as part
+    // of an extern declaration return type. Instead we instantiate explicitly.
+    // See https://stackoverflow.com/a/57429504/6086311.
+    out.next_section();
+    let mut slice_in_return_position = OrderedSet::new();
+    for api in apis {
+        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
+            if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+                slice_in_return_position.insert(ty);
             }
         }
-        for ty in &slice_in_return_position {
-            write!(out, "template class ");
-            write_type(out, ty);
-            writeln!(out, ";");
-        }
+    }
+    for ty in &slice_in_return_position {
+        write!(out, "template class ");
+        write_type(out, ty);
+        writeln!(out, ";");
+    }
 
-        out.next_section();
-        for api in apis {
-            if let Api::TypeAlias(ety) = api {
-                if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
-                    check_trivial_extern_type(out, ety, reasons)
-                }
+    out.next_section();
+    for api in apis {
+        if let Api::TypeAlias(ety) = api {
+            if let Some(reasons) = out.types.required_trivial.get(&ety.name.rust) {
+                check_trivial_extern_type(out, ety, reasons)
             }
         }
     }

From fe77f3323baf2ffa14a6f50b0c64b2c53705bbf1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:34:50 +0000
Subject: [PATCH 2000/2232] Resolve MSVC "C-linkage specified, but returns UDT" warning


    cxxbridge\sources\tests\ffi\lib.rs.cc(1335): warning C4190: 'tests$cxxbridge1$c_return_str' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Str' which is incompatible with C
    cxxbridge\include\rust/cxx.h(93): note: see declaration of 'rust::cxxbridge1::Str'
    cxxbridge\sources\tests\ffi\lib.rs.cc(1340): warning C4190: 'tests$cxxbridge1$c_return_slice_char' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Slice<const char>' which is incompatible with C
    cxxbridge\crate\tests/ffi/tests.h(93): note: see declaration of 'rust::cxxbridge1::Slice<const char>'
    cxxbridge\sources\tests\ffi\lib.rs.cc(1345): warning C4190: 'tests$cxxbridge1$c_return_mutsliceu8' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Slice<uint8_t>' which is incompatible with C
    cxxbridge\crate\tests/ffi/tests.h(94): note: see declaration of 'rust::cxxbridge1::Slice<uint8_t>'
    cxxbridge\sources\tests\ffi\lib.rs.cc(1976): warning C4190: 'tests$cxxbridge1$r_return_str' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Str' which is incompatible with C
    cxxbridge\include\rust/cxx.h(93): note: see declaration of 'rust::cxxbridge1::Str'
    cxxbridge\sources\tests\ffi\lib.rs.cc(1978): warning C4190: 'tests$cxxbridge1$r_return_sliceu8' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Slice<const uint8_t>' which is incompatible with C
    cxxbridge\crate\tests/ffi/tests.h(163): note: see declaration of 'rust::cxxbridge1::Slice<const uint8_t>'
    cxxbridge\sources\tests\ffi\lib.rs.cc(1980): warning C4190: 'tests$cxxbridge1$r_return_mutsliceu8' has C-linkage specified, but returns UDT 'rust::cxxbridge1::Slice<uint8_t>' which is incompatible with C
    cxxbridge\crate\tests/ffi/tests.h(94): note: see declaration of 'rust::cxxbridge1::Slice<uint8_t>'

---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 7b15b61..65cd703 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -20,6 +20,7 @@ pub struct Builtins<'a> {
     pub maybe_uninit: bool,
     pub trycatch: bool,
     pub ptr_len: bool,
+    pub repr_fat: bool,
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
@@ -230,6 +231,17 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
+    if builtin.repr_fat {
+        include.array = true;
+        include.cstdint = true;
+        out.begin_block(Block::Namespace("repr"));
+        writeln!(out, "template <typename T>");
+        writeln!(out, "struct Fat final {{");
+        writeln!(out, "  T repr;");
+        writeln!(out, "}};");
+        out.end_block(Block::Namespace("repr"));
+    }
+
     if builtin.rust_error {
         out.next_section();
         writeln!(out, "template <>");
diff --git a/gen/src/write.rs b/gen/src/write.rs
index dcb7850..02f615d 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -133,15 +133,15 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
     let mut slice_in_return_position = OrderedSet::new();
     for api in apis {
         if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            if let Some(ty @ Type::SliceRef(_)) = &efn.ret {
+            if let Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) = &efn.ret {
                 slice_in_return_position.insert(ty);
             }
         }
     }
     for ty in &slice_in_return_position {
-        write!(out, "template class ");
+        write!(out, "template class ::rust::repr::Fat<");
         write_type(out, ty);
-        writeln!(out, ";");
+        writeln!(out, ">;");
     }
 
     out.next_section();
@@ -756,8 +756,10 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     } else if efn.ret.is_some() {
         write!(out, "return ");
     }
-    if let Some(Type::Ref(_)) = efn.ret {
-        write!(out, "&");
+    match &efn.ret {
+        Some(Type::Ref(_)) => write!(out, "&"),
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "{{"),
+        _ => {}
     }
     match &efn.receiver {
         None => write!(out, "{}$(", efn.name.rust),
@@ -795,6 +797,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "}}"),
         _ => {}
     }
     if indirect_return {
@@ -1038,8 +1041,10 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
-                write!(out, ")");
+            match ret {
+                Type::RustBox(_) | Type::UniquePtr(_) => write!(out, ")"),
+                Type::Str(_) | Type::SliceRef(_) => write!(out, ".repr"),
+                _ => {}
             }
         }
     }
@@ -1109,6 +1114,12 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
+        Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) => {
+            out.builtin.repr_fat = true;
+            write!(out, "::rust::repr::Fat<");
+            write_type(out, ty);
+            write!(out, "> ");
+        }
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
     }

From 8f940cf26931bf5b813fb837fc99d77d1ba53d17 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:45:02 +0000
Subject: [PATCH 2001/2232] Explicitly delete opaque Rust type destructors


I guess MSVC finds this important enough to emit warnings about.

    cxxbridge\sources\tests\ffi\lib.rs.cc(1220): warning C4624: 'tests::R': destructor was implicitly defined as deleted

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 02f615d..c6331f4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -359,9 +359,8 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
         writeln!(out, ";");
     }
 
-    if !methods.is_empty() {
-        writeln!(out);
-    }
+    writeln!(out, "  ~{}() = delete;", ety.name.cxx);
+    writeln!(out);
 
     out.builtin.layout = true;
     out.include.cstddef = true;

From e229bf7193e133fc7dac2a3636f83a33c62655d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:55:11 +0000
Subject: [PATCH 2002/2232] Merge pull request #648 from dtolnay/destructor


Explicitly delete opaque Rust type destructors
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 02f615d..c6331f4 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -359,9 +359,8 @@ fn write_opaque_type<'a>(out: &mut OutFile<'a>, ety: &'a ExternType, methods: &[
         writeln!(out, ";");
     }
 
-    if !methods.is_empty() {
-        writeln!(out);
-    }
+    writeln!(out, "  ~{}() = delete;", ety.name.cxx);
+    writeln!(out);
 
     out.builtin.layout = true;
     out.include.cstddef = true;

From 671d2b90eabd9ade1f29b587bf7fb4a24ae240a6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 02:55:34 +0000
Subject: [PATCH 2003/2232] Enable standard exception handling for MSVC in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c9d60f8..7139f4a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,6 +26,9 @@ jobs:
           - name: Windows (msvc)
             rust: nightly-x86_64-pc-windows-msvc
             os: windows
+            flags: /EHsc
+    env:
+      CXXFLAGS: ${{matrix.flags}}
     steps:
       - name: Enable symlinks (windows)
         if: matrix.os == 'windows'

From 85805cec905c8a19182ba7bc21dba78bc351bb2d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 04:06:28 +0000
Subject: [PATCH 2004/2232] Turn off explicit instantiations in test suite on MSVC


MSVC warns about the ones that are specialized out of line.

    cxxbridge\include\rust/cxx.h(324): warning C4661: 'rust::cxxbridge1::Vec<uint8_t>::Vec(void) noexcept': no suitable definition provided for explicit template instantiation request
    cxxbridge\include\rust/cxx.h(269): note: see declaration of 'rust::cxxbridge1::Vec<uint8_t>::Vec'
    cxxbridge\include\rust/cxx.h(324): warning C4661: 'size_t rust::cxxbridge1::Vec<uint8_t>::size(void) noexcept const': no suitable definition provided for explicit template instantiation request
    cxxbridge\include\rust/cxx.h(278): note: see declaration of 'rust::cxxbridge1::Vec<uint8_t>::size'
    cxxbridge\include\rust/cxx.h(324): warning C4661: 'const T *rust::cxxbridge1::Vec<T>::data(void) noexcept const': no suitable definition provided for explicit template instantiation request
            with
            [
                T=uint8_t
            ]
    cxxbridge\include\rust/cxx.h(280): note: see declaration of 'rust::cxxbridge1::Vec<uint8_t>::data'
    cxxbridge\include\rust/cxx.h(324): warning C4661: 'size_t rust::cxxbridge1::Vec<uint8_t>::capacity(void) noexcept const': no suitable definition provided for explicit template instantiation request
    cxxbridge\include\rust/cxx.h(282): note: see declaration of 'rust::cxxbridge1::Vec<uint8_t>::capacity'

---

diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index e583944..c8f010e 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -7,8 +7,11 @@ fn main() {
 
     CFG.include_prefix = "tests/ffi";
     let sources = vec!["lib.rs", "module.rs"];
-    cxx_build::bridges(sources)
-        .file("tests.cc")
-        .flag_if_supported(cxxbridge_flags::STD)
-        .compile("cxx-test-suite");
+    let mut build = cxx_build::bridges(sources);
+    build.file("tests.cc");
+    build.flag_if_supported(cxxbridge_flags::STD);
+    if cfg!(not(target_env = "msvc")) {
+        build.define("CXX_TEST_INSTANTIATIONS", None);
+    }
+    build.compile("cxx-test-suite");
 }
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 302944a..9c3c62a 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -848,6 +848,7 @@ std::unique_ptr<I> ns_c_return_unique_ptr_ns() {
 // > serves as an explicit instantiation of the same kind (declaration or
 // > definition) of each of its non-inherited non-template members that has not
 // > been previously explicitly specialized in the translation unit.
+#if defined(CXX_TEST_INSTANTIATIONS)
 template class rust::Box<tests::Shared>;
 template class rust::Slice<const char>;
 template class rust::Slice<const uint8_t>;
@@ -860,3 +861,4 @@ template class rust::Vec<uint8_t>;
 template class rust::Vec<rust::String>;
 template class rust::Vec<tests::Shared>;
 template class rust::Fn<size_t(rust::String)>;
+#endif

From e5cd1489e3c02a62aab5814af6cb7a4ca965bc6c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 05:28:14 +0000
Subject: [PATCH 2005/2232] Fix remaining "C-linkage specified, but returns UDT" warnings on macOS


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 65cd703..5248a20 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -21,6 +21,10 @@ pub struct Builtins<'a> {
     pub trycatch: bool,
     pub ptr_len: bool,
     pub repr_fat: bool,
+    pub rust_str_new_unchecked: bool,
+    pub rust_str_repr: bool,
+    pub rust_slice_new: bool,
+    pub rust_slice_repr: bool,
     pub exception: bool,
     pub relocatable: bool,
     pub friend_impl: bool,
@@ -162,6 +166,20 @@ pub(super) fn write(out: &mut OutFile) {
     ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
     ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
 
+    if builtin.rust_str_new_unchecked {
+        out.next_section();
+        writeln!(out, "class Str::uninit {{}};");
+        writeln!(out, "inline Str::Str(uninit) noexcept {{}}");
+    }
+
+    if builtin.rust_slice_new {
+        out.next_section();
+        writeln!(out, "template <typename T>");
+        writeln!(out, "class Slice<T>::uninit {{}};");
+        writeln!(out, "template <typename T>");
+        writeln!(out, "inline Slice<T>::Slice(uninit) noexcept {{}}");
+    }
+
     out.begin_block(Block::Namespace("detail"));
 
     if builtin.maybe_uninit {
@@ -221,8 +239,18 @@ pub(super) fn write(out: &mut OutFile) {
 
     out.begin_block(Block::AnonymousNamespace);
 
+    if builtin.repr_fat {
+        include.array = true;
+        include.cstdint = true;
+        out.next_section();
+        out.begin_block(Block::Namespace("repr"));
+        writeln!(out, "using Fat = ::std::array<::std::uintptr_t, 2>;");
+        out.end_block(Block::Namespace("repr"));
+    }
+
     if builtin.ptr_len {
         include.cstddef = true;
+        out.next_section();
         out.begin_block(Block::Namespace("repr"));
         writeln!(out, "struct PtrLen final {{");
         writeln!(out, "  void *ptr;");
@@ -231,15 +259,47 @@ pub(super) fn write(out: &mut OutFile) {
         out.end_block(Block::Namespace("repr"));
     }
 
-    if builtin.repr_fat {
-        include.array = true;
-        include.cstdint = true;
-        out.begin_block(Block::Namespace("repr"));
+    if builtin.rust_str_new_unchecked || builtin.rust_str_repr {
+        out.next_section();
+        writeln!(out, "template <>");
+        writeln!(out, "class impl<Str> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_str_new_unchecked {
+            writeln!(
+                out,
+                "  static Str new_unchecked(repr::Fat repr) noexcept {{",
+            );
+            writeln!(out, "    Str str = Str::uninit{{}};");
+            writeln!(out, "    str.repr = repr;");
+            writeln!(out, "    return str;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_str_repr {
+            writeln!(out, "  static repr::Fat repr(Str str) noexcept {{");
+            writeln!(out, "    return str.repr;");
+            writeln!(out, "  }}");
+        }
+        writeln!(out, "}};");
+    }
+
+    if builtin.rust_slice_new || builtin.rust_slice_repr {
+        out.next_section();
         writeln!(out, "template <typename T>");
-        writeln!(out, "struct Fat final {{");
-        writeln!(out, "  T repr;");
+        writeln!(out, "class impl<Slice<T>> final {{");
+        writeln!(out, "public:");
+        if builtin.rust_slice_new {
+            writeln!(out, "  static Slice<T> slice(repr::Fat repr) noexcept {{");
+            writeln!(out, "    Slice<T> slice = typename Slice<T>::uninit{{}};");
+            writeln!(out, "    slice.repr = repr;");
+            writeln!(out, "    return slice;");
+            writeln!(out, "  }}");
+        }
+        if builtin.rust_slice_repr {
+            writeln!(out, "  static repr::Fat repr(Slice<T> slice) noexcept {{");
+            writeln!(out, "    return slice.repr;");
+            writeln!(out, "  }}");
+        }
         writeln!(out, "}};");
-        out.end_block(Block::Namespace("repr"));
     }
 
     if builtin.rust_error {
diff --git a/gen/src/write.rs b/gen/src/write.rs
index c6331f4..2404f9c 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -5,7 +5,7 @@ use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::instantiate::ImplKey;
 use crate::syntax::map::UnorderedMap as Map;
-use crate::syntax::set::{OrderedSet, UnorderedSet};
+use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::trivial::{self, TrivialReason};
 use crate::syntax::{
@@ -125,25 +125,6 @@ fn write_data_structures<'a>(out: &mut OutFile<'a>, apis: &'a [Api]) {
 
     out.set_namespace(Default::default());
 
-    // MSVC workaround for "C linkage function cannot return C++ class" error.
-    // Apparently the compiler fails to perform implicit instantiations as part
-    // of an extern declaration return type. Instead we instantiate explicitly.
-    // See https://stackoverflow.com/a/57429504/6086311.
-    out.next_section();
-    let mut slice_in_return_position = OrderedSet::new();
-    for api in apis {
-        if let Api::CxxFunction(efn) | Api::RustFunction(efn) = api {
-            if let Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) = &efn.ret {
-                slice_in_return_position.insert(ty);
-            }
-        }
-    }
-    for ty in &slice_in_return_position {
-        write!(out, "template class ::rust::repr::Fat<");
-        write_type(out, ty);
-        writeln!(out, ">;");
-    }
-
     out.next_section();
     for api in apis {
         if let Api::TypeAlias(ety) = api {
@@ -757,7 +738,16 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     }
     match &efn.ret {
         Some(Type::Ref(_)) => write!(out, "&"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "{{"),
+        Some(Type::Str(_)) if !indirect_return => {
+            out.builtin.rust_str_repr = true;
+            write!(out, "::rust::impl<::rust::Str>::repr(");
+        }
+        Some(ty @ Type::SliceRef(_)) if !indirect_return => {
+            out.builtin.rust_slice_repr = true;
+            write!(out, "::rust::impl<");
+            write_type(out, ty);
+            write!(out, ">::repr(");
+        }
         _ => {}
     }
     match &efn.receiver {
@@ -796,7 +786,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
     match &efn.ret {
         Some(Type::RustBox(_)) => write!(out, ".into_raw()"),
         Some(Type::UniquePtr(_)) => write!(out, ".release()"),
-        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, "}}"),
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) if !indirect_return => write!(out, ")"),
         _ => {}
     }
     if indirect_return {
@@ -995,6 +985,16 @@ fn write_rust_function_shim_impl(
                 write!(out, "(");
             }
             Type::Ref(_) => write!(out, "*"),
+            Type::Str(_) => {
+                out.builtin.rust_str_new_unchecked = true;
+                write!(out, "::rust::impl<::rust::Str>::new_unchecked(");
+            }
+            Type::SliceRef(_) => {
+                out.builtin.rust_slice_new = true;
+                write!(out, "::rust::impl<");
+                write_type(out, ret);
+                write!(out, ">::slice(");
+            }
             _ => {}
         }
     }
@@ -1040,10 +1040,8 @@ fn write_rust_function_shim_impl(
     write!(out, ")");
     if !indirect_return {
         if let Some(ret) = &sig.ret {
-            match ret {
-                Type::RustBox(_) | Type::UniquePtr(_) => write!(out, ")"),
-                Type::Str(_) | Type::SliceRef(_) => write!(out, ".repr"),
-                _ => {}
+            if let Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRef(_) = ret {
+                write!(out, ")");
             }
         }
     }
@@ -1113,11 +1111,9 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option<Type>) {
             write_type(out, &ty.inner);
             write!(out, " *");
         }
-        Some(ty @ Type::Str(_)) | Some(ty @ Type::SliceRef(_)) => {
+        Some(Type::Str(_)) | Some(Type::SliceRef(_)) => {
             out.builtin.repr_fat = true;
-            write!(out, "::rust::repr::Fat<");
-            write_type(out, ty);
-            write!(out, "> ");
+            write!(out, "::rust::repr::Fat ");
         }
         Some(ty) if out.types.needs_indirect_abi(ty) => write!(out, "void "),
         _ => write_return_type(out, ty),
diff --git a/include/cxx.h b/include/cxx.h
index 4a1316f..b9749de 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -127,6 +127,10 @@ public:
   void swap(Str &) noexcept;
 
 private:
+  class uninit;
+  Str(uninit) noexcept;
+  friend impl<Str>;
+
   std::array<std::uintptr_t, 2> repr;
 };
 #endif // CXXBRIDGE1_RUST_STR
@@ -179,6 +183,9 @@ public:
   void swap(Slice &) noexcept;
 
 private:
+  class uninit;
+  Slice(uninit) noexcept;
+  friend impl<Slice>;
   friend void sliceInit(void *, const void *, std::size_t) noexcept;
   friend void *slicePtr(const void *) noexcept;
   friend std::size_t sliceLen(const void *) noexcept;

From a9b3a77ba84f2ea64f3821fd8a6db34131f17d1b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 05:30:42 +0000
Subject: [PATCH 2006/2232] Trigger intentional warning in cxx.cc


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 9983fba..a4a060c 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -3,6 +3,8 @@
 #include <iostream>
 #include <memory>
 
+int warning() {}
+
 extern "C" {
 void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
                                 std::size_t len) noexcept {

From 970ed99049f1589ff1ede07aaeaf3b8747dbbb3f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 05:30:42 +0000
Subject: [PATCH 2007/2232] Add an option to fail build on C++ compile warnings


---

diff --git a/build.rs b/build.rs
index aec0dc9..f799441 100644
--- a/build.rs
+++ b/build.rs
@@ -8,6 +8,7 @@ fn main() {
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
+        .warnings_into_errors(cfg!(deny_warnings))
         .compile("cxxbridge1");
 
     println!("cargo:rerun-if-changed=src/cxx.cc");
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index c8f010e..86f8cd3 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -10,6 +10,7 @@ fn main() {
     let mut build = cxx_build::bridges(sources);
     build.file("tests.cc");
     build.flag_if_supported(cxxbridge_flags::STD);
+    build.warnings_into_errors(cfg!(deny_warnings));
     if cfg!(not(target_env = "msvc")) {
         build.define("CXX_TEST_INSTANTIATIONS", None);
     }

From 0e84959b2a02438a4da6d6240ffb9461db2f83fe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 05:30:43 +0000
Subject: [PATCH 2008/2232] Enable deny_warnings in CI


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7139f4a..9e1aef3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,6 +29,7 @@ jobs:
             flags: /EHsc
     env:
       CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings
     steps:
       - name: Enable symlinks (windows)
         if: matrix.os == 'windows'
@@ -45,7 +46,7 @@ jobs:
         # still ensure the test is kept passing on the basis of the scheduled
         # builds.
         if: matrix.os && github.event_name != 'schedule'
-        run: echo 'RUSTFLAGS=--cfg skip_ui_tests' >> $GITHUB_ENV
+        run: echo "RUSTFLAGS=--cfg skip_ui_tests $RUSTFLAGS" >> $GITHUB_ENV
         shell: bash
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite

From fc07064015689f0d712707362eef4192349427bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 05:30:43 +0000
Subject: [PATCH 2009/2232] Revert "Trigger intentional warning in cxx.cc"


---

diff --git a/src/cxx.cc b/src/cxx.cc
index a4a060c..9983fba 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -3,8 +3,6 @@
 #include <iostream>
 #include <memory>
 
-int warning() {}
-
 extern "C" {
 void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr,
                                 std::size_t len) noexcept {

From 341f1a19d3d96205cfd35949b9c3a2b070cf79bc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 06:04:07 +0000
Subject: [PATCH 2010/2232] Merge pull request #649 from dtolnay/warnings


Build with -Werror in CI
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7139f4a..9e1aef3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,6 +29,7 @@ jobs:
             flags: /EHsc
     env:
       CXXFLAGS: ${{matrix.flags}}
+      RUSTFLAGS: --cfg deny_warnings
     steps:
       - name: Enable symlinks (windows)
         if: matrix.os == 'windows'
@@ -45,7 +46,7 @@ jobs:
         # still ensure the test is kept passing on the basis of the scheduled
         # builds.
         if: matrix.os && github.event_name != 'schedule'
-        run: echo 'RUSTFLAGS=--cfg skip_ui_tests' >> $GITHUB_ENV
+        run: echo "RUSTFLAGS=--cfg skip_ui_tests $RUSTFLAGS" >> $GITHUB_ENV
         shell: bash
       - run: cargo run --manifest-path demo/Cargo.toml
       - run: cargo test --workspace --exclude cxx-test-suite
diff --git a/build.rs b/build.rs
index aec0dc9..f799441 100644
--- a/build.rs
+++ b/build.rs
@@ -8,6 +8,7 @@ fn main() {
         .cpp(true)
         .cpp_link_stdlib(None) // linked via link-cplusplus crate
         .flag_if_supported(cxxbridge_flags::STD)
+        .warnings_into_errors(cfg!(deny_warnings))
         .compile("cxxbridge1");
 
     println!("cargo:rerun-if-changed=src/cxx.cc");
diff --git a/tests/ffi/build.rs b/tests/ffi/build.rs
index c8f010e..86f8cd3 100644
--- a/tests/ffi/build.rs
+++ b/tests/ffi/build.rs
@@ -10,6 +10,7 @@ fn main() {
     let mut build = cxx_build::bridges(sources);
     build.file("tests.cc");
     build.flag_if_supported(cxxbridge_flags::STD);
+    build.warnings_into_errors(cfg!(deny_warnings));
     if cfg!(not(target_env = "msvc")) {
         build.define("CXX_TEST_INSTANTIATIONS", None);
     }

From 43d03b6737d153fcae4ec65d2bed347a75ad1bf6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 06:47:46 +0000
Subject: [PATCH 2011/2232] Parse lifetimes on shared structs


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 9d84799..3a7e00f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -73,18 +73,6 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         },
     );
 
-    let generics = &item.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
-        let struct_token = item.struct_token;
-        let ident = &item.ident;
-        let where_clause = &generics.where_clause;
-        let span = quote!(#struct_token #ident #generics #where_clause);
-        return Err(Error::new_spanned(
-            span,
-            "struct with generic parameters is not supported yet",
-        ));
-    }
-
     let named_fields = match item.fields {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
@@ -93,6 +81,46 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         }
     };
 
+    let mut lifetimes = Punctuated::new();
+    let mut has_unsupported_generic_param = false;
+    for pair in item.generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(param) => {
+                if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                    let msg = "lifetime parameter with bounds is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+                lifetimes.push_value(param.lifetime);
+                if let Some(punct) = punct {
+                    lifetimes.push_punct(punct);
+                }
+            }
+            GenericParam::Type(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "struct with generic type parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+            GenericParam::Const(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "struct with const generic parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+        }
+    }
+
+    if let Some(where_clause) = &item.generics.where_clause {
+        cx.error(
+            where_clause,
+            "struct with where-clause is not supported yet",
+        );
+    }
+
     let mut fields = Vec::new();
     for field in named_fields.named {
         let ident = field.ident.unwrap();
@@ -131,9 +159,9 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let generics = Lifetimes {
-        lt_token: None,
-        lifetimes: Punctuated::new(),
-        gt_token: None,
+        lt_token: item.generics.lt_token,
+        lifetimes,
+        gt_token: item.generics.gt_token,
     };
     let brace_token = named_fields.brace_token;
 
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 7c89129..f736fd1 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -1,8 +1,8 @@
-error: struct with generic parameters is not supported yet
+error: unit structs are not supported
  --> $DIR/multiple_parse_error.rs:3:5
   |
 3 |     struct Monad<T>;
-  |     ^^^^^^^^^^^^^^^
+  |     ^^^^^^^^^^^^^^^^
 
 error: unrecognized ABI, requires either "C++" or "Rust"
  --> $DIR/multiple_parse_error.rs:5:5

From 81b69558e4be8cdf5975bae8a4da7c427b36e561 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 06:49:17 +0000
Subject: [PATCH 2012/2232] Emit lifetimes into struct definition


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 980ba3f..11115b8 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -131,6 +131,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let doc = &strct.doc;
     let attrs = &strct.attrs;
+    let generics = &strct.generics;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         let doc = &field.doc;
@@ -147,7 +148,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let visibility = strct.visibility;
     let struct_token = strct.struct_token;
     let struct_def = quote_spanned! {span=>
-        #visibility #struct_token #ident {
+        #visibility #struct_token #ident #generics {
             #(#fields,)*
         }
     };
@@ -159,7 +160,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         #[repr(C)]
         #struct_def
 
-        unsafe impl ::cxx::ExternType for #ident {
+        unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }

From bc25f11e7b4851b547ebd559d9f7e69f982bce20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 06:52:23 +0000
Subject: [PATCH 2013/2232] Emit lifetimes into struct derived impls


---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 3e95ea4..2f77095 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -92,14 +92,16 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
 
 fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     quote_spanned! {span=>
-        impl ::std::marker::Copy for #ident {}
+        impl #generics ::std::marker::Copy for #ident #generics {}
     }
 }
 
 fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     let body = if derive::contains(&strct.derives, Trait::Copy) {
         quote!(*self)
@@ -117,7 +119,7 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     };
 
     quote_spanned! {span=>
-        impl ::std::clone::Clone for #ident {
+        impl #generics ::std::clone::Clone for #ident #generics {
             fn clone(&self) -> Self {
                 #body
             }
@@ -127,12 +129,13 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let struct_name = ident.to_string();
     let fields = strct.fields.iter().map(|field| &field.name.rust);
     let field_names = fields.clone().map(Ident::to_string);
 
     quote_spanned! {span=>
-        impl ::std::fmt::Debug for #ident {
+        impl #generics ::std::fmt::Debug for #ident #generics {
             fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 formatter.debug_struct(#struct_name)
                     #(.field(#field_names, &self.#fields))*
@@ -144,10 +147,11 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_default(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
-        impl ::std::default::Default for #ident {
+        impl #generics ::std::default::Default for #ident #generics {
             fn default() -> Self {
                 #ident {
                     #(
@@ -161,10 +165,11 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
-        impl ::std::cmp::Ord for #ident {
+        impl #generics ::std::cmp::Ord for #ident #generics {
             fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                 #(
                     match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) {
@@ -180,6 +185,7 @@ fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     let body = if derive::contains(&strct.derives, Trait::Ord) {
         quote! {
@@ -199,7 +205,7 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
     };
 
     quote_spanned! {span=>
-        impl ::std::cmp::PartialOrd for #ident {
+        impl #generics ::std::cmp::PartialOrd for #ident #generics {
             fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
                 #body
             }

From 62da0319659c6d616c3ddfd3efca24745369b0d1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 06:53:15 +0000
Subject: [PATCH 2014/2232] Test a struct definition containing lifetimes and derives


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d07ff45..be19697 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -80,6 +80,11 @@ pub mod ffi {
         a: [i32; 4],
     }
 
+    #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+    pub struct StructWithLifetime<'a> {
+        s: &'a str,
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 

From 4d7e4aa3a815c337ffe7676cdd94974193cc8f5c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:04:57 +0000
Subject: [PATCH 2015/2232] Merge pull request #650 from dtolnay/lifetime


Support lifetimes on shared structs
---

diff --git a/macro/src/derive.rs b/macro/src/derive.rs
index 3e95ea4..2f77095 100644
--- a/macro/src/derive.rs
+++ b/macro/src/derive.rs
@@ -92,14 +92,16 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
 
 fn struct_copy(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     quote_spanned! {span=>
-        impl ::std::marker::Copy for #ident {}
+        impl #generics ::std::marker::Copy for #ident #generics {}
     }
 }
 
 fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     let body = if derive::contains(&strct.derives, Trait::Copy) {
         quote!(*self)
@@ -117,7 +119,7 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
     };
 
     quote_spanned! {span=>
-        impl ::std::clone::Clone for #ident {
+        impl #generics ::std::clone::Clone for #ident #generics {
             fn clone(&self) -> Self {
                 #body
             }
@@ -127,12 +129,13 @@ fn struct_clone(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let struct_name = ident.to_string();
     let fields = strct.fields.iter().map(|field| &field.name.rust);
     let field_names = fields.clone().map(Ident::to_string);
 
     quote_spanned! {span=>
-        impl ::std::fmt::Debug for #ident {
+        impl #generics ::std::fmt::Debug for #ident #generics {
             fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 formatter.debug_struct(#struct_name)
                     #(.field(#field_names, &self.#fields))*
@@ -144,10 +147,11 @@ fn struct_debug(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_default(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
-        impl ::std::default::Default for #ident {
+        impl #generics ::std::default::Default for #ident #generics {
             fn default() -> Self {
                 #ident {
                     #(
@@ -161,10 +165,11 @@ fn struct_default(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
     let fields = strct.fields.iter().map(|field| &field.name.rust);
 
     quote_spanned! {span=>
-        impl ::std::cmp::Ord for #ident {
+        impl #generics ::std::cmp::Ord for #ident #generics {
             fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
                 #(
                     match ::std::cmp::Ord::cmp(&self.#fields, &other.#fields) {
@@ -180,6 +185,7 @@ fn struct_ord(strct: &Struct, span: Span) -> TokenStream {
 
 fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
     let ident = &strct.name.rust;
+    let generics = &strct.generics;
 
     let body = if derive::contains(&strct.derives, Trait::Ord) {
         quote! {
@@ -199,7 +205,7 @@ fn struct_partial_ord(strct: &Struct, span: Span) -> TokenStream {
     };
 
     quote_spanned! {span=>
-        impl ::std::cmp::PartialOrd for #ident {
+        impl #generics ::std::cmp::PartialOrd for #ident #generics {
             fn partial_cmp(&self, other: &Self) -> ::std::option::Option<::std::cmp::Ordering> {
                 #body
             }
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 980ba3f..11115b8 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -131,6 +131,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let doc = &strct.doc;
     let attrs = &strct.attrs;
+    let generics = &strct.generics;
     let type_id = type_id(&strct.name);
     let fields = strct.fields.iter().map(|field| {
         let doc = &field.doc;
@@ -147,7 +148,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
     let visibility = strct.visibility;
     let struct_token = strct.struct_token;
     let struct_def = quote_spanned! {span=>
-        #visibility #struct_token #ident {
+        #visibility #struct_token #ident #generics {
             #(#fields,)*
         }
     };
@@ -159,7 +160,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         #[repr(C)]
         #struct_def
 
-        unsafe impl ::cxx::ExternType for #ident {
+        unsafe impl #generics ::cxx::ExternType for #ident #generics {
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 9d84799..3a7e00f 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -73,18 +73,6 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         },
     );
 
-    let generics = &item.generics;
-    if !generics.params.is_empty() || generics.where_clause.is_some() {
-        let struct_token = item.struct_token;
-        let ident = &item.ident;
-        let where_clause = &generics.where_clause;
-        let span = quote!(#struct_token #ident #generics #where_clause);
-        return Err(Error::new_spanned(
-            span,
-            "struct with generic parameters is not supported yet",
-        ));
-    }
-
     let named_fields = match item.fields {
         Fields::Named(fields) => fields,
         Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
@@ -93,6 +81,46 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         }
     };
 
+    let mut lifetimes = Punctuated::new();
+    let mut has_unsupported_generic_param = false;
+    for pair in item.generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(param) => {
+                if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                    let msg = "lifetime parameter with bounds is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+                lifetimes.push_value(param.lifetime);
+                if let Some(punct) = punct {
+                    lifetimes.push_punct(punct);
+                }
+            }
+            GenericParam::Type(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "struct with generic type parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+            GenericParam::Const(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "struct with const generic parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+        }
+    }
+
+    if let Some(where_clause) = &item.generics.where_clause {
+        cx.error(
+            where_clause,
+            "struct with where-clause is not supported yet",
+        );
+    }
+
     let mut fields = Vec::new();
     for field in named_fields.named {
         let ident = field.ident.unwrap();
@@ -131,9 +159,9 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
     let struct_token = item.struct_token;
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let generics = Lifetimes {
-        lt_token: None,
-        lifetimes: Punctuated::new(),
-        gt_token: None,
+        lt_token: item.generics.lt_token,
+        lifetimes,
+        gt_token: item.generics.gt_token,
     };
     let brace_token = named_fields.brace_token;
 
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index d07ff45..be19697 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -80,6 +80,11 @@ pub mod ffi {
         a: [i32; 4],
     }
 
+    #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+    pub struct StructWithLifetime<'a> {
+        s: &'a str,
+    }
+
     unsafe extern "C++" {
         include!("tests/ffi/tests.h");
 
diff --git a/tests/ui/multiple_parse_error.stderr b/tests/ui/multiple_parse_error.stderr
index 7c89129..f736fd1 100644
--- a/tests/ui/multiple_parse_error.stderr
+++ b/tests/ui/multiple_parse_error.stderr
@@ -1,8 +1,8 @@
-error: struct with generic parameters is not supported yet
+error: unit structs are not supported
  --> $DIR/multiple_parse_error.rs:3:5
   |
 3 |     struct Monad<T>;
-  |     ^^^^^^^^^^^^^^^
+  |     ^^^^^^^^^^^^^^^^
 
 error: unrecognized ABI, requires either "C++" or "Rust"
  --> $DIR/multiple_parse_error.rs:5:5

From 10852ed5061b69eb8c520076d1c971cfc24ddd1e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:07:18 +0000
Subject: [PATCH 2016/2232] Fix slice restriction to exclude slice of CxxString


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 44be4dc..fbe6fbc 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -236,7 +236,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = match &ty.inner {
         Type::Str(_) | Type::SliceRef(_) => false,
-        Type::Ident(ident) => !is_opaque_cxx(cx, &ident.rust),
+        Type::Ident(ident) => !is_unsized(cx, &ty.inner) || cx.types.rust.contains(&ident.rust),
         element => !is_unsized(cx, element),
     };
 

From bf9d6e815b419764fbc608337f8708018b4d6493 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:11:01 +0000
Subject: [PATCH 2017/2232] Enable slices and arrays containing str/slice


---

diff --git a/syntax/check.rs b/syntax/check.rs
index fbe6fbc..b315ae7 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -234,11 +234,11 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
-    let supported = match &ty.inner {
-        Type::Str(_) | Type::SliceRef(_) => false,
-        Type::Ident(ident) => !is_unsized(cx, &ty.inner) || cx.types.rust.contains(&ident.rust),
-        element => !is_unsized(cx, element),
-    };
+    let supported = !is_unsized(cx, &ty.inner)
+        || match &ty.inner {
+            Type::Ident(ident) => cx.types.rust.contains(&ident.rust),
+            _ => false,
+        };
 
     if !supported {
         let mutable = if ty.mutable { "mut " } else { "" };
@@ -253,10 +253,7 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
-    let supported = match &ty.inner {
-        Type::Str(_) | Type::SliceRef(_) => false,
-        element => !is_unsized(cx, element),
-    };
+    let supported = !is_unsized(cx, &ty.inner);
 
     if !supported {
         cx.error(ty, "unsupported array element type");

From 2e040531f3df1511c4415b422762da9e2ac556d0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:24:26 +0000
Subject: [PATCH 2018/2232] Merge pull request #651 from dtolnay/slices


Enable slices and arrays containing str/slice
---

diff --git a/syntax/check.rs b/syntax/check.rs
index fbe6fbc..b315ae7 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -234,11 +234,11 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
-    let supported = match &ty.inner {
-        Type::Str(_) | Type::SliceRef(_) => false,
-        Type::Ident(ident) => !is_unsized(cx, &ty.inner) || cx.types.rust.contains(&ident.rust),
-        element => !is_unsized(cx, element),
-    };
+    let supported = !is_unsized(cx, &ty.inner)
+        || match &ty.inner {
+            Type::Ident(ident) => cx.types.rust.contains(&ident.rust),
+            _ => false,
+        };
 
     if !supported {
         let mutable = if ty.mutable { "mut " } else { "" };
@@ -253,10 +253,7 @@ fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
 }
 
 fn check_type_array(cx: &mut Check, ty: &Array) {
-    let supported = match &ty.inner {
-        Type::Str(_) | Type::SliceRef(_) => false,
-        element => !is_unsized(cx, element),
-    };
+    let supported = !is_unsized(cx, &ty.inner);
 
     if !supported {
         cx.error(ty, "unsupported array element type");

From 3a48021f54a391357f8a60c8788f07d2f576a831 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:25:53 +0000
Subject: [PATCH 2019/2232] Include lifetimes in error reporting spans


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 757673d..7664427 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -153,6 +153,7 @@ impl ToTokens for ExternType {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
         self.name.rust.to_tokens(tokens);
+        self.generics.to_tokens(tokens);
     }
 }
 
@@ -161,6 +162,7 @@ impl ToTokens for TypeAlias {
         // Notional token range for error reporting purposes.
         self.type_token.to_tokens(tokens);
         self.name.rust.to_tokens(tokens);
+        self.generics.to_tokens(tokens);
     }
 }
 
@@ -169,6 +171,7 @@ impl ToTokens for Struct {
         // Notional token range for error reporting purposes.
         self.struct_token.to_tokens(tokens);
         self.name.rust.to_tokens(tokens);
+        self.generics.to_tokens(tokens);
     }
 }
 
@@ -177,6 +180,7 @@ impl ToTokens for Enum {
         // Notional token range for error reporting purposes.
         self.enum_token.to_tokens(tokens);
         self.name.rust.to_tokens(tokens);
+        self.generics.to_tokens(tokens);
     }
 }
 

From 30d46731ef3905ffa0df7240e4c9562a36e871e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:34:51 +0000
Subject: [PATCH 2020/2232] Suppress needless_lifetimes lint in test suite


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index be19697..9e7b351 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -3,6 +3,7 @@
     clippy::just_underscores_and_digits,
     clippy::let_underscore_drop,
     clippy::must_use_candidate,
+    clippy::needless_lifetimes,
     clippy::needless_pass_by_value,
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref,

From 06c60a32a720135277ca64c7447c07aac88f26e5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:35:18 +0000
Subject: [PATCH 2021/2232] Remove opaque C++ type lifetimes gates


---

diff --git a/syntax/check.rs b/syntax/check.rs
index b315ae7..9a8881f 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -71,11 +71,6 @@ fn check_type_ident(cx: &mut Check, name: &NamedType) {
     {
         let msg = format!("unsupported type: {}", ident);
         cx.error(ident, &msg);
-        return;
-    }
-
-    if !name.generics.lifetimes.is_empty() {
-        cx.error(name, "type with lifetime parameter is not supported yet");
     }
 }
 
@@ -341,7 +336,10 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     }
 
     if let Some(lifetime) = ety.generics.lifetimes.first() {
-        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+        if ety.lang == Lang::Rust {
+            let msg = "extern Rust type with lifetimes is not supported yet";
+            cx.error(lifetime, msg);
+        }
     }
 
     if !ety.bounds.is_empty() {
@@ -447,10 +445,6 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         let msg = format!("derive({}) on extern type alias is not supported", derive);
         cx.error(derive, msg);
     }
-
-    if let Some(lifetime) = alias.generics.lifetimes.first() {
-        cx.error(lifetime, "extern type with lifetimes is not supported yet");
-    }
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
diff --git a/tests/ui/extern_type_lifetime.rs b/tests/ui/extern_type_lifetime.rs
deleted file mode 100644
index 4e0e2f7..0000000
--- a/tests/ui/extern_type_lifetime.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    extern "C++" {
-        type Complex<'a, 'b>;
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/extern_type_lifetime.stderr b/tests/ui/extern_type_lifetime.stderr
deleted file mode 100644
index 85a5d39..0000000
--- a/tests/ui/extern_type_lifetime.stderr
+++ /dev/null
@@ -1,5 +0,0 @@
-error: extern type with lifetimes is not supported yet
- --> $DIR/extern_type_lifetime.rs:4:22
-  |
-4 |         type Complex<'a, 'b>;
-  |                      ^^

From e099157c8cc9ba4213e0d3b1a2ac39a0c8ccba26 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:35:18 +0000
Subject: [PATCH 2022/2232] Add test with opaque C++ type containing lifetime


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9e7b351..ba28f50 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -210,6 +210,15 @@ pub mod ffi {
         type Job = crate::module::ffi::Job;
     }
 
+    unsafe extern "C++" {
+        type Borrow<'a>;
+
+        fn c_return_borrow<'a>(s: &'a CxxString) -> UniquePtr<Borrow<'a>>;
+
+        #[rust_name = "c_return_borrow_elided"]
+        fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
+    }
+
     #[repr(u32)]
     #[derive(Hash)]
     enum COwnedEnum {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9c3c62a..57c48f5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,6 +207,12 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+Borrow::Borrow(const std::string &s) : s(s) {}
+
+std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
+  return std::unique_ptr<Borrow>(new Borrow(s));
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 8235f5f..4492286 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -77,6 +77,11 @@ enum COwnedEnum {
   CVAL2,
 };
 
+struct Borrow {
+  Borrow(const std::string &s);
+  const std::string &s;
+};
+
 size_t c_return_primitive();
 Shared c_return_shared();
 ::A::AShared c_return_ns_shared();
@@ -110,6 +115,7 @@ size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
+std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);

From 42883ac16b25191cf7d6065016694ff3b3a12b64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:40:46 +0000
Subject: [PATCH 2023/2232] Merge pull request #652 from dtolnay/lifetimes


Enable lifetimes on opaque C++ types
---

diff --git a/syntax/check.rs b/syntax/check.rs
index b315ae7..9a8881f 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -71,11 +71,6 @@ fn check_type_ident(cx: &mut Check, name: &NamedType) {
     {
         let msg = format!("unsupported type: {}", ident);
         cx.error(ident, &msg);
-        return;
-    }
-
-    if !name.generics.lifetimes.is_empty() {
-        cx.error(name, "type with lifetime parameter is not supported yet");
     }
 }
 
@@ -341,7 +336,10 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
     }
 
     if let Some(lifetime) = ety.generics.lifetimes.first() {
-        cx.error(lifetime, "extern type with lifetimes is not supported yet");
+        if ety.lang == Lang::Rust {
+            let msg = "extern Rust type with lifetimes is not supported yet";
+            cx.error(lifetime, msg);
+        }
     }
 
     if !ety.bounds.is_empty() {
@@ -447,10 +445,6 @@ fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
         let msg = format!("derive({}) on extern type alias is not supported", derive);
         cx.error(derive, msg);
     }
-
-    if let Some(lifetime) = alias.generics.lifetimes.first() {
-        cx.error(lifetime, "extern type with lifetimes is not supported yet");
-    }
 }
 
 fn check_api_impl(cx: &mut Check, imp: &Impl) {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 9e7b351..ba28f50 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -210,6 +210,15 @@ pub mod ffi {
         type Job = crate::module::ffi::Job;
     }
 
+    unsafe extern "C++" {
+        type Borrow<'a>;
+
+        fn c_return_borrow<'a>(s: &'a CxxString) -> UniquePtr<Borrow<'a>>;
+
+        #[rust_name = "c_return_borrow_elided"]
+        fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
+    }
+
     #[repr(u32)]
     #[derive(Hash)]
     enum COwnedEnum {
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 9c3c62a..57c48f5 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,6 +207,12 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+Borrow::Borrow(const std::string &s) : s(s) {}
+
+std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
+  return std::unique_ptr<Borrow>(new Borrow(s));
+}
+
 void c_take_primitive(size_t n) {
   if (n == 2020) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 8235f5f..4492286 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -77,6 +77,11 @@ enum COwnedEnum {
   CVAL2,
 };
 
+struct Borrow {
+  Borrow(const std::string &s);
+  const std::string &s;
+};
+
 size_t c_return_primitive();
 Shared c_return_shared();
 ::A::AShared c_return_ns_shared();
@@ -110,6 +115,7 @@ size_t c_return_sum(size_t n1, size_t n2);
 Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
+std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
diff --git a/tests/ui/extern_type_lifetime.rs b/tests/ui/extern_type_lifetime.rs
deleted file mode 100644
index 4e0e2f7..0000000
--- a/tests/ui/extern_type_lifetime.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    extern "C++" {
-        type Complex<'a, 'b>;
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/extern_type_lifetime.stderr b/tests/ui/extern_type_lifetime.stderr
deleted file mode 100644
index 85a5d39..0000000
--- a/tests/ui/extern_type_lifetime.stderr
+++ /dev/null
@@ -1,5 +0,0 @@
-error: extern type with lifetimes is not supported yet
- --> $DIR/extern_type_lifetime.rs:4:22
-  |
-4 |         type Complex<'a, 'b>;
-  |                      ^^

From 78c8ae037af61f18afd7374f75e3ce1648de2118 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:46:54 +0000
Subject: [PATCH 2024/2232] Emit lifetimes into extern Rust type's trait impls


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 11115b8..476012f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -677,11 +677,12 @@ fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
+    let generics = &ety.generics;
     let span = ident.span();
     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
 
     let mut impls = quote_spanned! {span=>
-        #unsafe_impl ::cxx::private::RustType for #ident {}
+        #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
     };
 
     for derive in &ety.derives {
@@ -689,7 +690,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
             let type_id = type_id(&ety.name);
             let span = derive.span;
             impls.extend(quote_spanned! {span=>
-                unsafe impl ::cxx::ExternType for #ident {
+                unsafe impl #generics ::cxx::ExternType for #ident #generics {
                     type Id = #type_id;
                     type Kind = ::cxx::kind::Opaque;
                 }

From 58183e2228a15e50f8c6006c51fb090cead4f6d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:47:16 +0000
Subject: [PATCH 2025/2232] Enable support for extern Rust types containing lifetimes


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 9a8881f..b9f6660 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -335,13 +335,6 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = ety.generics.lifetimes.first() {
-        if ety.lang == Lang::Rust {
-            let msg = "extern Rust type with lifetimes is not supported yet";
-            cx.error(lifetime, msg);
-        }
-    }
-
     if !ety.bounds.is_empty() {
         let bounds = &ety.bounds;
         let span = quote!(#(#bounds)*);

From 5b9bbdf861ffd3a4cacfdf090adda57ca31a9d9e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:48:53 +0000
Subject: [PATCH 2026/2232] Add test of extern Rust type with lifetime


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ba28f50..5ac461c 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -210,6 +210,11 @@ pub mod ffi {
         type Job = crate::module::ffi::Job;
     }
 
+    extern "Rust" {
+        #[derive(ExternType)]
+        type Reference<'a>;
+    }
+
     unsafe extern "C++" {
         type Borrow<'a>;
 
@@ -377,6 +382,8 @@ impl R {
     }
 }
 
+pub struct Reference<'a>(&'a String);
+
 impl ffi::Shared {
     fn r_method_on_shared(&self) -> String {
         "2020".to_owned()

From 967ec5e6b1d49aef586a2ea68f669ccbfecd10df Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 07:56:00 +0000
Subject: [PATCH 2027/2232] Merge pull request #653 from dtolnay/lifetimes


Enable lifetimes on opaque Rust types
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 11115b8..476012f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -677,11 +677,12 @@ fn expand_rust_type_import(ety: &ExternType) -> TokenStream {
 
 fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
     let ident = &ety.name.rust;
+    let generics = &ety.generics;
     let span = ident.span();
     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
 
     let mut impls = quote_spanned! {span=>
-        #unsafe_impl ::cxx::private::RustType for #ident {}
+        #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
     };
 
     for derive in &ety.derives {
@@ -689,7 +690,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
             let type_id = type_id(&ety.name);
             let span = derive.span;
             impls.extend(quote_spanned! {span=>
-                unsafe impl ::cxx::ExternType for #ident {
+                unsafe impl #generics ::cxx::ExternType for #ident #generics {
                     type Id = #type_id;
                     type Kind = ::cxx::kind::Opaque;
                 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 9a8881f..b9f6660 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -335,13 +335,6 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
         cx.error(derive, msg);
     }
 
-    if let Some(lifetime) = ety.generics.lifetimes.first() {
-        if ety.lang == Lang::Rust {
-            let msg = "extern Rust type with lifetimes is not supported yet";
-            cx.error(lifetime, msg);
-        }
-    }
-
     if !ety.bounds.is_empty() {
         let bounds = &ety.bounds;
         let span = quote!(#(#bounds)*);
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index ba28f50..5ac461c 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -210,6 +210,11 @@ pub mod ffi {
         type Job = crate::module::ffi::Job;
     }
 
+    extern "Rust" {
+        #[derive(ExternType)]
+        type Reference<'a>;
+    }
+
     unsafe extern "C++" {
         type Borrow<'a>;
 
@@ -377,6 +382,8 @@ impl R {
     }
 }
 
+pub struct Reference<'a>(&'a String);
+
 impl ffi::Shared {
     fn r_method_on_shared(&self) -> String {
         "2020".to_owned()

From b9bf5e7aec27404f3a6684fd8a7297c283170f9d Mon Sep 17 00:00:00 2001
From: David Cattermole <cattermole91@gmail.com>
Date: Jan 03 2021 08:00:06 +0000
Subject: [PATCH 2028/2232] Force annotation on all functions in both source and header files


Annotations for symbol visibility (such as `__declspec(dllexport)` and
`__attribute__((visibility("default")))`) is the primary use case.
Such annotations are expected to be needed on declarations (headers)
only, however forcing the annotations into the header file only
is causes missing symbols. Therefore the fix is to force the
annotations into both declaration (header files) and definition
(source files).

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2404f9c..a2ce630 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -910,6 +910,7 @@ fn write_rust_function_shim_decl(
     sig: &Signature,
     indirect_call: bool,
 ) {
+    begin_function_definition(out);
     write_return_type(out, &sig.ret);
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
@@ -947,9 +948,6 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    if !out.header {
-        begin_function_definition(out);
-    }
     write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");

From 4d04cf59d795b6650696aba26713c68db3b2eb64 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 08:05:58 +0000
Subject: [PATCH 2029/2232] Merge pull request #654 from dtolnay/symbol-visibility-revisit


Force annotation on all functions in both source and header files
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 2404f9c..a2ce630 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -910,6 +910,7 @@ fn write_rust_function_shim_decl(
     sig: &Signature,
     indirect_call: bool,
 ) {
+    begin_function_definition(out);
     write_return_type(out, &sig.ret);
     write!(out, "{}(", local_name);
     for (i, arg) in sig.args.iter().enumerate() {
@@ -947,9 +948,6 @@ fn write_rust_function_shim_impl(
         // We've already defined this inside the struct.
         return;
     }
-    if !out.header {
-        begin_function_definition(out);
-    }
     write_rust_function_shim_decl(out, local_name, sig, indirect_call);
     if out.header {
         writeln!(out, ";");

From a0df0974aacb7e785492809f680951ce8d09b70e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 03 2021 20:04:39 +0000
Subject: [PATCH 2030/2232] Release 1.0.26


---

diff --git a/Cargo.toml b/Cargo.toml
index a6937b4..1010661 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.25" # remember to update html_root_url
+version = "1.0.26" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.25", path = "macro" }
+cxxbridge-macro = { version = "=1.0.26", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.25", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.26", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.25", path = "gen/build" }
+cxx-build = { version = "=1.0.26", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 31ffd70..d70279f 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.25"
+version = "1.0.26"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 811b261..73280ad 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.25"
+version = "1.0.26"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index a8129df..e557c38 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.25"
+version = "1.0.26"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 2780187..29cf45d 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.25"
+version = "0.7.26"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 5aa2292..a5a6d50 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.25"
+version = "1.0.26"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index bed0bc0..a3668dd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.25")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.26")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 148af20..7c90ab4 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.25"
+version = "1.0.26"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.25"
+version = "1.0.26"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.25"
+version = "0.7.26"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.25"
+version = "1.0.26"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.25"
+version = "1.0.26"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.25"
+version = "1.0.26"
 dependencies = [
  "cxx",
  "proc-macro2",

From fb5e1bad327eae247f124d37849f3e4b464cd132 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:05:43 +0000
Subject: [PATCH 2031/2232] Add documentation about lifetimes to book


---

diff --git a/book/src/extern-c++.md b/book/src/extern-c++.md
index c015b03..11ed7b5 100644
--- a/book/src/extern-c++.md
+++ b/book/src/extern-c++.md
@@ -112,6 +112,43 @@ mod ffi {
 }
 ```
 
+## Lifetimes
+
+C++ types holding borrowed data may be described naturally in Rust by an extern
+type with a generic lifetime parameter. For example in the case of the following
+pair of types:
+
+```cpp
+// header.h
+
+class Resource;
+
+class TypeContainingBorrow {
+  TypeContainingBorrow(const Resource &res) : res(res) {}
+  const Resource &res;
+};
+
+std::shared_ptr<TypeContainingBorrow> create(const Resource &res);
+```
+
+we'd want to expose this to Rust as:
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        # include!("path/to/header.h");
+        #
+        type Resource;
+        type TypeContainingBorrow<'a>;
+
+        fn create<'a>(res: &'a Resource) -> SharedPtr<TypeContainingBorrow<'a>>;
+
+        // or with lifetime elision:
+        fn create(res: &Resource) -> SharedPtr<TypeContainingBorrow>;
+    }
+}
+```
 
 ## Reusing existing binding types
 
diff --git a/book/src/extern-rust.md b/book/src/extern-rust.md
index a9ad8b6..ab9dcb6 100644
--- a/book/src/extern-rust.md
+++ b/book/src/extern-rust.md
@@ -31,7 +31,7 @@ indirection.
     extern "Rust" {
         type MyType;
         type MyOtherType;
-        type OneMoreType;
+        type OneMoreType<'a>;
     }
 # }
 ```
diff --git a/book/src/shared.md b/book/src/shared.md
index b919cde..4043db1 100644
--- a/book/src/shared.md
+++ b/book/src/shared.md
@@ -100,6 +100,27 @@ fn main() {
 }
 ```
 
+If a shared struct has generic lifetime parameters, the lifetimes are simply not
+represented on the C++ side. C++ code will need care when working with borrowed
+data (as usual in C++).
+
+```rust,noplayground
+#[cxx::bridge]
+mod ffi {
+    struct Borrowed<'a> {
+        flags: &'a [&'a str],
+    }
+}
+```
+
+```cpp
+// generated header
+
+struct Borrowed final {
+  rust::Slice<const rust::Str> flags;
+};
+```
+
 ## Enum discriminants
 
 You may provide explicit discriminants for some or all of the enum variants, in

From a22b7decff3e550e5dd683482fe1f27de9742af5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:08:37 +0000
Subject: [PATCH 2032/2232] Add ui test of extern function with body


---

diff --git a/tests/ui/function_with_body.rs b/tests/ui/function_with_body.rs
new file mode 100644
index 0000000..52be79a
--- /dev/null
+++ b/tests/ui/function_with_body.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn f() {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/function_with_body.stderr b/tests/ui/function_with_body.stderr
new file mode 100644
index 0000000..ea54f5b
--- /dev/null
+++ b/tests/ui/function_with_body.stderr
@@ -0,0 +1,5 @@
+error: unsupported foreign item
+ --> $DIR/function_with_body.rs:4:9
+  |
+4 |         fn f() {}
+  |         ^^^^^^^^^

From aea7a5869e3764194eac01bc0dcc9d9f797b228c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:14:08 +0000
Subject: [PATCH 2033/2232] Extract extern verbatim type parsing to function


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3a7e00f..d053bb3 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -662,69 +662,79 @@ fn parse_extern_verbatim(
     |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
         let visibility: Visibility = input.parse()?;
-        let type_token: Token![type] = match input.parse()? {
-            Some(type_token) => type_token,
-            None => {
-                let span = input.cursor().token_stream();
-                return Err(Error::new_spanned(span, "unsupported foreign item"));
-            }
-        };
-        let ident: Ident = input.parse()?;
-        let generics: Generics = input.parse()?;
-        let mut lifetimes = Punctuated::new();
-        let mut has_unsupported_generic_param = false;
-        for pair in generics.params.into_pairs() {
-            let (param, punct) = pair.into_tuple();
-            match param {
-                GenericParam::Lifetime(param) => {
-                    if !param.bounds.is_empty() && !has_unsupported_generic_param {
-                        let msg = "lifetime parameter with bounds is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
-                    lifetimes.push_value(param.lifetime);
-                    if let Some(punct) = punct {
-                        lifetimes.push_punct(punct);
-                    }
+        if input.peek(Token![type]) {
+            parse_extern_verbatim_type(cx, attrs, visibility, input, lang, trusted, namespace)
+        } else {
+            let span = input.cursor().token_stream();
+            Err(Error::new_spanned(span, "unsupported foreign item"))
+        }
+    }
+    .parse2(tokens)
+}
+
+fn parse_extern_verbatim_type(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    visibility: Visibility,
+    input: ParseStream,
+    lang: Lang,
+    trusted: bool,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let type_token: Token![type] = input.parse()?;
+    let ident: Ident = input.parse()?;
+    let generics: Generics = input.parse()?;
+    let mut lifetimes = Punctuated::new();
+    let mut has_unsupported_generic_param = false;
+    for pair in generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(param) => {
+                if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                    let msg = "lifetime parameter with bounds is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
                 }
-                GenericParam::Type(param) => {
-                    if !has_unsupported_generic_param {
-                        let msg = "extern type with generic type parameter is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
+                lifetimes.push_value(param.lifetime);
+                if let Some(punct) = punct {
+                    lifetimes.push_punct(punct);
                 }
-                GenericParam::Const(param) => {
-                    if !has_unsupported_generic_param {
-                        let msg = "extern type with const generic parameter is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
+            }
+            GenericParam::Type(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "extern type with generic type parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+            GenericParam::Const(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "extern type with const generic parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
                 }
             }
-        }
-        let lifetimes = Lifetimes {
-            lt_token: generics.lt_token,
-            lifetimes,
-            gt_token: generics.gt_token,
-        };
-        let lookahead = input.lookahead1();
-        if lookahead.peek(Token![=]) {
-            // type Alias = crate::path::to::Type;
-            parse_type_alias(
-                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
-            )
-        } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
-            // type Opaque: Bound2 + Bound2;
-            parse_extern_type_bounded(
-                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted,
-                namespace,
-            )
-        } else {
-            Err(lookahead.error())
         }
     }
-    .parse2(tokens)
+    let lifetimes = Lifetimes {
+        lt_token: generics.lt_token,
+        lifetimes,
+        gt_token: generics.gt_token,
+    };
+    let lookahead = input.lookahead1();
+    if lookahead.peek(Token![=]) {
+        // type Alias = crate::path::to::Type;
+        parse_type_alias(
+            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
+        )
+    } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
+        // type Opaque: Bound2 + Bound2;
+        parse_extern_type_bounded(
+            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted, namespace,
+        )
+    } else {
+        Err(lookahead.error())
+    }
 }
 
 fn parse_type_alias(

From 8c28af564fb6a17f288a8b4ed174512c134cd107 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:23:52 +0000
Subject: [PATCH 2034/2232] Improve extern fn with body error message


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d053bb3..fbb24e2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -16,9 +16,9 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
-    Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
-    Variant as RustVariant, Visibility,
+    Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
+    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath,
+    TypeReference, Variant as RustVariant, Visibility,
 };
 
 pub mod kw {
@@ -664,9 +664,14 @@ fn parse_extern_verbatim(
         let visibility: Visibility = input.parse()?;
         if input.peek(Token![type]) {
             parse_extern_verbatim_type(cx, attrs, visibility, input, lang, trusted, namespace)
+        } else if input.peek(Token![fn]) {
+            parse_extern_verbatim_fn(input)
         } else {
             let span = input.cursor().token_stream();
-            Err(Error::new_spanned(span, "unsupported foreign item"))
+            Err(Error::new_spanned(
+                span,
+                "unsupported foreign item, expected `type` or `fn`",
+            ))
         }
     }
     .parse2(tokens)
@@ -737,6 +742,12 @@ fn parse_extern_verbatim_type(
     }
 }
 
+fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
+    input.parse::<RustSignature>()?;
+    input.parse::<Token![;]>()?;
+    unreachable!()
+}
+
 fn parse_type_alias(
     cx: &mut Errors,
     attrs: Vec<Attribute>,
diff --git a/tests/ui/function_with_body.stderr b/tests/ui/function_with_body.stderr
index ea54f5b..c5641db 100644
--- a/tests/ui/function_with_body.stderr
+++ b/tests/ui/function_with_body.stderr
@@ -1,5 +1,5 @@
-error: unsupported foreign item
- --> $DIR/function_with_body.rs:4:9
+error: expected `;`
+ --> $DIR/function_with_body.rs:4:16
   |
 4 |         fn f() {}
-  |         ^^^^^^^^^
+  |                ^

From 7c969ce953986c878a18f1fc65cb53e5c1119b30 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:35:11 +0000
Subject: [PATCH 2035/2232] Merge pull request #659 from dtolnay/externbody


Improve extern fn with body error message
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3a7e00f..fbb24e2 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -16,9 +16,9 @@ use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
-    Pat, PathArguments, Result, ReturnType, Token, TraitBound, TraitBoundModifier,
-    Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypeReference,
-    Variant as RustVariant, Visibility,
+    Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
+    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath,
+    TypeReference, Variant as RustVariant, Visibility,
 };
 
 pub mod kw {
@@ -662,69 +662,90 @@ fn parse_extern_verbatim(
     |input: ParseStream| -> Result<Api> {
         let attrs = input.call(Attribute::parse_outer)?;
         let visibility: Visibility = input.parse()?;
-        let type_token: Token![type] = match input.parse()? {
-            Some(type_token) => type_token,
-            None => {
-                let span = input.cursor().token_stream();
-                return Err(Error::new_spanned(span, "unsupported foreign item"));
-            }
-        };
-        let ident: Ident = input.parse()?;
-        let generics: Generics = input.parse()?;
-        let mut lifetimes = Punctuated::new();
-        let mut has_unsupported_generic_param = false;
-        for pair in generics.params.into_pairs() {
-            let (param, punct) = pair.into_tuple();
-            match param {
-                GenericParam::Lifetime(param) => {
-                    if !param.bounds.is_empty() && !has_unsupported_generic_param {
-                        let msg = "lifetime parameter with bounds is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
-                    lifetimes.push_value(param.lifetime);
-                    if let Some(punct) = punct {
-                        lifetimes.push_punct(punct);
-                    }
+        if input.peek(Token![type]) {
+            parse_extern_verbatim_type(cx, attrs, visibility, input, lang, trusted, namespace)
+        } else if input.peek(Token![fn]) {
+            parse_extern_verbatim_fn(input)
+        } else {
+            let span = input.cursor().token_stream();
+            Err(Error::new_spanned(
+                span,
+                "unsupported foreign item, expected `type` or `fn`",
+            ))
+        }
+    }
+    .parse2(tokens)
+}
+
+fn parse_extern_verbatim_type(
+    cx: &mut Errors,
+    attrs: Vec<Attribute>,
+    visibility: Visibility,
+    input: ParseStream,
+    lang: Lang,
+    trusted: bool,
+    namespace: &Namespace,
+) -> Result<Api> {
+    let type_token: Token![type] = input.parse()?;
+    let ident: Ident = input.parse()?;
+    let generics: Generics = input.parse()?;
+    let mut lifetimes = Punctuated::new();
+    let mut has_unsupported_generic_param = false;
+    for pair in generics.params.into_pairs() {
+        let (param, punct) = pair.into_tuple();
+        match param {
+            GenericParam::Lifetime(param) => {
+                if !param.bounds.is_empty() && !has_unsupported_generic_param {
+                    let msg = "lifetime parameter with bounds is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
                 }
-                GenericParam::Type(param) => {
-                    if !has_unsupported_generic_param {
-                        let msg = "extern type with generic type parameter is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
+                lifetimes.push_value(param.lifetime);
+                if let Some(punct) = punct {
+                    lifetimes.push_punct(punct);
                 }
-                GenericParam::Const(param) => {
-                    if !has_unsupported_generic_param {
-                        let msg = "extern type with const generic parameter is not supported yet";
-                        cx.error(&param, msg);
-                        has_unsupported_generic_param = true;
-                    }
+            }
+            GenericParam::Type(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "extern type with generic type parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
+                }
+            }
+            GenericParam::Const(param) => {
+                if !has_unsupported_generic_param {
+                    let msg = "extern type with const generic parameter is not supported yet";
+                    cx.error(&param, msg);
+                    has_unsupported_generic_param = true;
                 }
             }
-        }
-        let lifetimes = Lifetimes {
-            lt_token: generics.lt_token,
-            lifetimes,
-            gt_token: generics.gt_token,
-        };
-        let lookahead = input.lookahead1();
-        if lookahead.peek(Token![=]) {
-            // type Alias = crate::path::to::Type;
-            parse_type_alias(
-                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
-            )
-        } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
-            // type Opaque: Bound2 + Bound2;
-            parse_extern_type_bounded(
-                cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted,
-                namespace,
-            )
-        } else {
-            Err(lookahead.error())
         }
     }
-    .parse2(tokens)
+    let lifetimes = Lifetimes {
+        lt_token: generics.lt_token,
+        lifetimes,
+        gt_token: generics.gt_token,
+    };
+    let lookahead = input.lookahead1();
+    if lookahead.peek(Token![=]) {
+        // type Alias = crate::path::to::Type;
+        parse_type_alias(
+            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
+        )
+    } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
+        // type Opaque: Bound2 + Bound2;
+        parse_extern_type_bounded(
+            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted, namespace,
+        )
+    } else {
+        Err(lookahead.error())
+    }
+}
+
+fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
+    input.parse::<RustSignature>()?;
+    input.parse::<Token![;]>()?;
+    unreachable!()
 }
 
 fn parse_type_alias(
diff --git a/tests/ui/function_with_body.rs b/tests/ui/function_with_body.rs
new file mode 100644
index 0000000..52be79a
--- /dev/null
+++ b/tests/ui/function_with_body.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn f() {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/function_with_body.stderr b/tests/ui/function_with_body.stderr
new file mode 100644
index 0000000..c5641db
--- /dev/null
+++ b/tests/ui/function_with_body.stderr
@@ -0,0 +1,5 @@
+error: expected `;`
+ --> $DIR/function_with_body.rs:4:16
+  |
+4 |         fn f() {}
+  |                ^

From 54bce274b64acb34955467ccdf1732edf37222d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:51:13 +0000
Subject: [PATCH 2036/2232] Implement lifetime elision for member function receivers


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 476012f..1b09cf0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -6,13 +6,13 @@ use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, Signature, Struct,
-    Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
-use syn::{parse_quote, Result, Token};
+use syn::{parse_quote, punctuated, Lifetime, Result, Token};
 
 pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
@@ -617,16 +617,44 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         #trampolines
         #dispatch
     });
-    let function_shim = quote! {
-        #doc
-        #attrs
-        #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
-    };
     match &efn.receiver {
-        None => function_shim,
+        None => {
+            quote! {
+                #doc
+                #attrs
+                #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
+            }
+        }
         Some(receiver) => {
-            let receiver_type = &receiver.ty;
-            quote!(impl #receiver_type { #function_shim })
+            let elided_generics;
+            let receiver_ident = &receiver.ty.rust;
+            let resolve = types.resolve(&receiver.ty);
+            let receiver_generics = if receiver.ty.generics.lt_token.is_some() {
+                &receiver.ty.generics
+            } else {
+                elided_generics = Lifetimes {
+                    lt_token: resolve.generics.lt_token,
+                    lifetimes: resolve
+                        .generics
+                        .lifetimes
+                        .pairs()
+                        .map(|pair| {
+                            let lifetime = Lifetime::new("'_", pair.value().apostrophe);
+                            let punct = pair.punct().map(|&&comma| comma);
+                            punctuated::Pair::new(lifetime, punct)
+                        })
+                        .collect(),
+                    gt_token: resolve.generics.gt_token,
+                };
+                &elided_generics
+            };
+            quote! {
+                impl #generics #receiver_ident #receiver_generics {
+                    #doc
+                    #attrs
+                    #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
+                }
+            }
         }
     }
 }

From 774fd5293989b8cfd5f985dce00d215b14eb57a9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 04:58:04 +0000
Subject: [PATCH 2037/2232] Add test of lifetime elision on const member


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5ac461c..10e16a6 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -222,6 +222,8 @@ pub mod ffi {
 
         #[rust_name = "c_return_borrow_elided"]
         fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
+
+        fn const_member(self: &Borrow);
     }
 
     #[repr(u32)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 57c48f5..d80785d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -209,6 +209,8 @@ Enum c_return_enum(uint16_t n) {
 
 Borrow::Borrow(const std::string &s) : s(s) {}
 
+void Borrow::const_member() const {}
+
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
   return std::unique_ptr<Borrow>(new Borrow(s));
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 4492286..cd265d4 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -79,6 +79,7 @@ enum COwnedEnum {
 
 struct Borrow {
   Borrow(const std::string &s);
+  void const_member() const;
   const std::string &s;
 };
 

From a2bd047d68e64d42df1d278549d41c4a313809e9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 05:04:40 +0000
Subject: [PATCH 2038/2232] Merge pull request #660 from dtolnay/elision


Implement lifetime elision for member function receivers
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 476012f..1b09cf0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -6,13 +6,13 @@ use crate::syntax::instantiate::ImplKey;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Pair, Signature, Struct,
-    Trait, Type, TypeAlias, Types,
+    self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
+    Struct, Trait, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
-use syn::{parse_quote, Result, Token};
+use syn::{parse_quote, punctuated, Lifetime, Result, Token};
 
 pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
     let ref mut errors = Errors::new();
@@ -617,16 +617,44 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
         #trampolines
         #dispatch
     });
-    let function_shim = quote! {
-        #doc
-        #attrs
-        #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
-    };
     match &efn.receiver {
-        None => function_shim,
+        None => {
+            quote! {
+                #doc
+                #attrs
+                #visibility #unsafety #fn_token #ident #generics #arg_list #ret #fn_body
+            }
+        }
         Some(receiver) => {
-            let receiver_type = &receiver.ty;
-            quote!(impl #receiver_type { #function_shim })
+            let elided_generics;
+            let receiver_ident = &receiver.ty.rust;
+            let resolve = types.resolve(&receiver.ty);
+            let receiver_generics = if receiver.ty.generics.lt_token.is_some() {
+                &receiver.ty.generics
+            } else {
+                elided_generics = Lifetimes {
+                    lt_token: resolve.generics.lt_token,
+                    lifetimes: resolve
+                        .generics
+                        .lifetimes
+                        .pairs()
+                        .map(|pair| {
+                            let lifetime = Lifetime::new("'_", pair.value().apostrophe);
+                            let punct = pair.punct().map(|&&comma| comma);
+                            punctuated::Pair::new(lifetime, punct)
+                        })
+                        .collect(),
+                    gt_token: resolve.generics.gt_token,
+                };
+                &elided_generics
+            };
+            quote! {
+                impl #generics #receiver_ident #receiver_generics {
+                    #doc
+                    #attrs
+                    #visibility #unsafety #fn_token #ident #arg_list #ret #fn_body
+                }
+            }
         }
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5ac461c..10e16a6 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -222,6 +222,8 @@ pub mod ffi {
 
         #[rust_name = "c_return_borrow_elided"]
         fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
+
+        fn const_member(self: &Borrow);
     }
 
     #[repr(u32)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 57c48f5..d80785d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -209,6 +209,8 @@ Enum c_return_enum(uint16_t n) {
 
 Borrow::Borrow(const std::string &s) : s(s) {}
 
+void Borrow::const_member() const {}
+
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
   return std::unique_ptr<Borrow>(new Borrow(s));
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 4492286..cd265d4 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -79,6 +79,7 @@ enum COwnedEnum {
 
 struct Borrow {
   Borrow(const std::string &s);
+  void const_member() const;
   const std::string &s;
 };
 

From 5e8bb1ce796daff7fad75b5ebdaa42a1597ddaf0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 05:04:55 +0000
Subject: [PATCH 2039/2232] Add test of lifetime elision on nonconst member


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 10e16a6..32d739d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -224,6 +224,7 @@ pub mod ffi {
         fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
 
         fn const_member(self: &Borrow);
+        fn nonconst_member(self: Pin<&mut Borrow>);
     }
 
     #[repr(u32)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d80785d..8ed5456 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -211,6 +211,8 @@ Borrow::Borrow(const std::string &s) : s(s) {}
 
 void Borrow::const_member() const {}
 
+void Borrow::nonconst_member() {}
+
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
   return std::unique_ptr<Borrow>(new Borrow(s));
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index cd265d4..a28c166 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -80,6 +80,7 @@ enum COwnedEnum {
 struct Borrow {
   Borrow(const std::string &s);
   void const_member() const;
+  void nonconst_member();
   const std::string &s;
 };
 

From 9bd65aa60cfb71871f30d366c5241e64e0ae91c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 05:04:55 +0000
Subject: [PATCH 2040/2232] Implement lifetime elision inside of pins


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1b09cf0..d4ceb3d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -436,7 +436,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let var = receiver.var;
         if receiver.pinned {
-            let ty = receiver.ty();
+            let ty = receiver.ty_self();
             quote!(#var: #ty)
         } else {
             let ampersand = receiver.ampersand;
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7664427..bb04e16 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -270,12 +270,18 @@ impl ToTokens for NamedType {
 }
 
 pub struct ReceiverType<'a>(&'a Receiver);
+pub struct ReceiverTypeSelf<'a>(&'a Receiver);
 
 impl Receiver {
     // &TheType
     pub fn ty(&self) -> ReceiverType {
         ReceiverType(self)
     }
+
+    // &Self
+    pub fn ty_self(&self) -> ReceiverTypeSelf {
+        ReceiverTypeSelf(self)
+    }
 }
 
 impl ToTokens for ReceiverType<'_> {
@@ -304,3 +310,30 @@ impl ToTokens for ReceiverType<'_> {
         }
     }
 }
+
+impl ToTokens for ReceiverTypeSelf<'_> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Receiver {
+            pinned: _,
+            ampersand,
+            lifetime,
+            mutable: _,
+            var: _,
+            ty,
+            shorthand: _,
+            pin_tokens,
+            mutability,
+        } = &self.0;
+        if let Some((pin, langle, _rangle)) = pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
+        ampersand.to_tokens(tokens);
+        lifetime.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        Token![Self](ty.rust.span()).to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = pin_tokens {
+            rangle.to_tokens(tokens);
+        }
+    }
+}

From efb45061027ba4e9949dda68f7c301668e011135 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 05:15:28 +0000
Subject: [PATCH 2041/2232] Merge pull request #661 from dtolnay/elision


Implement lifetime elision inside of pins
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1b09cf0..d4ceb3d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -436,7 +436,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let receiver = efn.receiver.iter().map(|receiver| {
         let var = receiver.var;
         if receiver.pinned {
-            let ty = receiver.ty();
+            let ty = receiver.ty_self();
             quote!(#var: #ty)
         } else {
             let ampersand = receiver.ampersand;
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 7664427..bb04e16 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -270,12 +270,18 @@ impl ToTokens for NamedType {
 }
 
 pub struct ReceiverType<'a>(&'a Receiver);
+pub struct ReceiverTypeSelf<'a>(&'a Receiver);
 
 impl Receiver {
     // &TheType
     pub fn ty(&self) -> ReceiverType {
         ReceiverType(self)
     }
+
+    // &Self
+    pub fn ty_self(&self) -> ReceiverTypeSelf {
+        ReceiverTypeSelf(self)
+    }
 }
 
 impl ToTokens for ReceiverType<'_> {
@@ -304,3 +310,30 @@ impl ToTokens for ReceiverType<'_> {
         }
     }
 }
+
+impl ToTokens for ReceiverTypeSelf<'_> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Receiver {
+            pinned: _,
+            ampersand,
+            lifetime,
+            mutable: _,
+            var: _,
+            ty,
+            shorthand: _,
+            pin_tokens,
+            mutability,
+        } = &self.0;
+        if let Some((pin, langle, _rangle)) = pin_tokens {
+            tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin));
+            langle.to_tokens(tokens);
+        }
+        ampersand.to_tokens(tokens);
+        lifetime.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        Token![Self](ty.rust.span()).to_tokens(tokens);
+        if let Some((_pin, _langle, rangle)) = pin_tokens {
+            rangle.to_tokens(tokens);
+        }
+    }
+}
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 10e16a6..32d739d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -224,6 +224,7 @@ pub mod ffi {
         fn c_return_borrow(s: &CxxString) -> UniquePtr<Borrow>;
 
         fn const_member(self: &Borrow);
+        fn nonconst_member(self: Pin<&mut Borrow>);
     }
 
     #[repr(u32)]
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index d80785d..8ed5456 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -211,6 +211,8 @@ Borrow::Borrow(const std::string &s) : s(s) {}
 
 void Borrow::const_member() const {}
 
+void Borrow::nonconst_member() {}
+
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s) {
   return std::unique_ptr<Borrow>(new Borrow(s));
 }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index cd265d4..a28c166 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -80,6 +80,7 @@ enum COwnedEnum {
 struct Borrow {
   Borrow(const std::string &s);
   void const_member() const;
+  void nonconst_member();
   const std::string &s;
 };
 

From 2d1fcc2d2efe2d7988ba44e965e6540b5a1e4bff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 06:47:35 +0000
Subject: [PATCH 2042/2232] Implement Vec<&str>


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 9983fba..0dba805 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -602,7 +602,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
-  MACRO(string, rust::String)
+  MACRO(string, rust::String)                                                  \
+  MACRO(str, rust::Str)
 
 #define FOR_EACH_SHARED_PTR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 60b9cfa..bda1209 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -77,3 +77,4 @@ rust_vec_shims_for_primitive!(f64);
 
 rust_vec_shims!("char", c_char);
 rust_vec_shims!("string", RustString);
+rust_vec_shims!("str", &str);
diff --git a/syntax/check.rs b/syntax/check.rs
index b9f6660..2098a1b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -93,23 +93,27 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
-    if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(&ident.rust)
-            && !cx.types.aliases.contains_key(&ident.rust)
-            && !cx.types.structs.contains_key(&ident.rust)
-            && !cx.types.enums.contains_key(&ident.rust)
-        {
-            cx.error(ty, "Rust Vec containing C++ type is not supported yet");
-            return;
-        }
+    match &ty.inner {
+        Type::Ident(ident) => {
+            if cx.types.cxx.contains(&ident.rust)
+                && !cx.types.aliases.contains_key(&ident.rust)
+                && !cx.types.structs.contains_key(&ident.rust)
+                && !cx.types.enums.contains_key(&ident.rust)
+            {
+                cx.error(ty, "Rust Vec containing C++ type is not supported yet");
+                return;
+            }
 
-        match Atom::from(&ident.rust) {
-            None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
-            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
-            | Some(F64) | Some(RustString) => return,
-            Some(Bool) => { /* todo */ }
-            Some(CxxString) => {}
+            match Atom::from(&ident.rust) {
+                None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+                | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+                | Some(F64) | Some(RustString) => return,
+                Some(Bool) => { /* todo */ }
+                Some(CxxString) => {}
+            }
         }
+        Type::Str(_) => return,
+        _ => {}
     }
 
     cx.error(ty, "unsupported element type of Vec");

From 5b4b829f8aa301fe3a512324dfacdb752f4958ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 06:55:38 +0000
Subject: [PATCH 2043/2232] Merge pull request #662 from dtolnay/vecstr


Implement Vec<&str>
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 9983fba..0dba805 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -602,7 +602,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
-  MACRO(string, rust::String)
+  MACRO(string, rust::String)                                                  \
+  MACRO(str, rust::Str)
 
 #define FOR_EACH_SHARED_PTR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 60b9cfa..bda1209 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -77,3 +77,4 @@ rust_vec_shims_for_primitive!(f64);
 
 rust_vec_shims!("char", c_char);
 rust_vec_shims!("string", RustString);
+rust_vec_shims!("str", &str);
diff --git a/syntax/check.rs b/syntax/check.rs
index b9f6660..2098a1b 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -93,23 +93,27 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
 }
 
 fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
-    if let Type::Ident(ident) = &ty.inner {
-        if cx.types.cxx.contains(&ident.rust)
-            && !cx.types.aliases.contains_key(&ident.rust)
-            && !cx.types.structs.contains_key(&ident.rust)
-            && !cx.types.enums.contains_key(&ident.rust)
-        {
-            cx.error(ty, "Rust Vec containing C++ type is not supported yet");
-            return;
-        }
+    match &ty.inner {
+        Type::Ident(ident) => {
+            if cx.types.cxx.contains(&ident.rust)
+                && !cx.types.aliases.contains_key(&ident.rust)
+                && !cx.types.structs.contains_key(&ident.rust)
+                && !cx.types.enums.contains_key(&ident.rust)
+            {
+                cx.error(ty, "Rust Vec containing C++ type is not supported yet");
+                return;
+            }
 
-        match Atom::from(&ident.rust) {
-            None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
-            | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
-            | Some(F64) | Some(RustString) => return,
-            Some(Bool) => { /* todo */ }
-            Some(CxxString) => {}
+            match Atom::from(&ident.rust) {
+                None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
+                | Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
+                | Some(F64) | Some(RustString) => return,
+                Some(Bool) => { /* todo */ }
+                Some(CxxString) => {}
+            }
         }
+        Type::Str(_) => return,
+        _ => {}
     }
 
     cx.error(ty, "unsupported element type of Vec");

From 7bc0ca362f9111d2baef1ce237c9ae740923737b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 08:57:12 +0000
Subject: [PATCH 2044/2232] Preserve mod and brace token spans in macro output


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d4ceb3d..7e666b2 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -114,16 +114,17 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
     }
 
     let vis = &ffi.vis;
+    let mod_token = &ffi.mod_token;
     let ident = &ffi.ident;
+    let span = ffi.brace_token.span;
+    let expanded = quote_spanned!(span=> {#expanded});
 
     quote! {
         #doc
         #attrs
         #[deny(improper_ctypes)]
         #[allow(non_snake_case)]
-        #vis mod #ident {
-            #expanded
-        }
+        #vis #mod_token #ident #expanded
     }
 }
 

From a0b5fcb756d0c85f4c77bff36065c331a89bf840 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 20:18:24 +0000
Subject: [PATCH 2045/2232] Update documentation to reflect opaque Rust types in slices and arrays


---

diff --git a/README.md b/README.md
index f6a18eb..b3058f6 100644
--- a/README.md
+++ b/README.md
@@ -322,13 +322,13 @@ returns of functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td>String</td><td>rust::String</td><td></td></tr>
 <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
-<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index b6e0e30..4a765b3 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -11,13 +11,13 @@ returns of extern functions.
 <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 <tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">&amp;str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr>
-<tr><td style="padding:3px 6px">&amp;[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
-<tr><td style="padding:3px 6px">&amp;mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;const&nbsp;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">&amp;mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Box&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::unique_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/sharedptr.md">SharedPtr&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::shared_ptr&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
diff --git a/src/lib.rs b/src/lib.rs
index a3668dd..0a3e3fa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -331,13 +331,13 @@
 //! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr>
 //! <tr><td>String</td><td>rust::String</td><td></td></tr>
 //! <tr><td>&amp;str</td><td>rust::Str</td><td></td></tr>
-//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
-//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+//! <tr><td>&amp;[T]</td><td>rust::Slice&lt;const T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
+//! <tr><td>&amp;mut [T]</td><td>rust::Slice&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr>
 //! <tr><td>Box&lt;T&gt;</td><td>rust::Box&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.UniquePtr.html">UniquePtr&lt;T&gt;</a></td><td>std::unique_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td><a href="struct.SharedPtr.html">SharedPtr&lt;T&gt;</a></td><td>std::shared_ptr&lt;T&gt;</td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr>
-//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque Rust or C++ type</i></sup></td></tr>
+//! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>

From 851d2f71eb29413136a4e60ae6647dd3372b47fc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 20:20:50 +0000
Subject: [PATCH 2046/2232] Fill in some missing header dependencies related to array and uintptr_t


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 5248a20..3b411aa 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -55,6 +55,7 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_str {
+        include.array = true;
         include.cstdint = true;
         include.string = true;
         builtin.friend_impl = true;
@@ -64,6 +65,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.algorithm = true;
         include.array = true;
         include.cstddef = true;
+        include.cstdint = true;
         include.initializer_list = true;
         include.iterator = true;
         include.new = true;
@@ -75,7 +77,9 @@ pub(super) fn write(out: &mut OutFile) {
     }
 
     if builtin.rust_slice {
+        include.array = true;
         include.cstddef = true;
+        include.cstdint = true;
         include.iterator = true;
         include.type_traits = true;
         builtin.friend_impl = true;

From 26cd914e0c7c2dbea510c813ff9fb63bc47544d2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 04 2021 20:22:15 +0000
Subject: [PATCH 2047/2232] Release 1.0.27


---

diff --git a/Cargo.toml b/Cargo.toml
index 1010661..7cb33fe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.26" # remember to update html_root_url
+version = "1.0.27" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.26", path = "macro" }
+cxxbridge-macro = { version = "=1.0.27", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.26", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.27", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.26", path = "gen/build" }
+cxx-build = { version = "=1.0.27", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index d70279f..b4532cc 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.26"
+version = "1.0.27"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 73280ad..b4e2548 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.26"
+version = "1.0.27"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e557c38..005a088 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.26"
+version = "1.0.27"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 29cf45d..cf9d658 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.26"
+version = "0.7.27"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index a5a6d50..0951135 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.26"
+version = "1.0.27"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 0a3e3fa..030fabb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.26")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.27")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 7c90ab4..a7a2f59 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.26"
+version = "1.0.27"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.26"
+version = "1.0.27"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.26"
+version = "0.7.27"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.26"
+version = "1.0.27"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.26"
+version = "1.0.27"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.26"
+version = "1.0.27"
 dependencies = [
  "cxx",
  "proc-macro2",

From abd52bc75bda2a3d8a2d3703fb894bc0b749a385 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 05 2021 08:13:31 +0000
Subject: [PATCH 2048/2232] Emit mdBook version into build log


Allows confirming that we've picked up the fix for https://blog.rust-lang.org/2021/01/04/mdbook-security-advisory.html

---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index b106db9..f4f186c 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -20,6 +20,7 @@ jobs:
           export MDBOOK_TARBALL="mdbook-${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz"
           export MDBOOK_URL="https://github.com/dtolnay/mdBook/releases/download/cxx/${MDBOOK_TARBALL}"
           curl -Lf "${MDBOOK_URL}" | tar -xzC book
+          book/mdbook --version
 
       - name: Build
         run: book/build.sh

From aa619660c72c4e39e2ccc9d578a364984f155d71 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 05 2021 08:15:43 +0000
Subject: [PATCH 2049/2232] Trigger site rebuild on workflow changes


---

diff --git a/.github/workflows/site.yml b/.github/workflows/site.yml
index f4f186c..d6b0ca6 100644
--- a/.github/workflows/site.yml
+++ b/.github/workflows/site.yml
@@ -6,6 +6,7 @@ on:
       - master
     paths:
       - book/**
+      - .github/workflows/site.yml
 
 jobs:
   deploy:

From 8e2faa4991c75704b33e998cd332eb45346d5336 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 06 2021 05:46:58 +0000
Subject: [PATCH 2050/2232] Omit receiver type lifetimes from Rust method shim


For a receiver like `self: &mut RustType<'a>`, before:

    RustType<'a>::methodname  // invalid

after:

    RustType::methodname  // 👍

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 7e666b2..578d624 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1008,7 +1008,7 @@ fn expand_rust_function_shim_super(
     let call = match &sig.receiver {
         None => quote_spanned!(span=> super::#invoke),
         Some(receiver) => {
-            let receiver_type = &receiver.ty;
+            let receiver_type = &receiver.ty.rust;
             quote_spanned!(span=> #receiver_type::#invoke)
         }
     };

From ecb4dbff0e62cf00d75382cf2b04eec21caeec27 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 14 2021 19:22:34 +0000
Subject: [PATCH 2051/2232] Include <cassert> where needed in generated code


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 3b411aa..378467b 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_vec {
         include.algorithm = true;
         include.array = true;
+        include.cassert = true;
         include.cstddef = true;
         include.cstdint = true;
         include.initializer_list = true;
@@ -78,6 +79,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     if builtin.rust_slice {
         include.array = true;
+        include.cassert = true;
         include.cstddef = true;
         include.cstdint = true;
         include.iterator = true;
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 6b7e580..93ce60b 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -23,6 +23,7 @@ pub struct Includes<'a> {
     pub custom: Vec<Include>,
     pub algorithm: bool,
     pub array: bool,
+    pub cassert: bool,
     pub cstddef: bool,
     pub cstdint: bool,
     pub cstring: bool,
@@ -75,6 +76,7 @@ pub(super) fn write(out: &mut OutFile) {
         custom: _,
         algorithm,
         array,
+        cassert,
         cstddef,
         cstdint,
         cstring,
@@ -99,6 +101,9 @@ pub(super) fn write(out: &mut OutFile) {
     if array {
         writeln!(out, "#include <array>");
     }
+    if cassert {
+        writeln!(out, "#include <cassert>");
+    }
     if cstddef {
         writeln!(out, "#include <cstddef>");
     }

From db0a42145095a52a3ef0fd4aa087dd26122c95c1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 14 2021 19:32:58 +0000
Subject: [PATCH 2052/2232] Merge pull request #676 from dtolnay/cassert


Include <cassert> where needed in generated code
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 3b411aa..378467b 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -64,6 +64,7 @@ pub(super) fn write(out: &mut OutFile) {
     if builtin.rust_vec {
         include.algorithm = true;
         include.array = true;
+        include.cassert = true;
         include.cstddef = true;
         include.cstdint = true;
         include.initializer_list = true;
@@ -78,6 +79,7 @@ pub(super) fn write(out: &mut OutFile) {
 
     if builtin.rust_slice {
         include.array = true;
+        include.cassert = true;
         include.cstddef = true;
         include.cstdint = true;
         include.iterator = true;
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 6b7e580..93ce60b 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -23,6 +23,7 @@ pub struct Includes<'a> {
     pub custom: Vec<Include>,
     pub algorithm: bool,
     pub array: bool,
+    pub cassert: bool,
     pub cstddef: bool,
     pub cstdint: bool,
     pub cstring: bool,
@@ -75,6 +76,7 @@ pub(super) fn write(out: &mut OutFile) {
         custom: _,
         algorithm,
         array,
+        cassert,
         cstddef,
         cstdint,
         cstring,
@@ -99,6 +101,9 @@ pub(super) fn write(out: &mut OutFile) {
     if array {
         writeln!(out, "#include <array>");
     }
+    if cassert {
+        writeln!(out, "#include <cassert>");
+    }
     if cstddef {
         writeln!(out, "#include <cstddef>");
     }

From 5c353d80244a4704f8eadaaa86f046535b79db35 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 14 2021 19:35:17 +0000
Subject: [PATCH 2053/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index 43d94c9..2479558 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.57/src/**"]),
+    srcs = glob(["vendor/syn-1.0.58/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index cda5cdd..a8e5622 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -78,7 +78,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.57/src/**"]),
+    srcs = glob(["vendor/syn-1.0.58/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a7a2f59..c56d13e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -175,15 +175,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.81"
+version = "0.2.82"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
+checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
 
 [[package]]
 name = "link-cplusplus"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f96aa785c87218ec773df6c510af203872b34e2df2cf47d6e908e5f36231e354"
+checksum = "8f1becd27d473556dc610b8afa1636ef90747b574a84553bc11e82371d5ef2d1"
 dependencies = [
  "cc",
 ]
@@ -232,18 +232,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.118"
+version = "1.0.119"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
+checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.118"
+version = "1.0.119"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
+checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.57"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
+checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
 dependencies = [
  "proc-macro2",
  "quote",

From 23fe7e437a5e1bb0a02ac8d341fa138674622127 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 14 2021 19:35:32 +0000
Subject: [PATCH 2054/2232] Release 1.0.28


---

diff --git a/Cargo.toml b/Cargo.toml
index 7cb33fe..847d6c3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.27" # remember to update html_root_url
+version = "1.0.28" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.27", path = "macro" }
+cxxbridge-macro = { version = "=1.0.28", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.27", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.28", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.27", path = "gen/build" }
+cxx-build = { version = "=1.0.28", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index b4532cc..8a7b56f 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.27"
+version = "1.0.28"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index b4e2548..fdcbe27 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.27"
+version = "1.0.28"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 005a088..e518369 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.27"
+version = "1.0.28"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index cf9d658..c6da2ba 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.27"
+version = "0.7.28"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 0951135..02ed6c8 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.27"
+version = "1.0.28"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 030fabb..e7e769c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.27")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.28")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index c56d13e..ab40d00 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.27"
+version = "1.0.28"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.27"
+version = "1.0.28"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.27"
+version = "0.7.28"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.27"
+version = "1.0.28"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.27"
+version = "1.0.28"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.27"
+version = "1.0.28"
 dependencies = [
  "cxx",
  "proc-macro2",

From cbad4f37fe92c2762a7fc75da6cc202e97b14a1a Mon Sep 17 00:00:00 2001
From: Vitaly Shukela <vi0oss@gmail.com>
Date: Jan 15 2021 06:25:41 +0000
Subject: [PATCH 2055/2232] Fix minor typo


---

diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 18f600f..b3a1b1c 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -47,7 +47,7 @@ where
         }
     }
 
-    /// Chacks whether the SharedPtr does not own an object.
+    /// Checks whether the SharedPtr does not own an object.
     ///
     /// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
     pub fn is_null(&self) -> bool {

From 2029c873c2733846e47516d540ae9ff525e0abfe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 15 2021 07:16:06 +0000
Subject: [PATCH 2056/2232] Merge pull request #678 from vi/patch-1


Fix minor typo
---

diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 18f600f..b3a1b1c 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -47,7 +47,7 @@ where
         }
     }
 
-    /// Chacks whether the SharedPtr does not own an object.
+    /// Checks whether the SharedPtr does not own an object.
     ///
     /// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
     pub fn is_null(&self) -> bool {

From 0ba1079dd0c85e45a23bd5c8dfb8fdc30899bed8 Mon Sep 17 00:00:00 2001
From: Fletcher Woodruff <fletcherw@chromium.org>
Date: Jan 20 2021 21:09:04 +0000
Subject: [PATCH 2057/2232] Clarify error for using enum as method receiver


Update the syntax checker to print a more specific error when an enum is
used as a method receiver, rather than printing a misleading "unrecognized
receiver type" error.

This is done because C++ prohibits enums from having member functions.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2098a1b..0aa3837 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -389,6 +389,8 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 mutability = mutability,
             );
             cx.error(span, msg);
+        } else if cx.types.enums.contains_key(&receiver.ty.rust) {
+            cx.error(span, "C++ does not allow member functions on enums");
         } else if !cx.types.structs.contains_key(&receiver.ty.rust)
             && !cx.types.cxx.contains(&receiver.ty.rust)
             && !cx.types.rust.contains(&receiver.ty.rust)
diff --git a/tests/ui/enum_receiver.rs b/tests/ui/enum_receiver.rs
new file mode 100644
index 0000000..a27f274
--- /dev/null
+++ b/tests/ui/enum_receiver.rs
@@ -0,0 +1,11 @@
+#[cxx::bridge]
+mod ffi {
+    enum Enum {
+        Variant,
+    }
+    extern "Rust" {
+        fn f(self: &Enum);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_receiver.stderr b/tests/ui/enum_receiver.stderr
new file mode 100644
index 0000000..8523c77
--- /dev/null
+++ b/tests/ui/enum_receiver.stderr
@@ -0,0 +1,5 @@
+error: C++ does not allow member functions on enums
+ --> $DIR/enum_receiver.rs:7:20
+  |
+7 |         fn f(self: &Enum);
+  |                    ^^^^^

From 38ae2288343725899c936dd06d5d4e147d80e8b1 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adrian@macrobug.com>
Date: Jan 23 2021 19:34:13 +0000
Subject: [PATCH 2058/2232] Support raw pointers in cxx::bridge.


This allows raw pointers to types to be passed into and out of
cxx::bridge extern "C++" APIs. As normal with raw pointers in Rust,
there are no safety or lifetime guarantees.

Passing a raw pointer into such an API requires that the
function be marked "unsafe".

---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index a2ce630..b3911c1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -222,7 +222,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Fn(_) => out.builtin.rust_fn = true,
             Type::SliceRef(_) => out.builtin.rust_slice = true,
             Type::Array(_) => out.include.array = true,
-            Type::Ref(_) | Type::Void(_) => {}
+            Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {}
         }
     }
 }
@@ -1179,6 +1179,13 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &r.inner);
             write!(out, " &");
         }
+        Type::Ptr(p) => {
+            if !p.mutable {
+                write!(out, "const ");
+            }
+            write_type(out, &p.inner);
+            write!(out, " *");
+        }
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
@@ -1253,7 +1260,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::SliceRef(_)
         | Type::Fn(_)
         | Type::Array(_) => write!(out, " "),
-        Type::Ref(_) => {}
+        Type::Ref(_) | Type::Ptr(_) => {}
         Type::Void(_) => unreachable!(),
     }
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 2098a1b..e4933d3 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -8,6 +8,8 @@ use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
 
+use super::Ptr;
+
 pub(crate) struct Check<'a> {
     apis: &'a [Api],
     types: &'a Types<'a>,
@@ -35,6 +37,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Ptr(ty) => check_type_ptr(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
@@ -221,7 +224,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     }
 
     match ty.inner {
-        Type::Fn(_) | Type::Void(_) => {}
+        Type::Fn(_) | Type::Void(_) | Type::Ptr(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow references to references");
             return;
@@ -232,6 +235,12 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     cx.error(ty, "unsupported reference type");
 }
 
+fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
+    if let Type::Ident(_) = ty.inner { return }
+
+    cx.error(ty, "unsupported pointer type");
+}
+
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = !is_unsized(cx, &ty.inner)
         || match &ty.inner {
@@ -555,6 +564,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         | Type::SharedPtr(_)
         | Type::WeakPtr(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
     }
@@ -628,6 +638,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::SharedPtr(_) => "shared_ptr".to_owned(),
         Type::WeakPtr(_) => "weak_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
+        Type::Ptr(_) => "raw pointer".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::SliceRef(_) => "slice".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 3a0b3e0..954f39b 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -5,6 +5,8 @@ use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+use super::Ptr;
+
 impl PartialEq for Include {
     fn eq(&self, other: &Include) -> bool {
         let Include {
@@ -47,6 +49,7 @@ impl Hash for Type {
             Type::SharedPtr(t) => t.hash(state),
             Type::WeakPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
+            Type::Ptr(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
             Type::CxxVector(t) => t.hash(state),
@@ -189,6 +192,42 @@ impl Hash for Ref {
     }
 }
 
+impl Eq for Ptr {}
+
+impl PartialEq for Ptr {
+    fn eq(&self, other: &Ptr) -> bool {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        let Ptr {
+            star: _,
+            mutable: mutable2,
+            inner: inner2,
+            mutability: _,
+            constness: _,
+        } = other;
+        mutable == mutable2 && inner == inner2
+    }
+}
+
+impl Hash for Ptr {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        mutable.hash(state);
+        inner.hash(state);
+    }
+}
+
 impl Eq for SliceRef {}
 
 impl PartialEq for SliceRef {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index d672e7d..6a9b5ac 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -32,6 +32,7 @@ impl<'a> Types<'a> {
                 Definite(false)
             }
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+            Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 30faccc..87e3454 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -204,6 +204,7 @@ pub enum Type {
     SharedPtr(Box<Ty1>),
     WeakPtr(Box<Ty1>),
     Ref(Box<Ref>),
+    Ptr(Box<Ptr>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
@@ -229,6 +230,14 @@ pub struct Ref {
     pub mutability: Option<Token![mut]>,
 }
 
+pub struct Ptr {
+    pub star: Token![*],
+    pub mutable: bool,
+    pub inner: Type,
+    pub mutability: Option<Token![mut]>,
+    pub constness: Option<Token![const]>,
+}
+
 pub struct SliceRef {
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index fbb24e2..af03248 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -11,7 +11,7 @@ use crate::syntax::{
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
-use syn::parse::{ParseStream, Parser};
+use syn::{TypePtr, parse::{ParseStream, Parser}};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -21,6 +21,8 @@ use syn::{
     TypeReference, Variant as RustVariant, Visibility,
 };
 
+use super::Ptr;
+
 pub mod kw {
     syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
@@ -547,6 +549,7 @@ fn parse_extern_fn(
         ));
     }
 
+    let unsafety = foreign_fn.sig.unsafety;
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -583,6 +586,11 @@ fn parse_extern_fn(
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     let name = pair(Namespace::default(), &ident, None, None);
+                    if let Type::Ptr(_) = &ty {
+                        if unsafety.is_none() {
+                            return Err(Error::new_spanned(arg, "pointer argument requires that the function be marked unsafe"));
+                        }
+                    }
                     args.push_value(Var {
                         doc,
                         attrs,
@@ -620,7 +628,6 @@ fn parse_extern_fn(
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
-    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
@@ -965,6 +972,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         },
         Type::Ident(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::Fn(_)
         | Type::Void(_)
@@ -1033,6 +1041,7 @@ fn parse_include(input: ParseStream) -> Result<Include> {
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Ptr(ty) => parse_type_ptr(ty),
         RustType::Path(ty) => parse_type_path(ty),
         RustType::Array(ty) => parse_type_array(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
@@ -1084,6 +1093,26 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     })))
 }
 
+fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
+    let star = ty.star_token;
+    let mutable = ty.mutability.is_some();
+    let constness = ty.const_token;
+    let mutability = ty.mutability;
+    if !constness.is_some() && !mutable {
+        return Err(Error::new_spanned(ty, "pointer is neither const nor mut"));
+    }
+
+    let inner = parse_type(&ty.elem)?;
+    
+    Ok(Type::Ptr(Box::new(Ptr {
+        star,
+        mutable,
+        inner,
+        mutability,
+        constness,
+    })))
+}
+
 fn parse_type_path(ty: &TypePath) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
diff --git a/syntax/pod.rs b/syntax/pod.rs
index e1c4831..0bf152e 100644
--- a/syntax/pod.rs
+++ b/syntax/pod.rs
@@ -29,7 +29,7 @@ impl<'a> Types<'a> {
             | Type::WeakPtr(_)
             | Type::CxxVector(_)
             | Type::Void(_) => false,
-            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) | Type::Ptr(_) => true,
             Type::Array(array) => self.is_guaranteed_pod(&array.inner),
         }
     }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index bb04e16..d728ac0 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -7,6 +7,8 @@ use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::{token, Token};
 
+use super::Ptr;
+
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
@@ -27,6 +29,7 @@ impl ToTokens for Type {
             | Type::CxxVector(ty)
             | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ptr(p) => p.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
@@ -100,6 +103,22 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Ptr {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Ptr {
+            star,
+            mutable: _,
+            inner,
+            mutability,
+            constness,
+        } = self;
+        star.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        constness.to_tokens(tokens);
+        inner.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for SliceRef {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let SliceRef {
diff --git a/syntax/types.rs b/syntax/types.rs
index 7bf2baf..031dc08 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -51,6 +51,7 @@ impl<'a> Types<'a> {
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Ptr(p) => visit(all, &p.inner),
                 Type::Array(a) => visit(all, &a.inner),
                 Type::SliceRef(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 32d739d..5f11a6a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -121,6 +121,8 @@ pub mod ffi {
         fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
         fn c_return_ns_enum(n: u16) -> AEnum;
         fn c_return_nested_ns_enum(n: u16) -> ABEnum;
+        fn c_return_opaque_raw_ptr(n: usize) -> *const C;
+        fn c_return_opaque_mut_raw_ptr(n: usize) -> *mut C;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -161,6 +163,12 @@ pub mod ffi {
         fn c_take_nested_ns_shared(shared: ABShared);
         fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
         fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
+        /// # Unsafety
+        /// To keep clippy happy.
+        unsafe fn c_take_opaque_mut_raw_ptr(c: *mut C) -> usize;
+        /// # Unsafety
+        /// To keep clippy happy.
+        unsafe fn c_take_opaque_raw_ptr(c: *const C) -> usize;
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8ed5456..25cf26b 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,6 +207,24 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+const C* c_return_opaque_raw_ptr(size_t c) {
+  return new C(c);
+}
+
+C* c_return_opaque_mut_raw_ptr(size_t c) {
+  return new C(c);
+}
+
+size_t c_take_opaque_raw_ptr(const C* c) {
+  return c->get();
+}
+
+size_t c_take_opaque_mut_raw_ptr(C* c) {
+  size_t result = c->get();
+  delete c;
+  return result;
+}
+
 Borrow::Borrow(const std::string &s) : s(s) {}
 
 void Borrow::const_member() const {}
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index a28c166..3de24e6 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -118,6 +118,8 @@ Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
+const C* c_return_opaque_raw_ptr(size_t n);
+C* c_return_opaque_mut_raw_ptr(size_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -161,6 +163,8 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
+size_t c_take_opaque_raw_ptr(const C* c);
+size_t c_take_opaque_mut_raw_ptr(C* c);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index e0815a6..2c7f763 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -335,3 +335,19 @@ fn test_extern_opaque() {
     check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ns_ptr(f));
 }
+
+#[test]
+fn test_raw_ptr() {
+    let c = ffi::c_return_opaque_mut_raw_ptr(2023);
+    let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) };
+    assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap());
+    // c will be dropped as it's now in a UniquePtr
+
+    let c2 = ffi::c_return_opaque_mut_raw_ptr(2024);
+    assert_eq!(2024, unsafe { ffi::c_take_opaque_raw_ptr(c2) });
+    assert_eq!(2024, unsafe { ffi::c_take_opaque_mut_raw_ptr(c2) }); // deletes c2
+
+    let c3 = ffi::c_return_opaque_raw_ptr(2025);
+    assert_eq!(2025, unsafe { ffi::c_take_opaque_raw_ptr(c3) });
+    assert_eq!(2025, unsafe { ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C) }); // deletes c3
+}
\ No newline at end of file
diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
new file mode 100644
index 0000000..773afe8
--- /dev/null
+++ b/tests/ui/unsupported_ptr.rs
@@ -0,0 +1,30 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn not_unsafe_ptr(c: *mut C);
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_neither_const_nor_mut() -> *C;
+    }
+}
+
+#[cxx::bridge]
+mod ffi3 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_ptr() -> *mut *mut C;
+        fn get_ptr_reference() -> *mut & C;
+        fn get_reference_ptr() -> & *mut C;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
new file mode 100644
index 0000000..fdd704f
--- /dev/null
+++ b/tests/ui/unsupported_ptr.stderr
@@ -0,0 +1,37 @@
+error: expected mut or const in raw pointer type
+  --> $DIR/unsupported_ptr.rs:15:43
+   |
+15 |         fn get_neither_const_nor_mut() -> *C;
+   |                                           ^ expected mut or const in raw pointer type
+   |
+   = help: use `*mut T` or `*const T` as appropriate
+
+error: pointer argument requires that the function be marked unsafe
+ --> $DIR/unsupported_ptr.rs:6:27
+  |
+6 |         fn not_unsafe_ptr(c: *mut C);
+  |                           ^^^^^^^^^
+
+error: expected `const` or `mut`
+  --> $DIR/unsupported_ptr.rs:15:44
+   |
+15 |         fn get_neither_const_nor_mut() -> *C;
+   |                                            ^
+
+error: unsupported pointer type
+  --> $DIR/unsupported_ptr.rs:24:29
+   |
+24 |         fn get_ptr_ptr() -> *mut *mut C;
+   |                             ^^^^^^^^^^^
+
+error: unsupported pointer type
+  --> $DIR/unsupported_ptr.rs:25:35
+   |
+25 |         fn get_ptr_reference() -> *mut & C;
+   |                                   ^^^^^^^^
+
+error: unsupported reference type
+  --> $DIR/unsupported_ptr.rs:26:35
+   |
+26 |         fn get_reference_ptr() -> & *mut C;
+   |                                   ^^^^^^^^

From 38ad389ef006334e7de93625092c85502d465429 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adrian@macrobug.com>
Date: Jan 24 2021 16:08:46 +0000
Subject: [PATCH 2059/2232] Prevent pointers in Vector, UniquePtr.


For now. This could be supported in future.

---

diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
index 773afe8..a3b5cc4 100644
--- a/tests/ui/unsupported_ptr.rs
+++ b/tests/ui/unsupported_ptr.rs
@@ -27,4 +27,14 @@ mod ffi3 {
     }
 }
 
+#[cxx::bridge]
+mod ffi4 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
+        fn get_ptr_unique() -> UniquePtr<*mut C>;
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
index fdd704f..03756bf 100644
--- a/tests/ui/unsupported_ptr.stderr
+++ b/tests/ui/unsupported_ptr.stderr
@@ -35,3 +35,15 @@ error: unsupported reference type
    |
 26 |         fn get_reference_ptr() -> & *mut C;
    |                                   ^^^^^^^^
+
+error: unsupported vector target type
+  --> $DIR/unsupported_ptr.rs:35:42
+   |
+35 |         fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
+   |                                          ^^^^^^^^^^^^^^^^^^
+
+error: unsupported unique_ptr target type
+  --> $DIR/unsupported_ptr.rs:36:32
+   |
+36 |         fn get_ptr_unique() -> UniquePtr<*mut C>;
+   |                                ^^^^^^^^^^^^^^^^^

From 75f417fff6e62c5340448cc1c38d70d3ce4b3055 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adrian@macrobug.com>
Date: Jan 24 2021 16:57:45 +0000
Subject: [PATCH 2060/2232] Documentation for raw pointers.


---

diff --git a/README.md b/README.md
index b3058f6..c5d93ae 100644
--- a/README.md
+++ b/README.md
@@ -333,6 +333,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/book/src/binding/raw_ptr.md b/book/src/binding/raw_ptr.md
new file mode 100644
index 0000000..7ad6475
--- /dev/null
+++ b/book/src/binding/raw_ptr.md
@@ -0,0 +1,68 @@
+{{#title *mut T, *const T — Rust ♡ C++}}
+# *mut T, *const T - Raw Pointers
+
+cxx supports tranfer of raw pointers across the FFI boundary.
+
+Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
+or references. You should resort to using raw pointers only where lifetimes
+are too complicated to model with standard cxx facilities.
+
+As is normal with raw pointers in Rust, you'll need to use `unsafe` when
+working with them. In particular, to pass any raw pointer into a cxx
+bridge function you will need to declare the function `unsafe`, even if
+the overall `extern "C++"` section is already marked as `unsafe`. By calling
+such a function, you're committing that you - the human - know enough about
+the lifetimes of those objects that the compiler doesn't need to do checks.
+
+On the other hand, C++ functions can freely return raw pointers to
+Rust without `unsafe`, but actually using those raw pointers in any way is likely
+to require an `unsafe` keyword.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+
+        include!("tests/ffi/tests.h");
+        //include!("example/include/container.h");
+
+        type ComplexHierarchicContainer;
+
+        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
+        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
+        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
+        // ...
+    }
+}
+
+fn main() {
+    let mut container = ffi17::new_hierarchic_container();
+    cxx::let_cxx_string!(key = "a");
+    let mut subcontainer = container.pin_mut().add_child(&key);
+    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
+    cxx::let_cxx_string!(key2 = "b");
+    cxx::let_cxx_string!(value = "c");
+    subcontainer.add_value(&key2, &value);
+    // ...
+}
+```
+
+```cpp
+// include/container.h
+
+#pragma once
+
+class ComplexHierarchicContainer {
+public:
+    ComplexHierarchicContainer();
+    void add_value(const std::string& key, const std::string& value);
+    ComplexHierarchicContainer* add_child(const std::string& key);
+    // ...
+};
+
+std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 4a765b3..9ba0c41 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -22,6 +22,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 </table>
 
 <br>

From 26d0f442f0c142136b3ec0d009064440f5342ee8 Mon Sep 17 00:00:00 2001
From: Michael Forster <forster@google.com>
Date: Jan 27 2021 16:48:50 +0000
Subject: [PATCH 2061/2232] Upgrade the dependency on codespan_reporting


This is to avoid a downstream dependency to depend on multiple versions of
that crate.

---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index fdcbe27..6d5a6cd 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,7 +13,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e518369..87c6296 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ path = "src/main.rs"
 
 [dependencies]
 clap = "2.33"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index c6da2ba..f938ae6 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -12,7 +12,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/third-party/BUCK b/third-party/BUCK
index 2479558..e2756a9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -25,7 +25,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
diff --git a/third-party/BUILD b/third-party/BUILD
index a8e5622..920d815 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",

From 5d3f36c8af4953df2e828a2ec866b4e47bf2cdf4 Mon Sep 17 00:00:00 2001
From: Andre Brisco <andre.brisco@gmail.com>
Date: Jan 27 2021 17:27:20 +0000
Subject: [PATCH 2062/2232] Updated Bazel Rust rules version


---

diff --git a/WORKSPACE b/WORKSPACE
index 039237b..ce4e1ac 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,39 +2,18 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//tools/bazel:vendor.bzl", "vendor")
 
 http_archive(
-    name = "io_bazel_rules_rust",
-    sha256 = "5ed804fcd10a506a5b8e9e59bc6b3b7f43bc30c87ce4670e6f78df43604894fd",
-    strip_prefix = "rules_rust-fdf9655ba95616e0314b4e0ebab40bb0c5fe005c",
-    # Master branch as of 2020-07-30
-    url = "https://github.com/bazelbuild/rules_rust/archive/fdf9655ba95616e0314b4e0ebab40bb0c5fe005c.tar.gz",
-)
-
-http_archive(
-    name = "bazel_skylib",
-    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
+    name = "rules_rust",
+    sha256 = "e6d835ee673f388aa5b62dc23d82db8fc76497e93fa47d8a4afe97abaf09b10d",
+    strip_prefix = "rules_rust-f37b9d6a552e9412285e627f30cb124e709f4f7a",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+        # Master branch as of 2021-01-27
+        "https://github.com/bazelbuild/rules_rust/archive/f37b9d6a552e9412285e627f30cb124e709f4f7a.tar.gz",
     ],
 )
 
-load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
-
-bazel_version(name = "bazel_version")
+load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
-load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
-
-rust_repository_set(
-    name = "rust_1_48_linux",
-    exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.48.0",
-)
-
-rust_repository_set(
-    name = "rust_1_48_darwin",
-    exec_triple = "x86_64-apple-darwin",
-    version = "1.48.0",
-)
+rust_repositories()
 
 vendor(
     name = "third-party",
diff --git a/third-party/BUILD b/third-party/BUILD
index a8e5622..6b9e7bb 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,10 +1,8 @@
 load(
     "//tools/bazel:rust.bzl",
     glob = "third_party_glob",
-    rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
-load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "bitflags",
diff --git a/tools/bazel/BUILD b/tools/bazel/BUILD
index e69de29..d42fc71 100644
--- a/tools/bazel/BUILD
+++ b/tools/bazel/BUILD
@@ -0,0 +1,7 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+bzl_library(
+    name = "bzl_srcs",
+    srcs = glob(["**/*.bzl"]),
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
index b7b23e5..9f71923 100644
--- a/tools/bazel/rust.bzl
+++ b/tools/bazel/rust.bzl
@@ -1,5 +1,7 @@
+"""A module wrapping the core rules of `rules_rust`"""
+
 load(
-    "@io_bazel_rules_rust//rust:rust.bzl",
+    "@rules_rust//rust:rust.bzl",
     _rust_binary = "rust_binary",
     _rust_library = "rust_library",
     _rust_test = "rust_test",
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 534f6b5..d026e0d 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,7 +1,15 @@
+# buildifier: disable=module-docstring
 load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 def rust_cxx_bridge(name, src, deps = []):
+    """A macro defining a cxx bridge library
+
+    Args:
+        name (string): The name of the new target
+        src (string): The rust source file to generate a bridge for
+        deps (list, optional): A list of dependencies for the underlying cc_library. Defaults to [].
+    """
     native.alias(
         name = "%s/header" % name,
         actual = src + ".h",
diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
index e9f10ac..24678e8 100644
--- a/tools/bazel/vendor.bzl
+++ b/tools/bazel/vendor.bzl
@@ -1,3 +1,7 @@
+"""A module defining a repository rule for vendoring the dependencies
+of a crate in the current workspace.
+"""
+
 def _impl(repository_ctx):
     # Link cxx repository into @third-party.
     lockfile = repository_ctx.path(repository_ctx.attr.lockfile)
@@ -48,7 +52,12 @@ def _log_cargo_vendor(repository_ctx, result):
         repository_ctx.execute(print, quiet = False)
 
 vendor = repository_rule(
-    attrs = {"lockfile": attr.label()},
+    doc = "A rule used to vender the dependencies of a crate in the current workspace",
+    attrs = {
+        "lockfile": attr.label(
+            doc = "A lockfile providing the set of crates to vendor",
+        ),
+    },
     local = True,
     implementation = _impl,
 )

From 57982c4d4c2ad3fbdb36315dd03846b90970d27a Mon Sep 17 00:00:00 2001
From: Andre Brisco <andre.brisco@gmail.com>
Date: Jan 27 2021 17:27:20 +0000
Subject: [PATCH 2063/2232] Updated version of Bazel used in CI to 4.0.0 (Bazel's first LTS release)


---

diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
index 6085459..f276388 100644
--- a/.devcontainer/build.Dockerfile
+++ b/.devcontainer/build.Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update \
     && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
     && rustup default nightly 2>&1 \
     && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
-    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh \
     && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex \
     && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
     && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9e1aef3..86f58a6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -84,7 +84,7 @@ jobs:
       - uses: actions/checkout@v2
       - name: Install Bazel
         run: |
-          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
           echo $HOME/bin >> $GITHUB_PATH

From f48155707c71f9edd3d49cd072aba3e12ae4a407 Mon Sep 17 00:00:00 2001
From: Michael Forster <forster@google.com>
Date: Jan 27 2021 17:54:07 +0000
Subject: [PATCH 2064/2232] Update the third-party/Cargo.lock file.


I assume that this is necessary for the Buck CI to succeed.

---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ab40d00..fc417e8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -49,9 +49,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d"
+checksum = "c6ce42b8998a383572e0a802d859b1f00c79b7b7474e62fff88ee5c2845d9c13"
 dependencies = [
  "termcolor",
  "unicode-width",

From 921c16de1ccba79140433b56dc168d0184cfba63 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:13:56 +0000
Subject: [PATCH 2065/2232] Merge pull request #692 from MForster/upgrade-codespan-reporting


Upgrade the dependency on codespan_reporting
---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index fdcbe27..6d5a6cd 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -13,7 +13,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e518369..87c6296 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -17,7 +17,7 @@ path = "src/main.rs"
 
 [dependencies]
 clap = "2.33"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index c6da2ba..f938ae6 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -12,7 +12,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/third-party/BUCK b/third-party/BUCK
index 2479558..e2756a9 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -25,7 +25,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
diff --git a/third-party/BUILD b/third-party/BUILD
index a8e5622..920d815 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -31,7 +31,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ab40d00..fc417e8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -49,9 +49,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d"
+checksum = "c6ce42b8998a383572e0a802d859b1f00c79b7b7474e62fff88ee5c2845d9c13"
 dependencies = [
  "termcolor",
  "unicode-width",

From dcc1db841ebfb3cb36dc869854e3370713e3b144 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:25:48 +0000
Subject: [PATCH 2066/2232] Add regression test of let_cxx_string in async fn


    error: future cannot be sent between threads safely
      --> tests/cxx_string.rs:14:5
       |
    13 |     fn assert_send(_: impl Send) {}
       |                            ---- required by this bound in `assert_send`
    14 |     assert_send(f());
       |     ^^^^^^^^^^^ future returned by `f` is not `Send`
       |
       = help: within `impl Future`, the trait `Send` is not implemented for `*const ()`
    note: future is not `Send` as this value is used across an await
      --> tests/cxx_string.rs:9:9
       |
    6  |         let_cxx_string!(s = "...");
       |         --------------------------- has type `StackString` which is not `Send`
    ...
    9  |         g(&s).await;
       |         ^^^^^^^^^^^ await occurs here, with `mut $var` maybe used later
    10 |     }
       |     - `mut $var` is later dropped here

---

diff --git a/tests/cxx_string.rs b/tests/cxx_string.rs
new file mode 100644
index 0000000..be693cd
--- /dev/null
+++ b/tests/cxx_string.rs
@@ -0,0 +1,15 @@
+use cxx::{let_cxx_string, CxxString};
+
+#[test]
+fn test_async_cxx_string() {
+    async fn f() {
+        let_cxx_string!(s = "...");
+
+        async fn g(_: &CxxString) {}
+        g(&s).await;
+    }
+
+    // https://github.com/dtolnay/cxx/issues/693
+    fn assert_send(_: impl Send) {}
+    assert_send(f());
+}

From 0df1fdbcedc4f3d58cd49cd62dabf96617ad7035 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:26:39 +0000
Subject: [PATCH 2067/2232] Allow Send/Sync of let_cxx_string


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 10abbce..08a58b1 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -188,7 +188,7 @@ impl PartialEq<str> for CxxString {
 pub struct StackString {
     // Static assertions in cxx.cc validate that this is large enough and
     // aligned enough.
-    space: MaybeUninit<[*const (); 8]>,
+    space: MaybeUninit<[usize; 8]>,
 }
 
 impl StackString {

From f514214284dda74df989b0d06e1d90cfc13a5f5b Mon Sep 17 00:00:00 2001
From: Andre Brisco <andre.brisco@gmail.com>
Date: Jan 27 2021 19:26:59 +0000
Subject: [PATCH 2068/2232] Restored explicit version and edition


---

diff --git a/WORKSPACE b/WORKSPACE
index ce4e1ac..e9b08ef 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,7 +13,10 @@ http_archive(
 
 load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
-rust_repositories()
+rust_repositories(
+    edition = "2018",
+    version = "1.48.0",
+)
 
 vendor(
     name = "third-party",

From 6adcf7d9a44114b5d8f03a4ea1a9eb528cb5a316 Mon Sep 17 00:00:00 2001
From: Andre Brisco <andre.brisco@gmail.com>
Date: Jan 27 2021 19:27:03 +0000
Subject: [PATCH 2069/2232] Fixed typo


---

diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
index 24678e8..e404ad9 100644
--- a/tools/bazel/vendor.bzl
+++ b/tools/bazel/vendor.bzl
@@ -52,7 +52,7 @@ def _log_cargo_vendor(repository_ctx, result):
         repository_ctx.execute(print, quiet = False)
 
 vendor = repository_rule(
-    doc = "A rule used to vender the dependencies of a crate in the current workspace",
+    doc = "A rule used to vendor the dependencies of a crate in the current workspace",
     attrs = {
         "lockfile": attr.label(
             doc = "A lockfile providing the set of crates to vendor",

From e15eb78cf3fe30f267e2ef5d9422eca10e37baa4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:29:16 +0000
Subject: [PATCH 2070/2232] Merge pull request #691 from UebelAndre/bazel


Updated Bazel Rust rules version
---

diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
index 6085459..f276388 100644
--- a/.devcontainer/build.Dockerfile
+++ b/.devcontainer/build.Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update \
     && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
     && rustup default nightly 2>&1 \
     && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
-    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh \
     && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex \
     && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
     && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9e1aef3..86f58a6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -84,7 +84,7 @@ jobs:
       - uses: actions/checkout@v2
       - name: Install Bazel
         run: |
-          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
           echo $HOME/bin >> $GITHUB_PATH
diff --git a/WORKSPACE b/WORKSPACE
index 039237b..e9b08ef 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,37 +2,19 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//tools/bazel:vendor.bzl", "vendor")
 
 http_archive(
-    name = "io_bazel_rules_rust",
-    sha256 = "5ed804fcd10a506a5b8e9e59bc6b3b7f43bc30c87ce4670e6f78df43604894fd",
-    strip_prefix = "rules_rust-fdf9655ba95616e0314b4e0ebab40bb0c5fe005c",
-    # Master branch as of 2020-07-30
-    url = "https://github.com/bazelbuild/rules_rust/archive/fdf9655ba95616e0314b4e0ebab40bb0c5fe005c.tar.gz",
-)
-
-http_archive(
-    name = "bazel_skylib",
-    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
+    name = "rules_rust",
+    sha256 = "e6d835ee673f388aa5b62dc23d82db8fc76497e93fa47d8a4afe97abaf09b10d",
+    strip_prefix = "rules_rust-f37b9d6a552e9412285e627f30cb124e709f4f7a",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+        # Master branch as of 2021-01-27
+        "https://github.com/bazelbuild/rules_rust/archive/f37b9d6a552e9412285e627f30cb124e709f4f7a.tar.gz",
     ],
 )
 
-load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
-
-bazel_version(name = "bazel_version")
-
-load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
-
-rust_repository_set(
-    name = "rust_1_48_linux",
-    exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.48.0",
-)
+load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
-rust_repository_set(
-    name = "rust_1_48_darwin",
-    exec_triple = "x86_64-apple-darwin",
+rust_repositories(
+    edition = "2018",
     version = "1.48.0",
 )
 
diff --git a/third-party/BUILD b/third-party/BUILD
index 920d815..1e37a09 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,10 +1,8 @@
 load(
     "//tools/bazel:rust.bzl",
     glob = "third_party_glob",
-    rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
-load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "bitflags",
diff --git a/tools/bazel/BUILD b/tools/bazel/BUILD
index e69de29..d42fc71 100644
--- a/tools/bazel/BUILD
+++ b/tools/bazel/BUILD
@@ -0,0 +1,7 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+bzl_library(
+    name = "bzl_srcs",
+    srcs = glob(["**/*.bzl"]),
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
index b7b23e5..9f71923 100644
--- a/tools/bazel/rust.bzl
+++ b/tools/bazel/rust.bzl
@@ -1,5 +1,7 @@
+"""A module wrapping the core rules of `rules_rust`"""
+
 load(
-    "@io_bazel_rules_rust//rust:rust.bzl",
+    "@rules_rust//rust:rust.bzl",
     _rust_binary = "rust_binary",
     _rust_library = "rust_library",
     _rust_test = "rust_test",
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 534f6b5..d026e0d 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,7 +1,15 @@
+# buildifier: disable=module-docstring
 load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 def rust_cxx_bridge(name, src, deps = []):
+    """A macro defining a cxx bridge library
+
+    Args:
+        name (string): The name of the new target
+        src (string): The rust source file to generate a bridge for
+        deps (list, optional): A list of dependencies for the underlying cc_library. Defaults to [].
+    """
     native.alias(
         name = "%s/header" % name,
         actual = src + ".h",
diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
index e9f10ac..e404ad9 100644
--- a/tools/bazel/vendor.bzl
+++ b/tools/bazel/vendor.bzl
@@ -1,3 +1,7 @@
+"""A module defining a repository rule for vendoring the dependencies
+of a crate in the current workspace.
+"""
+
 def _impl(repository_ctx):
     # Link cxx repository into @third-party.
     lockfile = repository_ctx.path(repository_ctx.attr.lockfile)
@@ -48,7 +52,12 @@ def _log_cargo_vendor(repository_ctx, result):
         repository_ctx.execute(print, quiet = False)
 
 vendor = repository_rule(
-    attrs = {"lockfile": attr.label()},
+    doc = "A rule used to vendor the dependencies of a crate in the current workspace",
+    attrs = {
+        "lockfile": attr.label(
+            doc = "A lockfile providing the set of crates to vendor",
+        ),
+    },
     local = True,
     implementation = _impl,
 )

From d5cb8ea52e69297a88977bfe83e9dfe0631ece24 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:31:27 +0000
Subject: [PATCH 2071/2232] Merge pull request #694 from dtolnay/sendstring


Allow Send/Sync of let_cxx_string
---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 10abbce..08a58b1 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -188,7 +188,7 @@ impl PartialEq<str> for CxxString {
 pub struct StackString {
     // Static assertions in cxx.cc validate that this is large enough and
     // aligned enough.
-    space: MaybeUninit<[*const (); 8]>,
+    space: MaybeUninit<[usize; 8]>,
 }
 
 impl StackString {
diff --git a/tests/cxx_string.rs b/tests/cxx_string.rs
new file mode 100644
index 0000000..be693cd
--- /dev/null
+++ b/tests/cxx_string.rs
@@ -0,0 +1,15 @@
+use cxx::{let_cxx_string, CxxString};
+
+#[test]
+fn test_async_cxx_string() {
+    async fn f() {
+        let_cxx_string!(s = "...");
+
+        async fn g(_: &CxxString) {}
+        g(&s).await;
+    }
+
+    // https://github.com/dtolnay/cxx/issues/693
+    fn assert_send(_: impl Send) {}
+    assert_send(f());
+}

From 539ccbc02dcf46d70a3ff0eea576a51ba8fabd58 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:32:44 +0000
Subject: [PATCH 2072/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index e2756a9..d5a03c2 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.58/src/**"]),
+    srcs = glob(["vendor/syn-1.0.60/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 1e37a09..c1ab800 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.58/src/**"]),
+    srcs = glob(["vendor/syn-1.0.60/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index fc417e8..8e2ea0e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -154,9 +154,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.17"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
 dependencies = [
  "libc",
 ]
@@ -232,18 +232,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.119"
+version = "1.0.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.119"
+version = "1.0.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.58"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.38"
+version = "1.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b06f8610494cbeb9a7665b398306f0109ab8708296d7f24b0bcd89178bb350"
+checksum = "1c9594b802f041389d2baac680663573dde3103bb4a4926d61d6aba689465978"
 dependencies = [
  "dissimilar",
  "glob",

From 45a1f88bf9e11ea0682f285a8dd353d866ff3cb8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 27 2021 19:37:31 +0000
Subject: [PATCH 2073/2232] Release 1.0.29


---

diff --git a/Cargo.toml b/Cargo.toml
index 847d6c3..9df0230 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.28" # remember to update html_root_url
+version = "1.0.29" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.28", path = "macro" }
+cxxbridge-macro = { version = "=1.0.29", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.28", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.29", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.28", path = "gen/build" }
+cxx-build = { version = "=1.0.29", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 8a7b56f..117385a 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 6d5a6cd..36c7a31 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 87c6296..58e5bd1 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index f938ae6..fd10605 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.28"
+version = "0.7.29"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 02ed6c8..907d864 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index e7e769c..0f92253 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.28")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.29")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8e2ea0e..5a8a4a1 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.28"
+version = "0.7.29"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.28"
+version = "1.0.29"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cxx",
  "proc-macro2",

From 83d6366d65aa0fdfd9cc956065e8c791c9c5ae3f Mon Sep 17 00:00:00 2001
From: Qinfan Wu <wqfish@calibra.com>
Date: Jan 31 2021 20:57:33 +0000
Subject: [PATCH 2074/2232] Minor correction in the async example


The first argument of the closure is actually the context, not the
sender. Rename it to `context` to make it clearer. Was slightly confused
the first time I read it.

---

diff --git a/book/src/async.md b/book/src/async.md
index 7574a22..b4c696a 100644
--- a/book/src/async.md
+++ b/book/src/async.md
@@ -60,7 +60,7 @@ pub async fn do_thing(arg: Arg) -> Ret {
 
     ffi::shim_doThing(
         arg,
-        |tx, ret| { let _ = tx.0.send(ret); },
+        |context, ret| { let _ = context.0.send(ret); },
         context,
     );
 

From 0cf68d335fbf2093c0dfc0d3b4851b91faf98ce4 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Jan 31 2021 21:10:53 +0000
Subject: [PATCH 2075/2232] Merge pull request #699 from wqfish/book


Minor correction in the async example
---

diff --git a/book/src/async.md b/book/src/async.md
index 7574a22..b4c696a 100644
--- a/book/src/async.md
+++ b/book/src/async.md
@@ -60,7 +60,7 @@ pub async fn do_thing(arg: Arg) -> Ret {
 
     ffi::shim_doThing(
         arg,
-        |tx, ret| { let _ = tx.0.send(ret); },
+        |context, ret| { let _ = context.0.send(ret); },
         context,
     );
 

From 9db5278dd41169ba9680ae5286d32ed4d785a02a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 01 2021 02:45:37 +0000
Subject: [PATCH 2076/2232] Ignore upper_case_acronyms clippy lint


    warning: name `CFG` contains a capitalized acronym
       --> gen/build/src/cfg.rs:350:9
        |
    350 |         CFG,
        |         ^^^ help: consider making the acronym lowercase, except the initial letter: `Cfg`
        |
        = note: `#[warn(clippy::upper_case_acronyms)]` on by default
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 204c89f..fda387d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -71,7 +71,8 @@
     clippy::struct_excessive_bools,
     clippy::too_many_arguments,
     clippy::too_many_lines,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    clippy::upper_case_acronyms
 )]
 
 mod cfg;
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 32d739d..e8e9b65 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -8,7 +8,8 @@
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref,
     clippy::unnecessary_wraps,
-    clippy::unused_self
+    clippy::unused_self,
+    clippy::upper_case_acronyms
 )]
 
 pub mod cast;

From 02ef21f484cb12cb39c72a8c35b5604daf678ffc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 01 2021 02:54:51 +0000
Subject: [PATCH 2077/2232] Ignore case convention lints in ffi module


The user may prefer to use C++ naming conventions rather than Rust
naming conventions on the language boundary, which isn't necessarily
bad.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 578d624..6b555d8 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -123,7 +123,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         #doc
         #attrs
         #[deny(improper_ctypes)]
-        #[allow(non_snake_case)]
+        #[allow(non_camel_case_types, non_snake_case)]
         #vis #mod_token #ident #expanded
     }
 }

From 2ed9d13d20b00912dd3bafe95d8cb69c48a7276f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 01 2021 02:55:55 +0000
Subject: [PATCH 2078/2232] Ignore clippy upper_case_acronyms lint in ffi module


The user may prefer to use C++ naming conventions rather than Rust
naming conventions on the language boundary, which isn't necessarily
bad.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6b555d8..1df0463 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -123,7 +123,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         #doc
         #attrs
         #[deny(improper_ctypes)]
-        #[allow(non_camel_case_types, non_snake_case)]
+        #[allow(non_camel_case_types, non_snake_case, clippy::upper_case_acronyms)]
         #vis #mod_token #ident #expanded
     }
 }
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index e8e9b65..32d739d 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -8,8 +8,7 @@
     clippy::ptr_arg,
     clippy::trivially_copy_pass_by_ref,
     clippy::unnecessary_wraps,
-    clippy::unused_self,
-    clippy::upper_case_acronyms
+    clippy::unused_self
 )]
 
 pub mod cast;

From ea34e6350c7ff6528e9aebec1be7918dd2a2b608 Mon Sep 17 00:00:00 2001
From: Marcel Hlopko <hlopko@google.com>
Date: Feb 01 2021 20:20:53 +0000
Subject: [PATCH 2079/2232] Make rust_cxx_bridge usable from other repositories


---

diff --git a/WORKSPACE b/WORKSPACE
index e9b08ef..fde28ff 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,3 +1,5 @@
+workspace(name = "cxx.rs")
+
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//tools/bazel:vendor.bzl", "vendor")
 
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index d026e0d..c7d07e8 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -34,7 +34,7 @@ def rust_cxx_bridge(name, src, deps = []):
             "-o",
             "$(location %s.cc)" % src,
         ],
-        tool = "//:codegen",
+        tool = "@cxx.rs//:codegen",
     )
 
     cc_library(

From 4bce6df73c44f836a3771e0642be86e94deeed8c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 01 2021 20:30:33 +0000
Subject: [PATCH 2080/2232] Merge pull request #700 from hlopko/name_the_workspace


Make rust_cxx_bridge usable from other repositories
---

diff --git a/WORKSPACE b/WORKSPACE
index e9b08ef..fde28ff 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,3 +1,5 @@
+workspace(name = "cxx.rs")
+
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//tools/bazel:vendor.bzl", "vendor")
 
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index d026e0d..c7d07e8 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -34,7 +34,7 @@ def rust_cxx_bridge(name, src, deps = []):
             "-o",
             "$(location %s.cc)" % src,
         ],
-        tool = "//:codegen",
+        tool = "@cxx.rs//:codegen",
     )
 
     cc_library(

From aa153ee92cc185c05dd6a42f680229b9a8bfe005 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 04 2021 05:15:07 +0000
Subject: [PATCH 2081/2232] Avoid bringing let_cxx_string's variable name into scope too early


Fixes #701.

---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 08a58b1..8834b49 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -71,10 +71,10 @@ pub struct CxxString {
 #[macro_export]
 macro_rules! let_cxx_string {
     ($var:ident = $value:expr $(,)?) => {
-        let mut $var = $crate::private::StackString::new();
+        let mut cxx_stack_string = $crate::private::StackString::new();
         #[allow(unused_mut, unused_unsafe)]
         let mut $var = match $value {
-            let_cxx_string => unsafe { $var.init(let_cxx_string) },
+            let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) },
         };
     };
 }

From 7d51573f8254845d6840be5e5aec583963bdb422 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Feb 05 2021 23:03:02 +0000
Subject: [PATCH 2082/2232] Merge branch 'master' of github.com:dtolnay/cxx into pointers


---

diff --git a/.devcontainer/build.Dockerfile b/.devcontainer/build.Dockerfile
index 6085459..f276388 100644
--- a/.devcontainer/build.Dockerfile
+++ b/.devcontainer/build.Dockerfile
@@ -5,7 +5,7 @@ RUN apt-get update \
     && apt-get -y install --no-install-recommends openjdk-11-jdk lld \
     && rustup default nightly 2>&1 \
     && rustup component add rust-analyzer-preview rustfmt clippy 2>&1 \
-    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh \
+    && wget -q -O bin/install-bazel https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh \
     && wget -q -O bin/buck https://jitpack.io/com/github/facebook/buck/a5f0342ae3/buck-a5f0342ae3-java11.pex \
     && wget -q -O bin/buildifier https://github.com/bazelbuild/buildtools/releases/latest/download/buildifier \
     && wget -q -O tmp/watchman.zip https://github.com/facebook/watchman/releases/download/v2020.09.21.00/watchman-v2020.09.21.00-linux.zip \
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9e1aef3..86f58a6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -84,7 +84,7 @@ jobs:
       - uses: actions/checkout@v2
       - name: Install Bazel
         run: |
-          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/2.1.1/bazel-2.1.1-installer-linux-x86_64.sh
+          wget -q -O install.sh https://github.com/bazelbuild/bazel/releases/download/4.0.0/bazel-4.0.0-installer-linux-x86_64.sh
           chmod +x install.sh
           ./install.sh --user
           echo $HOME/bin >> $GITHUB_PATH
diff --git a/Cargo.toml b/Cargo.toml
index 847d6c3..9df0230 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.28" # remember to update html_root_url
+version = "1.0.29" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.28", path = "macro" }
+cxxbridge-macro = { version = "=1.0.29", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.28", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.29", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.28", path = "gen/build" }
+cxx-build = { version = "=1.0.29", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/WORKSPACE b/WORKSPACE
index 039237b..fde28ff 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,38 +1,22 @@
+workspace(name = "cxx.rs")
+
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//tools/bazel:vendor.bzl", "vendor")
 
 http_archive(
-    name = "io_bazel_rules_rust",
-    sha256 = "5ed804fcd10a506a5b8e9e59bc6b3b7f43bc30c87ce4670e6f78df43604894fd",
-    strip_prefix = "rules_rust-fdf9655ba95616e0314b4e0ebab40bb0c5fe005c",
-    # Master branch as of 2020-07-30
-    url = "https://github.com/bazelbuild/rules_rust/archive/fdf9655ba95616e0314b4e0ebab40bb0c5fe005c.tar.gz",
-)
-
-http_archive(
-    name = "bazel_skylib",
-    sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
+    name = "rules_rust",
+    sha256 = "e6d835ee673f388aa5b62dc23d82db8fc76497e93fa47d8a4afe97abaf09b10d",
+    strip_prefix = "rules_rust-f37b9d6a552e9412285e627f30cb124e709f4f7a",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+        # Master branch as of 2021-01-27
+        "https://github.com/bazelbuild/rules_rust/archive/f37b9d6a552e9412285e627f30cb124e709f4f7a.tar.gz",
     ],
 )
 
-load("@io_bazel_rules_rust//:workspace.bzl", "bazel_version")
-
-bazel_version(name = "bazel_version")
-
-load("@io_bazel_rules_rust//rust:repositories.bzl", "rust_repository_set")
-
-rust_repository_set(
-    name = "rust_1_48_linux",
-    exec_triple = "x86_64-unknown-linux-gnu",
-    version = "1.48.0",
-)
+load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
-rust_repository_set(
-    name = "rust_1_48_darwin",
-    exec_triple = "x86_64-apple-darwin",
+rust_repositories(
+    edition = "2018",
     version = "1.48.0",
 )
 
diff --git a/book/src/async.md b/book/src/async.md
index 7574a22..b4c696a 100644
--- a/book/src/async.md
+++ b/book/src/async.md
@@ -60,7 +60,7 @@ pub async fn do_thing(arg: Arg) -> Ret {
 
     ffi::shim_doThing(
         arg,
-        |tx, ret| { let _ = tx.0.send(ret); },
+        |context, ret| { let _ = context.0.send(ret); },
         context,
     );
 
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 8a7b56f..117385a 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index fdcbe27..36c7a31 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -13,7 +13,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 lazy_static = "1.4"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index 204c89f..fda387d 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -71,7 +71,8 @@
     clippy::struct_excessive_bools,
     clippy::too_many_arguments,
     clippy::too_many_lines,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    clippy::upper_case_acronyms
 )]
 
 mod cfg;
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e518369..58e5bd1 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -17,7 +17,7 @@ path = "src/main.rs"
 
 [dependencies]
 clap = "2.33"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index c6da2ba..fd10605 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.28"
+version = "0.7.29"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -12,7 +12,7 @@ categories = ["development-tools::ffi"]
 
 [dependencies]
 cc = "1.0.49"
-codespan-reporting = "0.9"
+codespan-reporting = "0.11"
 proc-macro2 = { version = "1.0.17", default-features = false, features = ["span-locations"] }
 quote = { version = "1.0", default-features = false }
 syn = { version = "1.0.57", default-features = false, features = ["parsing", "printing", "clone-impls", "full"] }
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 02ed6c8..907d864 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.28"
+version = "1.0.29"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 578d624..1df0463 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -123,7 +123,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         #doc
         #attrs
         #[deny(improper_ctypes)]
-        #[allow(non_snake_case)]
+        #[allow(non_camel_case_types, non_snake_case, clippy::upper_case_acronyms)]
         #vis #mod_token #ident #expanded
     }
 }
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 10abbce..8834b49 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -71,10 +71,10 @@ pub struct CxxString {
 #[macro_export]
 macro_rules! let_cxx_string {
     ($var:ident = $value:expr $(,)?) => {
-        let mut $var = $crate::private::StackString::new();
+        let mut cxx_stack_string = $crate::private::StackString::new();
         #[allow(unused_mut, unused_unsafe)]
         let mut $var = match $value {
-            let_cxx_string => unsafe { $var.init(let_cxx_string) },
+            let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) },
         };
     };
 }
@@ -188,7 +188,7 @@ impl PartialEq<str> for CxxString {
 pub struct StackString {
     // Static assertions in cxx.cc validate that this is large enough and
     // aligned enough.
-    space: MaybeUninit<[*const (); 8]>,
+    space: MaybeUninit<[usize; 8]>,
 }
 
 impl StackString {
diff --git a/src/lib.rs b/src/lib.rs
index e7e769c..0f92253 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.28")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.29")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/tests/cxx_string.rs b/tests/cxx_string.rs
new file mode 100644
index 0000000..be693cd
--- /dev/null
+++ b/tests/cxx_string.rs
@@ -0,0 +1,15 @@
+use cxx::{let_cxx_string, CxxString};
+
+#[test]
+fn test_async_cxx_string() {
+    async fn f() {
+        let_cxx_string!(s = "...");
+
+        async fn g(_: &CxxString) {}
+        g(&s).await;
+    }
+
+    // https://github.com/dtolnay/cxx/issues/693
+    fn assert_send(_: impl Send) {}
+    assert_send(f());
+}
diff --git a/third-party/BUCK b/third-party/BUCK
index 2479558..d5a03c2 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -25,7 +25,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.58/src/**"]),
+    srcs = glob(["vendor/syn-1.0.60/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index a8e5622..c1ab800 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -1,10 +1,8 @@
 load(
     "//tools/bazel:rust.bzl",
     glob = "third_party_glob",
-    rust_binary = "third_party_rust_binary",
     rust_library = "third_party_rust_library",
 )
-load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
 
 rust_library(
     name = "bitflags",
@@ -31,7 +29,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.9.5/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
@@ -78,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.58/src/**"]),
+    srcs = glob(["vendor/syn-1.0.60/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ab40d00..5a8a4a1 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -49,9 +49,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.9.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e0762455306b1ed42bc651ef6a2197aabda5e1d4a43c34d5eab5c1a3634e81d"
+checksum = "c6ce42b8998a383572e0a802d859b1f00c79b7b7474e62fff88ee5c2845d9c13"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -59,7 +59,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +74,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +89,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.28"
+version = "0.7.29"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +120,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.28"
+version = "1.0.29"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.28"
+version = "1.0.29"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -154,9 +154,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.17"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
+checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
 dependencies = [
  "libc",
 ]
@@ -232,18 +232,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.119"
+version = "1.0.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bdd36f49e35b61d49efd8aa7fc068fd295961fd2286d0b2ee9a4c7a14e99cc3"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.119"
+version = "1.0.123"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "552954ce79a059ddd5fd68c271592374bd15cab2274970380c000118aeffe1cd"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -269,9 +269,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.58"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.38"
+version = "1.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b06f8610494cbeb9a7665b398306f0109ab8708296d7f24b0bcd89178bb350"
+checksum = "1c9594b802f041389d2baac680663573dde3103bb4a4926d61d6aba689465978"
 dependencies = [
  "dissimilar",
  "glob",
diff --git a/tools/bazel/BUILD b/tools/bazel/BUILD
index e69de29..d42fc71 100644
--- a/tools/bazel/BUILD
+++ b/tools/bazel/BUILD
@@ -0,0 +1,7 @@
+load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+
+bzl_library(
+    name = "bzl_srcs",
+    srcs = glob(["**/*.bzl"]),
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/bazel/rust.bzl b/tools/bazel/rust.bzl
index b7b23e5..9f71923 100644
--- a/tools/bazel/rust.bzl
+++ b/tools/bazel/rust.bzl
@@ -1,5 +1,7 @@
+"""A module wrapping the core rules of `rules_rust`"""
+
 load(
-    "@io_bazel_rules_rust//rust:rust.bzl",
+    "@rules_rust//rust:rust.bzl",
     _rust_binary = "rust_binary",
     _rust_library = "rust_library",
     _rust_test = "rust_test",
diff --git a/tools/bazel/rust_cxx_bridge.bzl b/tools/bazel/rust_cxx_bridge.bzl
index 534f6b5..c7d07e8 100644
--- a/tools/bazel/rust_cxx_bridge.bzl
+++ b/tools/bazel/rust_cxx_bridge.bzl
@@ -1,7 +1,15 @@
+# buildifier: disable=module-docstring
 load("@bazel_skylib//rules:run_binary.bzl", "run_binary")
 load("@rules_cc//cc:defs.bzl", "cc_library")
 
 def rust_cxx_bridge(name, src, deps = []):
+    """A macro defining a cxx bridge library
+
+    Args:
+        name (string): The name of the new target
+        src (string): The rust source file to generate a bridge for
+        deps (list, optional): A list of dependencies for the underlying cc_library. Defaults to [].
+    """
     native.alias(
         name = "%s/header" % name,
         actual = src + ".h",
@@ -26,7 +34,7 @@ def rust_cxx_bridge(name, src, deps = []):
             "-o",
             "$(location %s.cc)" % src,
         ],
-        tool = "//:codegen",
+        tool = "@cxx.rs//:codegen",
     )
 
     cc_library(
diff --git a/tools/bazel/vendor.bzl b/tools/bazel/vendor.bzl
index e9f10ac..e404ad9 100644
--- a/tools/bazel/vendor.bzl
+++ b/tools/bazel/vendor.bzl
@@ -1,3 +1,7 @@
+"""A module defining a repository rule for vendoring the dependencies
+of a crate in the current workspace.
+"""
+
 def _impl(repository_ctx):
     # Link cxx repository into @third-party.
     lockfile = repository_ctx.path(repository_ctx.attr.lockfile)
@@ -48,7 +52,12 @@ def _log_cargo_vendor(repository_ctx, result):
         repository_ctx.execute(print, quiet = False)
 
 vendor = repository_rule(
-    attrs = {"lockfile": attr.label()},
+    doc = "A rule used to vendor the dependencies of a crate in the current workspace",
+    attrs = {
+        "lockfile": attr.label(
+            doc = "A lockfile providing the set of crates to vendor",
+        ),
+    },
     local = True,
     implementation = _impl,
 )

From 8f16ecd896efb5ed7d5ed50b8b30966d4e207277 Mon Sep 17 00:00:00 2001
From: Evan Shaw <evan@vendhq.com>
Date: Feb 07 2021 08:55:33 +0000
Subject: [PATCH 2083/2232] Re-export cc's parallel feature for cxx-build


This allows building in parallel when the feature is enabled.

---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 36c7a31..98929db 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -11,6 +11,9 @@ exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
+[features]
+parallel = ["cc/parallel"]
+
 [dependencies]
 cc = "1.0.49"
 codespan-reporting = "0.11"

From 0aa3cac18f8e2abf43fd1bee08a53182cb19230b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 20:39:33 +0000
Subject: [PATCH 2084/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5a8a4a1..b6bdaa2 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -175,9 +175,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.82"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
 
 [[package]]
 name = "link-cplusplus"
@@ -252,9 +252,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.61"
+version = "1.0.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
+checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
 dependencies = [
  "itoa",
  "ryu",
@@ -307,9 +307,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.39"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c9594b802f041389d2baac680663573dde3103bb4a4926d61d6aba689465978"
+checksum = "6d954efdf324efc76ca06849b96cc484980e0e05e2eb8f3b2111354d6debea81"
 dependencies = [
  "dissimilar",
  "glob",

From 9a8ac6c41065cac66282b55b6245f4c6426d787b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 20:41:55 +0000
Subject: [PATCH 2085/2232] Merge pull request #704 from edsrzf/cxx-build-parallel


Re-export cc's parallel feature for cxx-build
---

diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 36c7a31..98929db 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -11,6 +11,9 @@ exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
+[features]
+parallel = ["cc/parallel"]
+
 [dependencies]
 cc = "1.0.49"
 codespan-reporting = "0.11"

From f545326fe8b190f65e9b5e6a8323b6c33c0cd91e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 20:42:42 +0000
Subject: [PATCH 2086/2232] Update lockfile for jobserver dependency from PR 704


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b6bdaa2..2470492 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -31,6 +31,9 @@ name = "cc"
 version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
+dependencies = [
+ "jobserver",
+]
 
 [[package]]
 name = "clap"
@@ -168,6 +171,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
 
 [[package]]
+name = "jobserver"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"

From 91a2d4a822f62d9471f6d9ce2b273cce335a422b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 20:48:19 +0000
Subject: [PATCH 2087/2232] Release 1.0.30


---

diff --git a/Cargo.toml b/Cargo.toml
index 9df0230..e5319a3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.29" # remember to update html_root_url
+version = "1.0.30" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.29", path = "macro" }
+cxxbridge-macro = { version = "=1.0.30", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.29", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.30", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.29", path = "gen/build" }
+cxx-build = { version = "=1.0.30", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 117385a..f6dab97 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.29"
+version = "1.0.30"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 98929db..c51afa9 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.29"
+version = "1.0.30"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 58e5bd1..a8d2bd5 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.29"
+version = "1.0.30"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index fd10605..96ca9e4 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.29"
+version = "0.7.30"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 907d864..9b75cff 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.29"
+version = "1.0.30"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 0f92253..50757c3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.29")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.30")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 2470492..8614e57 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -62,7 +62,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.29"
+version = "1.0.30"
 dependencies = [
  "cc",
  "cxx-build",
@@ -77,7 +77,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.29"
+version = "1.0.30"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -92,7 +92,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.29"
+version = "0.7.30"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -112,7 +112,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.29"
+version = "1.0.30"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -123,11 +123,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.29"
+version = "1.0.30"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.29"
+version = "1.0.30"
 dependencies = [
  "cxx",
  "proc-macro2",

From 14113b1c227fa621268eaf80d8b7c7b810bdfd8a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 21:34:56 +0000
Subject: [PATCH 2088/2232] Merge pull request #688 from fletcherw/enum_receiver


Clarify error for using enum as method receiver
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2098a1b..0aa3837 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -389,6 +389,8 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 mutability = mutability,
             );
             cx.error(span, msg);
+        } else if cx.types.enums.contains_key(&receiver.ty.rust) {
+            cx.error(span, "C++ does not allow member functions on enums");
         } else if !cx.types.structs.contains_key(&receiver.ty.rust)
             && !cx.types.cxx.contains(&receiver.ty.rust)
             && !cx.types.rust.contains(&receiver.ty.rust)
diff --git a/tests/ui/enum_receiver.rs b/tests/ui/enum_receiver.rs
new file mode 100644
index 0000000..a27f274
--- /dev/null
+++ b/tests/ui/enum_receiver.rs
@@ -0,0 +1,11 @@
+#[cxx::bridge]
+mod ffi {
+    enum Enum {
+        Variant,
+    }
+    extern "Rust" {
+        fn f(self: &Enum);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_receiver.stderr b/tests/ui/enum_receiver.stderr
new file mode 100644
index 0000000..8523c77
--- /dev/null
+++ b/tests/ui/enum_receiver.stderr
@@ -0,0 +1,5 @@
+error: C++ does not allow member functions on enums
+ --> $DIR/enum_receiver.rs:7:20
+  |
+7 |         fn f(self: &Enum);
+  |                    ^^^^^

From d15608434d9d9240c4f8ebf0c2ac2f74e626f709 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 21:36:35 +0000
Subject: [PATCH 2089/2232] Touch up error message from PR 688


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0aa3837..6228734 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -390,7 +390,10 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
             );
             cx.error(span, msg);
         } else if cx.types.enums.contains_key(&receiver.ty.rust) {
-            cx.error(span, "C++ does not allow member functions on enums");
+            cx.error(
+                span,
+                "unsupported receiver type; C++ does not allow member functions on enums",
+            );
         } else if !cx.types.structs.contains_key(&receiver.ty.rust)
             && !cx.types.cxx.contains(&receiver.ty.rust)
             && !cx.types.rust.contains(&receiver.ty.rust)
diff --git a/tests/ui/enum_receiver.stderr b/tests/ui/enum_receiver.stderr
index 8523c77..e09b4e3 100644
--- a/tests/ui/enum_receiver.stderr
+++ b/tests/ui/enum_receiver.stderr
@@ -1,4 +1,4 @@
-error: C++ does not allow member functions on enums
+error: unsupported receiver type; C++ does not allow member functions on enums
  --> $DIR/enum_receiver.rs:7:20
   |
 7 |         fn f(self: &Enum);

From 35f07dbdf855900f09080cb335cf5ebdf3af4a09 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 21:38:01 +0000
Subject: [PATCH 2090/2232] Avoid wrapping error message across source lines


This makes the source of the message easier to locate for someone using
grep with the full message.

The Linux kernel coding style follows the same approach:
https://www.kernel.org/doc/html/v5.10/process/coding-style.html#breaking-long-lines-and-strings

> never break user-visible strings such as printk messages because that
> breaks the ability to grep for them.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6228734..2aefbdf 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -383,9 +383,7 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 false => "",
             };
             let msg = format!(
-                "unnamed receiver type is only allowed if the surrounding \
-                 extern block contains exactly one extern type; \
-                 use `self: &{mutability}TheType`",
+                "unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &{mutability}TheType`",
                 mutability = mutability,
             );
             cx.error(span, msg);

From 1cb7e724c09cb18ef84e31b110921a3d878d3ff2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 07 2021 22:44:54 +0000
Subject: [PATCH 2091/2232] Expand type_id in same step as bridge expansion


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1df0463..86f0bb6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,6 +3,7 @@ use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
 use crate::syntax::instantiate::ImplKey;
+use crate::syntax::qualified::QualifiedName;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
@@ -1061,10 +1062,12 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
 }
 
 fn type_id(name: &Pair) -> TokenStream {
-    let path = name.to_fully_qualified();
-    quote! {
-        ::cxx::type_id!(#path)
-    }
+    let namespace_segments = name.namespace.iter();
+    let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
+    segments.extend(namespace_segments.cloned());
+    segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
+    let qualified = QualifiedName { segments };
+    crate::type_id::expand(qualified)
 }
 
 fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {

From 624bab91237c80a394c965794a07cca42eaf47dc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 06:45:31 +0000
Subject: [PATCH 2092/2232] Test Vec<usize> and Vec<isize> instantiation


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8ed5456..68ec544 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -817,6 +817,14 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(vec1[0] == 3 && vec1[1] == 4);
   ASSERT(vec2[0] == 1 && vec2[1] == 2);
 
+  // Test Vec<usize> and Vec<isize>. These are weird because on Linux and
+  // Windows size_t is exactly the same C++ type as one of the sized integer
+  // types (typically uint64_t, both of which are defined as unsigned long),
+  // while on macOS it is a distinct type.
+  // https://github.com/dtolnay/cxx/issues/705
+  (void)rust::Vec<size_t>();
+  (void)rust::Vec<rust::isize>();
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From 60f83590d7dc2a22eacda1532b49540dda48bbf5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 07:25:12 +0000
Subject: [PATCH 2093/2232] Add a specialization of Vec methods for macOS


---

diff --git a/src/cxx.cc b/src/cxx.cc
index 0dba805..fd34e34 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -413,6 +413,21 @@ union MaybeUninit {
 };
 } // namespace
 
+namespace detail {
+// On some platforms size_t is the same C++ type as one of the sized integer
+// types; on others it is a distinct type. Only in the latter case do we need to
+// define a specialized impl of rust::Vec<size_t>, because in the former case it
+// would collide with one of the other specializations.
+using usize_if_unique =
+    typename std::conditional<std::is_same<size_t, uint64_t>::value ||
+                                  std::is_same<size_t, uint32_t>::value,
+                              struct usize_ignore, size_t>::type;
+using isize_if_unique =
+    typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
+                                  std::is_same<rust::isize, int32_t>::value,
+                              struct isize_ignore, rust::isize>::type;
+} // namespace detail
+
 } // namespace cxxbridge1
 } // namespace rust
 
@@ -602,6 +617,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
+  MACRO(usize, rust::detail::usize_if_unique)                                  \
+  MACRO(isize, rust::detail::isize_if_unique)                                  \
   MACRO(string, rust::String)                                                  \
   MACRO(str, rust::Str)
 
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index bda1209..a26a156 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -68,10 +68,12 @@ rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
 rust_vec_shims_for_primitive!(u32);
 rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(usize);
 rust_vec_shims_for_primitive!(i8);
 rust_vec_shims_for_primitive!(i16);
 rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(isize);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
 

From 6024b5e5cf71311a9c4f542ee358723a10c7f4ca Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 07:40:48 +0000
Subject: [PATCH 2094/2232] Merge pull request #707 from dtolnay/vecsizet


Support for Vec<usize> and Vec<isize> on macOS
---

diff --git a/src/cxx.cc b/src/cxx.cc
index 0dba805..fd34e34 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -413,6 +413,21 @@ union MaybeUninit {
 };
 } // namespace
 
+namespace detail {
+// On some platforms size_t is the same C++ type as one of the sized integer
+// types; on others it is a distinct type. Only in the latter case do we need to
+// define a specialized impl of rust::Vec<size_t>, because in the former case it
+// would collide with one of the other specializations.
+using usize_if_unique =
+    typename std::conditional<std::is_same<size_t, uint64_t>::value ||
+                                  std::is_same<size_t, uint32_t>::value,
+                              struct usize_ignore, size_t>::type;
+using isize_if_unique =
+    typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
+                                  std::is_same<rust::isize, int32_t>::value,
+                              struct isize_ignore, rust::isize>::type;
+} // namespace detail
+
 } // namespace cxxbridge1
 } // namespace rust
 
@@ -602,6 +617,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
+  MACRO(usize, rust::detail::usize_if_unique)                                  \
+  MACRO(isize, rust::detail::isize_if_unique)                                  \
   MACRO(string, rust::String)                                                  \
   MACRO(str, rust::Str)
 
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index bda1209..a26a156 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -68,10 +68,12 @@ rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
 rust_vec_shims_for_primitive!(u32);
 rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(usize);
 rust_vec_shims_for_primitive!(i8);
 rust_vec_shims_for_primitive!(i16);
 rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(isize);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 8ed5456..68ec544 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -817,6 +817,14 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(vec1[0] == 3 && vec1[1] == 4);
   ASSERT(vec2[0] == 1 && vec2[1] == 2);
 
+  // Test Vec<usize> and Vec<isize>. These are weird because on Linux and
+  // Windows size_t is exactly the same C++ type as one of the sized integer
+  // types (typically uint64_t, both of which are defined as unsigned long),
+  // while on macOS it is a distinct type.
+  // https://github.com/dtolnay/cxx/issues/705
+  (void)rust::Vec<size_t>();
+  (void)rust::Vec<rust::isize>();
+
   cxx_test_suite_set_correct();
   return nullptr;
 }

From fb069b93093f99b9993faa725da169cf0bbfe948 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 07:41:29 +0000
Subject: [PATCH 2095/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8614e57..8048aa2 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -187,9 +187,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.85"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
 
 [[package]]
 name = "link-cplusplus"

From 29710fe93b14a7246fafcf438226953b95cbe91e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 07:45:12 +0000
Subject: [PATCH 2096/2232] Update bazel CI to use stable 1.49.0 compiler


---

diff --git a/WORKSPACE b/WORKSPACE
index fde28ff..8de7e1a 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,7 +17,7 @@ load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
 rust_repositories(
     edition = "2018",
-    version = "1.48.0",
+    version = "1.49.0",
 )
 
 vendor(

From f6e44208125ad4b5882514daadef0a742a52dc70 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 09 2021 07:49:20 +0000
Subject: [PATCH 2097/2232] Release 1.0.31


---

diff --git a/Cargo.toml b/Cargo.toml
index e5319a3..1f9d3d5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.30" # remember to update html_root_url
+version = "1.0.31" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.30", path = "macro" }
+cxxbridge-macro = { version = "=1.0.31", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.30", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.31", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.30", path = "gen/build" }
+cxx-build = { version = "=1.0.31", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index f6dab97..3452759 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.30"
+version = "1.0.31"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index c51afa9..ee8080b 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.30"
+version = "1.0.31"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index a8d2bd5..b993bab 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.30"
+version = "1.0.31"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 96ca9e4..ebcec64 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.30"
+version = "0.7.31"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 9b75cff..7b1e47c 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.30"
+version = "1.0.31"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 50757c3..018582d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.30")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.31")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 8048aa2..5c40d1e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -62,7 +62,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.30"
+version = "1.0.31"
 dependencies = [
  "cc",
  "cxx-build",
@@ -77,7 +77,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.30"
+version = "1.0.31"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -92,7 +92,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.30"
+version = "0.7.31"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -112,7 +112,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.30"
+version = "1.0.31"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -123,11 +123,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.30"
+version = "1.0.31"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.30"
+version = "1.0.31"
 dependencies = [
  "cxx",
  "proc-macro2",

From dfafc8b210dba7e9db8963985d683f44b8632ff3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:03:48 +0000
Subject: [PATCH 2098/2232] Move span of inherited pub to next consecutive token


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index fbb24e2..3dd09f5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -144,7 +144,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
                 continue;
             }
         };
-        let visibility = visibility_pub(&field.vis, &ident);
+        let visibility = visibility_pub(&field.vis, ident.span());
         let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
         fields.push(Var {
             doc,
@@ -155,8 +155,8 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
+    let visibility = visibility_pub(&item.vis, struct_token.span);
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: item.generics.lt_token,
@@ -219,8 +219,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
         }
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let enum_token = item.enum_token;
+    let visibility = visibility_pub(&item.vis, enum_token.span);
     let brace_token = item.brace_token;
 
     let explicit_repr = repr.is_some();
@@ -452,8 +452,8 @@ fn parse_extern_type(
         },
     );
 
-    let visibility = visibility_pub(&foreign_type.vis, &foreign_type.ident);
     let type_token = foreign_type.type_token;
+    let visibility = visibility_pub(&foreign_type.vis, type_token.span);
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: None,
@@ -619,9 +619,10 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
+    let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
+    let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -787,7 +788,7 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
@@ -867,7 +868,7 @@ fn parse_extern_type_bounded(
         },
     );
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -1326,12 +1327,12 @@ fn parse_return_type(
     }
 }
 
-fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
+fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
     Token![pub](match vis {
         Visibility::Public(vis) => vis.pub_token.span,
         Visibility::Crate(vis) => vis.crate_token.span,
         Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => inherited.span(),
+        Visibility::Inherited => inherited,
     })
 }
 
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 183aa5e..f43678f 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -2,7 +2,7 @@ error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 3  |     enum A {
-   |          - `ffi::A` defined here
+   |     ------ `ffi::A` defined here
 ...
 12 |     match a {
    |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered

From 47cb2bbccd87d6895162c1829568ab229a8649d7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:11:06 +0000
Subject: [PATCH 2099/2232] Merge pull request #710 from dtolnay/inherited


Move span of inherited pub to next consecutive token
---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index fbb24e2..3dd09f5 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -144,7 +144,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
                 continue;
             }
         };
-        let visibility = visibility_pub(&field.vis, &ident);
+        let visibility = visibility_pub(&field.vis, ident.span());
         let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
         fields.push(Var {
             doc,
@@ -155,8 +155,8 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
+    let visibility = visibility_pub(&item.vis, struct_token.span);
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: item.generics.lt_token,
@@ -219,8 +219,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
         }
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let enum_token = item.enum_token;
+    let visibility = visibility_pub(&item.vis, enum_token.span);
     let brace_token = item.brace_token;
 
     let explicit_repr = repr.is_some();
@@ -452,8 +452,8 @@ fn parse_extern_type(
         },
     );
 
-    let visibility = visibility_pub(&foreign_type.vis, &foreign_type.ident);
     let type_token = foreign_type.type_token;
+    let visibility = visibility_pub(&foreign_type.vis, type_token.span);
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: None,
@@ -619,9 +619,10 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
+    let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
+    let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -787,7 +788,7 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
@@ -867,7 +868,7 @@ fn parse_extern_type_bounded(
         },
     );
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -1326,12 +1327,12 @@ fn parse_return_type(
     }
 }
 
-fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
+fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
     Token![pub](match vis {
         Visibility::Public(vis) => vis.pub_token.span,
         Visibility::Crate(vis) => vis.crate_token.span,
         Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => inherited.span(),
+        Visibility::Inherited => inherited,
     })
 }
 
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 183aa5e..f43678f 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -2,7 +2,7 @@ error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 3  |     enum A {
-   |          - `ffi::A` defined here
+   |     ------ `ffi::A` defined here
 ...
 12 |     match a {
    |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered

From a91012640275e3e186a43a2efeb0fa090492d060 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:11:13 +0000
Subject: [PATCH 2100/2232] Add ui test of handwritten Drop for shared struct


---

diff --git a/tests/ui/drop_shared.rs b/tests/ui/drop_shared.rs
new file mode 100644
index 0000000..5e3de4a
--- /dev/null
+++ b/tests/ui/drop_shared.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        fd: i32,
+    }
+}
+
+impl Drop for ffi::Shared {
+    fn drop(&mut self) {
+        println!("close({})", self.fd);
+    }
+}
+
+fn main() {}

From 79ae1fa572909428925da341b821a27855c875aa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:11:13 +0000
Subject: [PATCH 2101/2232] Prevent handwritten Drop impl for shared struct on the Rust side


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 86f0bb6..235ffa0 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -43,6 +43,7 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
 fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
+    let mut forbid = TokenStream::new();
 
     for api in apis {
         if let Api::RustType(ety) = api {
@@ -57,6 +58,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
             Api::Struct(strct) => {
                 expanded.extend(expand_struct(strct));
                 hidden.extend(expand_struct_operators(strct));
+                forbid.extend(expand_struct_forbid_drop(strct));
             }
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -104,6 +106,10 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         }
     }
 
+    if !forbid.is_empty() {
+        hidden.extend(expand_forbid(forbid));
+    }
+
     // Work around https://github.com/rust-lang/rust/issues/67851.
     if !hidden.is_empty() {
         expanded.extend(quote! {
@@ -265,6 +271,15 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
     operators
 }
 
+fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let generics = &strct.generics;
+
+    quote! {
+        impl #generics self::Drop for super::#ident #generics {}
+    }
+}
+
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
@@ -786,6 +801,17 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_forbid(impls: TokenStream) -> TokenStream {
+    quote! {
+        mod forbid {
+            pub trait Drop {}
+            #[allow(drop_bounds)]
+            impl<T: ?::std::marker::Sized + ::std::ops::Drop> self::Drop for T {}
+            #impls
+        }
+    }
+}
+
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
     let local_name = match &efn.receiver {

From 894ad110420c8f1c6793dc335feb11573c1bc17c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:11:13 +0000
Subject: [PATCH 2102/2232] Update shared type drop test stderr file


---

diff --git a/tests/ui/drop_shared.stderr b/tests/ui/drop_shared.stderr
new file mode 100644
index 0000000..a215ddf
--- /dev/null
+++ b/tests/ui/drop_shared.stderr
@@ -0,0 +1,10 @@
+error[E0119]: conflicting implementations of trait `ffi::_::forbid::Drop` for type `ffi::Shared`:
+ --> $DIR/drop_shared.rs:1:1
+  |
+1 | #[cxx::bridge]
+  | ^^^^^^^^^^^^^^
+  | |
+  | first implementation here
+  | conflicting implementation for `ffi::Shared`
+  |
+  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From da9f1b947127d770e6592815f82c6985e3eab4b1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:11:13 +0000
Subject: [PATCH 2103/2232] Improve span of shared struct Drop error


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 235ffa0..639880d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -274,9 +274,11 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
 fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
     let ident = &strct.name.rust;
     let generics = &strct.generics;
+    let span = ident.span();
+    let impl_token = Token![impl](strct.visibility.span);
 
-    quote! {
-        impl #generics self::Drop for super::#ident #generics {}
+    quote_spanned! {span=>
+        #impl_token #generics self::Drop for super::#ident #generics {}
     }
 }
 
diff --git a/tests/ui/drop_shared.stderr b/tests/ui/drop_shared.stderr
index a215ddf..47db21e 100644
--- a/tests/ui/drop_shared.stderr
+++ b/tests/ui/drop_shared.stderr
@@ -1,10 +1,8 @@
 error[E0119]: conflicting implementations of trait `ffi::_::forbid::Drop` for type `ffi::Shared`:
- --> $DIR/drop_shared.rs:1:1
+ --> $DIR/drop_shared.rs:3:5
   |
 1 | #[cxx::bridge]
-  | ^^^^^^^^^^^^^^
-  | |
-  | first implementation here
-  | conflicting implementation for `ffi::Shared`
-  |
-  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+  | -------------- first implementation here
+2 | mod ffi {
+3 |     struct Shared {
+  |     ^^^^^^^^^^^^^ conflicting implementation for `ffi::Shared`

From 997e874a89d4e049d6634cb243482a4543f1ec17 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:17:34 +0000
Subject: [PATCH 2104/2232] Merge pull request #711 from dtolnay/drop


Disallow misleading Drop impl on shared types
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 86f0bb6..639880d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -43,6 +43,7 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
 fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
+    let mut forbid = TokenStream::new();
 
     for api in apis {
         if let Api::RustType(ety) = api {
@@ -57,6 +58,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
             Api::Struct(strct) => {
                 expanded.extend(expand_struct(strct));
                 hidden.extend(expand_struct_operators(strct));
+                forbid.extend(expand_struct_forbid_drop(strct));
             }
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -104,6 +106,10 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         }
     }
 
+    if !forbid.is_empty() {
+        hidden.extend(expand_forbid(forbid));
+    }
+
     // Work around https://github.com/rust-lang/rust/issues/67851.
     if !hidden.is_empty() {
         expanded.extend(quote! {
@@ -265,6 +271,17 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
     operators
 }
 
+fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let generics = &strct.generics;
+    let span = ident.span();
+    let impl_token = Token![impl](strct.visibility.span);
+
+    quote_spanned! {span=>
+        #impl_token #generics self::Drop for super::#ident #generics {}
+    }
+}
+
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
@@ -786,6 +803,17 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_forbid(impls: TokenStream) -> TokenStream {
+    quote! {
+        mod forbid {
+            pub trait Drop {}
+            #[allow(drop_bounds)]
+            impl<T: ?::std::marker::Sized + ::std::ops::Drop> self::Drop for T {}
+            #impls
+        }
+    }
+}
+
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
     let local_name = match &efn.receiver {
diff --git a/tests/ui/drop_shared.rs b/tests/ui/drop_shared.rs
new file mode 100644
index 0000000..5e3de4a
--- /dev/null
+++ b/tests/ui/drop_shared.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        fd: i32,
+    }
+}
+
+impl Drop for ffi::Shared {
+    fn drop(&mut self) {
+        println!("close({})", self.fd);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/drop_shared.stderr b/tests/ui/drop_shared.stderr
new file mode 100644
index 0000000..47db21e
--- /dev/null
+++ b/tests/ui/drop_shared.stderr
@@ -0,0 +1,8 @@
+error[E0119]: conflicting implementations of trait `ffi::_::forbid::Drop` for type `ffi::Shared`:
+ --> $DIR/drop_shared.rs:3:5
+  |
+1 | #[cxx::bridge]
+  | -------------- first implementation here
+2 | mod ffi {
+3 |     struct Shared {
+  |     ^^^^^^^^^^^^^ conflicting implementation for `ffi::Shared`

From b06ce54490b1fff9a910c8d42d7f9210bc0ff786 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:25:57 +0000
Subject: [PATCH 2105/2232] Move type_id re-export to wrapper macro_rules


---

diff --git a/src/lib.rs b/src/lib.rs
index 018582d..0bba6a2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -413,6 +413,7 @@ mod shared_ptr;
 #[path = "cxx_string.rs"]
 mod string;
 mod symbols;
+mod type_id;
 mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
@@ -429,11 +430,6 @@ pub use crate::vector::CxxVector;
 pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
-/// For use in impls of the `ExternType` trait. See [`ExternType`].
-///
-/// [`ExternType`]: trait.ExternType.html
-pub use cxxbridge_macro::type_id;
-
 /// Synonym for `CxxString`.
 ///
 /// To avoid confusion with Rust's standard library string you probably
@@ -466,6 +462,7 @@ pub mod private {
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorElement;
     pub use crate::weak_ptr::WeakPtrTarget;
+    pub use cxxbridge_macro::type_id;
 }
 
 mod actually_private {
diff --git a/src/type_id.rs b/src/type_id.rs
new file mode 100644
index 0000000..6d91e44
--- /dev/null
+++ b/src/type_id.rs
@@ -0,0 +1,9 @@
+/// For use in impls of the `ExternType` trait. See [`ExternType`].
+///
+/// [`ExternType`]: trait.ExternType.html
+#[macro_export]
+macro_rules! type_id {
+    ($($path:tt)*) => {
+        $crate::private::type_id! { $($path)* }
+    };
+}

From cedd85595ed417f109c08426ccf387f91d41129e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:29:07 +0000
Subject: [PATCH 2106/2232] Pass and parse $crate in type_id impl


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index fc7828b..b39de52 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -37,6 +37,7 @@ use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
 use proc_macro::TokenStream;
+use proc_macro2::TokenTree;
 use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
 
@@ -75,14 +76,19 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
 
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
-    struct TypeId(QualifiedName);
+    struct TypeId {
+        krate: TokenTree,
+        path: QualifiedName,
+    }
 
     impl Parse for TypeId {
         fn parse(input: ParseStream) -> Result<Self> {
-            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
+            let krate: TokenTree = input.parse()?;
+            let path = QualifiedName::parse_quoted_or_unquoted(input)?;
+            Ok(TypeId { krate, path })
         }
     }
 
     let arg = parse_macro_input!(input as TypeId);
-    type_id::expand(arg.0).into()
+    type_id::expand(arg.path).into()
 }
diff --git a/src/type_id.rs b/src/type_id.rs
index 6d91e44..bd2b4ea 100644
--- a/src/type_id.rs
+++ b/src/type_id.rs
@@ -4,6 +4,6 @@
 #[macro_export]
 macro_rules! type_id {
     ($($path:tt)*) => {
-        $crate::private::type_id! { $($path)* }
+        $crate::private::type_id! { $crate $($path)* }
     };
 }

From 3403ae85002d8e0679da47aa5345a3f6a0790575 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:34:50 +0000
Subject: [PATCH 2107/2232] Generalize $crate parse to Crate enum


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index b39de52..28c8a1b 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -36,8 +36,8 @@ mod type_id;
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
+use crate::type_id::Crate;
 use proc_macro::TokenStream;
-use proc_macro2::TokenTree;
 use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
 
@@ -77,13 +77,13 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
     struct TypeId {
-        krate: TokenTree,
+        krate: Crate,
         path: QualifiedName,
     }
 
     impl Parse for TypeId {
         fn parse(input: ParseStream) -> Result<Self> {
-            let krate: TokenTree = input.parse()?;
+            let krate = input.parse().map(Crate::DollarCrate)?;
             let path = QualifiedName::parse_quoted_or_unquoted(input)?;
             Ok(TypeId { krate, path })
         }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 5c5d9cc..23df13e 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,7 +1,12 @@
 use crate::syntax::qualified::QualifiedName;
-use proc_macro2::TokenStream;
+use proc_macro2::{TokenStream, TokenTree};
 use quote::{format_ident, quote};
 
+pub enum Crate {
+    Cxx,
+    DollarCrate(TokenTree),
+}
+
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
 pub fn expand(arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();

From c28f77e2e4a29040495561629379c404bcc15865 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:37:15 +0000
Subject: [PATCH 2108/2232] Insert $crate into type_id macro expansion


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 639880d..f88b602 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -10,6 +10,7 @@ use crate::syntax::{
     self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
     Struct, Trait, Type, TypeAlias, Types,
 };
+use crate::type_id::Crate;
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
@@ -1095,7 +1096,7 @@ fn type_id(name: &Pair) -> TokenStream {
     segments.extend(namespace_segments.cloned());
     segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
     let qualified = QualifiedName { segments };
-    crate::type_id::expand(qualified)
+    crate::type_id::expand(Crate::Cxx, qualified)
 }
 
 fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 28c8a1b..7894f30 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -90,5 +90,5 @@ pub fn type_id(input: TokenStream) -> TokenStream {
     }
 
     let arg = parse_macro_input!(input as TypeId);
-    type_id::expand(arg.path).into()
+    type_id::expand(arg.krate, arg.path).into()
 }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 23df13e..74f0c1c 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,14 +1,23 @@
 use crate::syntax::qualified::QualifiedName;
 use proc_macro2::{TokenStream, TokenTree};
-use quote::{format_ident, quote};
+use quote::{format_ident, quote, ToTokens};
 
 pub enum Crate {
     Cxx,
     DollarCrate(TokenTree),
 }
 
+impl ToTokens for Crate {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        match self {
+            Crate::Cxx => tokens.extend(quote!(::cxx)),
+            Crate::DollarCrate(krate) => krate.to_tokens(tokens),
+        }
+    }
+}
+
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
-pub fn expand(arg: QualifiedName) -> TokenStream {
+pub fn expand(krate: Crate, arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();
 
     for word in arg.segments {
@@ -19,11 +28,11 @@ pub fn expand(arg: QualifiedName) -> TokenStream {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 '0'..='9' | '_' => {
                     let t = format_ident!("_{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 _ => quote!([(); #ch as _]),
             });

From 12fced438b40455087f3099da25dcf3261b8f660 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:40:04 +0000
Subject: [PATCH 2109/2232] Hide underlying type_id proc macro from rustdoc


---

diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 7894f30..a92eae7 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -74,6 +74,7 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .into()
 }
 
+#[doc(hidden)]
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
     struct TypeId {

From 87ed59475df2b48ec38e2f45027b1f66f15dae83 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 06:46:25 +0000
Subject: [PATCH 2110/2232] Merge pull request #712 from dtolnay/crate


Enable expanding type_id macro in a crate with cxx renamed
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 639880d..f88b602 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -10,6 +10,7 @@ use crate::syntax::{
     self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
     Struct, Trait, Type, TypeAlias, Types,
 };
+use crate::type_id::Crate;
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
@@ -1095,7 +1096,7 @@ fn type_id(name: &Pair) -> TokenStream {
     segments.extend(namespace_segments.cloned());
     segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
     let qualified = QualifiedName { segments };
-    crate::type_id::expand(qualified)
+    crate::type_id::expand(Crate::Cxx, qualified)
 }
 
 fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index fc7828b..a92eae7 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -36,6 +36,7 @@ mod type_id;
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
+use crate::type_id::Crate;
 use proc_macro::TokenStream;
 use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
@@ -73,16 +74,22 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .into()
 }
 
+#[doc(hidden)]
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
-    struct TypeId(QualifiedName);
+    struct TypeId {
+        krate: Crate,
+        path: QualifiedName,
+    }
 
     impl Parse for TypeId {
         fn parse(input: ParseStream) -> Result<Self> {
-            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
+            let krate = input.parse().map(Crate::DollarCrate)?;
+            let path = QualifiedName::parse_quoted_or_unquoted(input)?;
+            Ok(TypeId { krate, path })
         }
     }
 
     let arg = parse_macro_input!(input as TypeId);
-    type_id::expand(arg.0).into()
+    type_id::expand(arg.krate, arg.path).into()
 }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 5c5d9cc..74f0c1c 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,9 +1,23 @@
 use crate::syntax::qualified::QualifiedName;
-use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
+use proc_macro2::{TokenStream, TokenTree};
+use quote::{format_ident, quote, ToTokens};
+
+pub enum Crate {
+    Cxx,
+    DollarCrate(TokenTree),
+}
+
+impl ToTokens for Crate {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        match self {
+            Crate::Cxx => tokens.extend(quote!(::cxx)),
+            Crate::DollarCrate(krate) => krate.to_tokens(tokens),
+        }
+    }
+}
 
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
-pub fn expand(arg: QualifiedName) -> TokenStream {
+pub fn expand(krate: Crate, arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();
 
     for word in arg.segments {
@@ -14,11 +28,11 @@ pub fn expand(arg: QualifiedName) -> TokenStream {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 '0'..='9' | '_' => {
                     let t = format_ident!("_{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 _ => quote!([(); #ch as _]),
             });
diff --git a/src/lib.rs b/src/lib.rs
index 018582d..0bba6a2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -413,6 +413,7 @@ mod shared_ptr;
 #[path = "cxx_string.rs"]
 mod string;
 mod symbols;
+mod type_id;
 mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
@@ -429,11 +430,6 @@ pub use crate::vector::CxxVector;
 pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
-/// For use in impls of the `ExternType` trait. See [`ExternType`].
-///
-/// [`ExternType`]: trait.ExternType.html
-pub use cxxbridge_macro::type_id;
-
 /// Synonym for `CxxString`.
 ///
 /// To avoid confusion with Rust's standard library string you probably
@@ -466,6 +462,7 @@ pub mod private {
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorElement;
     pub use crate::weak_ptr::WeakPtrTarget;
+    pub use cxxbridge_macro::type_id;
 }
 
 mod actually_private {
diff --git a/src/type_id.rs b/src/type_id.rs
new file mode 100644
index 0000000..bd2b4ea
--- /dev/null
+++ b/src/type_id.rs
@@ -0,0 +1,9 @@
+/// For use in impls of the `ExternType` trait. See [`ExternType`].
+///
+/// [`ExternType`]: trait.ExternType.html
+#[macro_export]
+macro_rules! type_id {
+    ($($path:tt)*) => {
+        $crate::private::type_id! { $crate $($path)* }
+    };
+}

From 7bc397cac0f58476b34d20c5d06d8313602071ab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 07:07:58 +0000
Subject: [PATCH 2111/2232] Remove this != &other checks from move assignment operators


---

diff --git a/include/cxx.h b/include/cxx.h
index b9749de..0744f8c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -824,11 +824,9 @@ Vec<T>::~Vec() noexcept {
 
 template <typename T>
 Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
-  if (this != &other) {
-    this->drop();
-    this->repr = other.repr;
-    new (&other) Vec();
-  }
+  this->drop();
+  this->repr = other.repr;
+  new (&other) Vec();
   return *this;
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index fd34e34..2e4e0a0 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -109,11 +109,9 @@ String &String::operator=(const String &other) noexcept {
 }
 
 String &String::operator=(String &&other) noexcept {
-  if (this != &other) {
-    cxxbridge1$string$drop(this);
-    this->repr = other.repr;
-    cxxbridge1$string$new(&other);
-  }
+  cxxbridge1$string$drop(this);
+  this->repr = other.repr;
+  cxxbridge1$string$new(&other);
   return *this;
 }
 
@@ -392,13 +390,11 @@ Error &Error::operator=(const Error &other) {
 }
 
 Error &Error::operator=(Error &&other) noexcept {
-  if (this != &other) {
-    std::exception::operator=(std::move(other));
-    this->msg = other.msg;
-    this->len = other.len;
-    other.msg = nullptr;
-    other.len = 0;
-  }
+  std::exception::operator=(std::move(other));
+  this->msg = other.msg;
+  this->len = other.len;
+  other.msg = nullptr;
+  other.len = 0;
   return *this;
 }
 

From 19b488c286d99c986b34bfc152e19b68b67c1a02 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 07:16:43 +0000
Subject: [PATCH 2112/2232] Merge pull request #713 from dtolnay/selfmove


Remove self assignment checks from move assignment operators
---

diff --git a/include/cxx.h b/include/cxx.h
index b9749de..0744f8c 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -824,11 +824,9 @@ Vec<T>::~Vec() noexcept {
 
 template <typename T>
 Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
-  if (this != &other) {
-    this->drop();
-    this->repr = other.repr;
-    new (&other) Vec();
-  }
+  this->drop();
+  this->repr = other.repr;
+  new (&other) Vec();
   return *this;
 }
 
diff --git a/src/cxx.cc b/src/cxx.cc
index fd34e34..2e4e0a0 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -109,11 +109,9 @@ String &String::operator=(const String &other) noexcept {
 }
 
 String &String::operator=(String &&other) noexcept {
-  if (this != &other) {
-    cxxbridge1$string$drop(this);
-    this->repr = other.repr;
-    cxxbridge1$string$new(&other);
-  }
+  cxxbridge1$string$drop(this);
+  this->repr = other.repr;
+  cxxbridge1$string$new(&other);
   return *this;
 }
 
@@ -392,13 +390,11 @@ Error &Error::operator=(const Error &other) {
 }
 
 Error &Error::operator=(Error &&other) noexcept {
-  if (this != &other) {
-    std::exception::operator=(std::move(other));
-    this->msg = other.msg;
-    this->len = other.len;
-    other.msg = nullptr;
-    other.len = 0;
-  }
+  std::exception::operator=(std::move(other));
+  this->msg = other.msg;
+  this->len = other.len;
+  other.msg = nullptr;
+  other.len = 0;
   return *this;
 }
 

From 63bec405990a204a987a87d25d174e03c1164eb5 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 07:19:16 +0000
Subject: [PATCH 2113/2232] Disallow assignment to rvalue


---

diff --git a/include/cxx.h b/include/cxx.h
index 0744f8c..654b176 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -44,8 +44,8 @@ public:
   String(const char *);
   String(const char *, std::size_t);
 
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
+  String &operator=(const String &) & noexcept;
+  String &operator=(String &&) & noexcept;
 
   explicit operator std::string() const;
 
@@ -97,7 +97,7 @@ public:
   Str(const char *);
   Str(const char *, std::size_t);
 
-  Str &operator=(const Str &) noexcept = default;
+  Str &operator=(const Str &) & noexcept = default;
 
   explicit operator std::string() const;
 
@@ -144,8 +144,8 @@ template <>
 struct copy_assignable_if<false> {
   copy_assignable_if() noexcept = default;
   copy_assignable_if(const copy_assignable_if &) noexcept = default;
-  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
-  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;
 };
 } // namespace detail
 
@@ -159,8 +159,8 @@ public:
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 
-  Slice &operator=(const Slice<T> &) noexcept = default;
-  Slice &operator=(Slice<T> &&) noexcept = default;
+  Slice &operator=(const Slice<T> &) & noexcept = default;
+  Slice &operator=(Slice<T> &&) & noexcept = default;
 
   T *data() const noexcept;
   std::size_t size() const noexcept;
@@ -248,7 +248,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(Box &&) noexcept;
+  Box &operator=(Box &&) & noexcept;
 
   const T *operator->() const noexcept;
   const T &operator*() const noexcept;
@@ -293,8 +293,8 @@ public:
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
-  Vec &operator=(Vec &&) noexcept;
-  Vec &operator=(const Vec &);
+  Vec &operator=(Vec &&) & noexcept;
+  Vec &operator=(const Vec &) &;
 
   std::size_t size() const noexcept;
   bool empty() const noexcept;
@@ -371,8 +371,8 @@ public:
   Error(Error &&) noexcept;
   ~Error() noexcept override;
 
-  Error &operator=(const Error &);
-  Error &operator=(Error &&) noexcept;
+  Error &operator=(const Error &) &;
+  Error &operator=(Error &&) & noexcept;
 
   const char *what() const noexcept override;
 
@@ -735,7 +735,7 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(Box &&other) noexcept {
+Box<T> &Box<T>::operator=(Box &&other) & noexcept {
   if (this->ptr) {
     this->drop();
   }
@@ -823,7 +823,7 @@ Vec<T>::~Vec() noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
+Vec<T> &Vec<T>::operator=(Vec &&other) & noexcept {
   this->drop();
   this->repr = other.repr;
   new (&other) Vec();
@@ -831,7 +831,7 @@ Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(const Vec &other) {
+Vec<T> &Vec<T>::operator=(const Vec &other) & {
   if (this != &other) {
     this->drop();
     new (this) Vec(other);
diff --git a/src/cxx.cc b/src/cxx.cc
index 2e4e0a0..0f87bfe 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -100,7 +100,7 @@ String::String(const char *s, std::size_t len) {
              len);
 }
 
-String &String::operator=(const String &other) noexcept {
+String &String::operator=(const String &other) & noexcept {
   if (this != &other) {
     cxxbridge1$string$drop(this);
     cxxbridge1$string$clone(this, other);
@@ -108,7 +108,7 @@ String &String::operator=(const String &other) noexcept {
   return *this;
 }
 
-String &String::operator=(String &&other) noexcept {
+String &String::operator=(String &&other) & noexcept {
   cxxbridge1$string$drop(this);
   this->repr = other.repr;
   cxxbridge1$string$new(&other);
@@ -376,7 +376,7 @@ Error::Error(Error &&other) noexcept
 
 Error::~Error() noexcept { delete[] this->msg; }
 
-Error &Error::operator=(const Error &other) {
+Error &Error::operator=(const Error &other) & {
   if (this != &other) {
     std::exception::operator=(other);
     delete[] this->msg;
@@ -389,7 +389,7 @@ Error &Error::operator=(const Error &other) {
   return *this;
 }
 
-Error &Error::operator=(Error &&other) noexcept {
+Error &Error::operator=(Error &&other) & noexcept {
   std::exception::operator=(std::move(other));
   this->msg = other.msg;
   this->len = other.len;

From d3cb1148da3fe6d5bf72ac0649e4ef5b36427cac Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 12 2021 07:24:27 +0000
Subject: [PATCH 2114/2232] Merge pull request #714 from dtolnay/rvalue-assign


Disallow assignment to rvalue
---

diff --git a/include/cxx.h b/include/cxx.h
index 0744f8c..654b176 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -44,8 +44,8 @@ public:
   String(const char *);
   String(const char *, std::size_t);
 
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
+  String &operator=(const String &) & noexcept;
+  String &operator=(String &&) & noexcept;
 
   explicit operator std::string() const;
 
@@ -97,7 +97,7 @@ public:
   Str(const char *);
   Str(const char *, std::size_t);
 
-  Str &operator=(const Str &) noexcept = default;
+  Str &operator=(const Str &) & noexcept = default;
 
   explicit operator std::string() const;
 
@@ -144,8 +144,8 @@ template <>
 struct copy_assignable_if<false> {
   copy_assignable_if() noexcept = default;
   copy_assignable_if(const copy_assignable_if &) noexcept = default;
-  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
-  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;
 };
 } // namespace detail
 
@@ -159,8 +159,8 @@ public:
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 
-  Slice &operator=(const Slice<T> &) noexcept = default;
-  Slice &operator=(Slice<T> &&) noexcept = default;
+  Slice &operator=(const Slice<T> &) & noexcept = default;
+  Slice &operator=(Slice<T> &&) & noexcept = default;
 
   T *data() const noexcept;
   std::size_t size() const noexcept;
@@ -248,7 +248,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(Box &&) noexcept;
+  Box &operator=(Box &&) & noexcept;
 
   const T *operator->() const noexcept;
   const T &operator*() const noexcept;
@@ -293,8 +293,8 @@ public:
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
-  Vec &operator=(Vec &&) noexcept;
-  Vec &operator=(const Vec &);
+  Vec &operator=(Vec &&) & noexcept;
+  Vec &operator=(const Vec &) &;
 
   std::size_t size() const noexcept;
   bool empty() const noexcept;
@@ -371,8 +371,8 @@ public:
   Error(Error &&) noexcept;
   ~Error() noexcept override;
 
-  Error &operator=(const Error &);
-  Error &operator=(Error &&) noexcept;
+  Error &operator=(const Error &) &;
+  Error &operator=(Error &&) & noexcept;
 
   const char *what() const noexcept override;
 
@@ -735,7 +735,7 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(Box &&other) noexcept {
+Box<T> &Box<T>::operator=(Box &&other) & noexcept {
   if (this->ptr) {
     this->drop();
   }
@@ -823,7 +823,7 @@ Vec<T>::~Vec() noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
+Vec<T> &Vec<T>::operator=(Vec &&other) & noexcept {
   this->drop();
   this->repr = other.repr;
   new (&other) Vec();
@@ -831,7 +831,7 @@ Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(const Vec &other) {
+Vec<T> &Vec<T>::operator=(const Vec &other) & {
   if (this != &other) {
     this->drop();
     new (this) Vec(other);
diff --git a/src/cxx.cc b/src/cxx.cc
index 2e4e0a0..0f87bfe 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -100,7 +100,7 @@ String::String(const char *s, std::size_t len) {
              len);
 }
 
-String &String::operator=(const String &other) noexcept {
+String &String::operator=(const String &other) & noexcept {
   if (this != &other) {
     cxxbridge1$string$drop(this);
     cxxbridge1$string$clone(this, other);
@@ -108,7 +108,7 @@ String &String::operator=(const String &other) noexcept {
   return *this;
 }
 
-String &String::operator=(String &&other) noexcept {
+String &String::operator=(String &&other) & noexcept {
   cxxbridge1$string$drop(this);
   this->repr = other.repr;
   cxxbridge1$string$new(&other);
@@ -376,7 +376,7 @@ Error::Error(Error &&other) noexcept
 
 Error::~Error() noexcept { delete[] this->msg; }
 
-Error &Error::operator=(const Error &other) {
+Error &Error::operator=(const Error &other) & {
   if (this != &other) {
     std::exception::operator=(other);
     delete[] this->msg;
@@ -389,7 +389,7 @@ Error &Error::operator=(const Error &other) {
   return *this;
 }
 
-Error &Error::operator=(Error &&other) noexcept {
+Error &Error::operator=(Error &&other) & noexcept {
   std::exception::operator=(std::move(other));
   this->msg = other.msg;
   this->len = other.len;

From de4e10cc7a5e0591225153db45986b5ff84598e1 Mon Sep 17 00:00:00 2001
From: Jan Staněk <jstanek@redhat.com>
Date: Feb 15 2021 10:30:55 +0000
Subject: [PATCH 2115/2232] Include license files in flags crate


Other crates in this repo already include them,
and it is a requirement (or at least a strong suggestion)
for packaging it into Fedora.

---

diff --git a/flags/LICENSE-APACHE b/flags/LICENSE-APACHE
new file mode 120000
index 0000000..965b606
--- /dev/null
+++ b/flags/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE
\ No newline at end of file
diff --git a/flags/LICENSE-MIT b/flags/LICENSE-MIT
new file mode 120000
index 0000000..76219eb
--- /dev/null
+++ b/flags/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT
\ No newline at end of file

From efd852d9156b311896615a1cd9d666630a780d09 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 15 2021 17:24:03 +0000
Subject: [PATCH 2116/2232] Merge pull request #717 from khardix/master


Include license files in flags crate
---

diff --git a/flags/LICENSE-APACHE b/flags/LICENSE-APACHE
new file mode 120000
index 0000000..965b606
--- /dev/null
+++ b/flags/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE
\ No newline at end of file
diff --git a/flags/LICENSE-MIT b/flags/LICENSE-MIT
new file mode 120000
index 0000000..76219eb
--- /dev/null
+++ b/flags/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT
\ No newline at end of file

From 6e3a8639fd5f394a080b578e5eeae60539c5cd54 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 16 2021 21:21:50 +0000
Subject: [PATCH 2117/2232] Hide Id associated types from ExternType impl rustdocs


This eliminates a quite large amount of unhelpful noise from https://docs.rs/cxx/1/cxx/trait.ExternType.html.

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index f88b602..6d414c3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -170,6 +170,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         #struct_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
@@ -330,6 +331,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         }
 
         unsafe impl ::cxx::ExternType for #ident {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
@@ -370,6 +372,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
         #extern_type_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Opaque;
         }
@@ -739,6 +742,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
             let span = derive.span;
             impls.extend(quote_spanned! {span=>
                 unsafe impl #generics ::cxx::ExternType for #ident #generics {
+                    #[doc(hidden)]
                     type Id = #type_id;
                     type Kind = ::cxx::kind::Opaque;
                 }
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 99e0cb1..35057ac 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -188,6 +188,7 @@ macro_rules! impl_extern_type {
     ($([$kind:ident] $($ty:path = $cxxpath:literal)*)*) => {
         $($(
             unsafe impl ExternType for $ty {
+                #[doc(hidden)]
                 type Id = crate::type_id!($cxxpath);
                 type Kind = $kind;
             }

From f9b5fe47408e9bbe6d25f41bcc986e0355ed2fd2 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 16 2021 21:26:18 +0000
Subject: [PATCH 2118/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index d5a03c2..bef999d 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -57,7 +57,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.8/src/**"]),
+    srcs = glob(["vendor/quote-1.0.9/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
diff --git a/third-party/BUILD b/third-party/BUILD
index c1ab800..9781d98 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -61,7 +61,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.8/src/**"]),
+    srcs = glob(["vendor/quote-1.0.9/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5c40d1e..bd9c79d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -1,5 +1,7 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "ansi_term"
 version = "0.11.0"
@@ -217,9 +219,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
 dependencies = [
  "proc-macro2",
 ]
@@ -319,9 +321,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.40"
+version = "1.0.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d954efdf324efc76ca06849b96cc484980e0e05e2eb8f3b2111354d6debea81"
+checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b"
 dependencies = [
  "dissimilar",
  "glob",

From 72d47c95a02fd22723aeac7d0893673dbac98488 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 16 2021 21:31:41 +0000
Subject: [PATCH 2119/2232] Release 1.0.32


---

diff --git a/Cargo.toml b/Cargo.toml
index 1f9d3d5..357eb05 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.31" # remember to update html_root_url
+version = "1.0.32" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.31", path = "macro" }
+cxxbridge-macro = { version = "=1.0.32", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.31", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.32", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.31", path = "gen/build" }
+cxx-build = { version = "=1.0.32", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 3452759..6bd957e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.31"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index ee8080b..74e7b2a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.31"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index b993bab..a62eab8 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.31"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index ebcec64..be389fe 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.31"
+version = "0.7.32"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 7b1e47c..c17f010 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.31"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 0bba6a2..906d951 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.31")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.32")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index bd9c79d..23f34b0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.31"
+version = "1.0.32"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.31"
+version = "1.0.32"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.31"
+version = "0.7.32"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.31"
+version = "1.0.32"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.31"
+version = "1.0.32"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.31"
+version = "1.0.32"
 dependencies = [
  "cxx",
  "proc-macro2",

From f67287db6fe884691f41e4bf285626d3e3c8e236 Mon Sep 17 00:00:00 2001
From: adetaylor <adetaylor@chromium.org>
Date: Feb 17 2021 23:32:06 +0000
Subject: [PATCH 2120/2232] Merge branch 'master' into pointers


---

diff --git a/Cargo.toml b/Cargo.toml
index 9df0230..357eb05 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.29" # remember to update html_root_url
+version = "1.0.32" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.29", path = "macro" }
+cxxbridge-macro = { version = "=1.0.32", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.29", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.32", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.29", path = "gen/build" }
+cxx-build = { version = "=1.0.32", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/WORKSPACE b/WORKSPACE
index fde28ff..8de7e1a 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,7 +17,7 @@ load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
 rust_repositories(
     edition = "2018",
-    version = "1.48.0",
+    version = "1.49.0",
 )
 
 vendor(
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 117385a..6bd957e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.29"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/flags/LICENSE-APACHE b/flags/LICENSE-APACHE
new file mode 120000
index 0000000..965b606
--- /dev/null
+++ b/flags/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE
\ No newline at end of file
diff --git a/flags/LICENSE-MIT b/flags/LICENSE-MIT
new file mode 120000
index 0000000..76219eb
--- /dev/null
+++ b/flags/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT
\ No newline at end of file
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 36c7a31..74e7b2a 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.29"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
@@ -11,6 +11,9 @@ exclude = ["build.rs"]
 keywords = ["ffi"]
 categories = ["development-tools::ffi"]
 
+[features]
+parallel = ["cc/parallel"]
+
 [dependencies]
 cc = "1.0.49"
 codespan-reporting = "0.11"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 58e5bd1..a62eab8 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.29"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index fd10605..be389fe 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.29"
+version = "0.7.32"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/include/cxx.h b/include/cxx.h
index b9749de..654b176 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -44,8 +44,8 @@ public:
   String(const char *);
   String(const char *, std::size_t);
 
-  String &operator=(const String &) noexcept;
-  String &operator=(String &&) noexcept;
+  String &operator=(const String &) & noexcept;
+  String &operator=(String &&) & noexcept;
 
   explicit operator std::string() const;
 
@@ -97,7 +97,7 @@ public:
   Str(const char *);
   Str(const char *, std::size_t);
 
-  Str &operator=(const Str &) noexcept = default;
+  Str &operator=(const Str &) & noexcept = default;
 
   explicit operator std::string() const;
 
@@ -144,8 +144,8 @@ template <>
 struct copy_assignable_if<false> {
   copy_assignable_if() noexcept = default;
   copy_assignable_if(const copy_assignable_if &) noexcept = default;
-  copy_assignable_if &operator=(const copy_assignable_if &) noexcept = delete;
-  copy_assignable_if &operator=(copy_assignable_if &&) noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;
 };
 } // namespace detail
 
@@ -159,8 +159,8 @@ public:
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 
-  Slice &operator=(const Slice<T> &) noexcept = default;
-  Slice &operator=(Slice<T> &&) noexcept = default;
+  Slice &operator=(const Slice<T> &) & noexcept = default;
+  Slice &operator=(Slice<T> &&) & noexcept = default;
 
   T *data() const noexcept;
   std::size_t size() const noexcept;
@@ -248,7 +248,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(Box &&) noexcept;
+  Box &operator=(Box &&) & noexcept;
 
   const T *operator->() const noexcept;
   const T &operator*() const noexcept;
@@ -293,8 +293,8 @@ public:
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
-  Vec &operator=(Vec &&) noexcept;
-  Vec &operator=(const Vec &);
+  Vec &operator=(Vec &&) & noexcept;
+  Vec &operator=(const Vec &) &;
 
   std::size_t size() const noexcept;
   bool empty() const noexcept;
@@ -371,8 +371,8 @@ public:
   Error(Error &&) noexcept;
   ~Error() noexcept override;
 
-  Error &operator=(const Error &);
-  Error &operator=(Error &&) noexcept;
+  Error &operator=(const Error &) &;
+  Error &operator=(Error &&) & noexcept;
 
   const char *what() const noexcept override;
 
@@ -735,7 +735,7 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(Box &&other) noexcept {
+Box<T> &Box<T>::operator=(Box &&other) & noexcept {
   if (this->ptr) {
     this->drop();
   }
@@ -823,17 +823,15 @@ Vec<T>::~Vec() noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(Vec &&other) noexcept {
-  if (this != &other) {
-    this->drop();
-    this->repr = other.repr;
-    new (&other) Vec();
-  }
+Vec<T> &Vec<T>::operator=(Vec &&other) & noexcept {
+  this->drop();
+  this->repr = other.repr;
+  new (&other) Vec();
   return *this;
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(const Vec &other) {
+Vec<T> &Vec<T>::operator=(const Vec &other) & {
   if (this != &other) {
     this->drop();
     new (this) Vec(other);
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 907d864..c17f010 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.29"
+version = "1.0.32"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1df0463..6d414c3 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,12 +3,14 @@ use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
 use crate::syntax::instantiate::ImplKey;
+use crate::syntax::qualified::QualifiedName;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
     self, check, mangle, Api, Doc, Enum, ExternFn, ExternType, Impl, Lifetimes, Pair, Signature,
     Struct, Trait, Type, TypeAlias, Types,
 };
+use crate::type_id::Crate;
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
@@ -42,6 +44,7 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
 fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types) -> TokenStream {
     let mut expanded = TokenStream::new();
     let mut hidden = TokenStream::new();
+    let mut forbid = TokenStream::new();
 
     for api in apis {
         if let Api::RustType(ety) = api {
@@ -56,6 +59,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
             Api::Struct(strct) => {
                 expanded.extend(expand_struct(strct));
                 hidden.extend(expand_struct_operators(strct));
+                forbid.extend(expand_struct_forbid_drop(strct));
             }
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
@@ -103,6 +107,10 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
         }
     }
 
+    if !forbid.is_empty() {
+        hidden.extend(expand_forbid(forbid));
+    }
+
     // Work around https://github.com/rust-lang/rust/issues/67851.
     if !hidden.is_empty() {
         expanded.extend(quote! {
@@ -162,6 +170,7 @@ fn expand_struct(strct: &Struct) -> TokenStream {
         #struct_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
@@ -264,6 +273,17 @@ fn expand_struct_operators(strct: &Struct) -> TokenStream {
     operators
 }
 
+fn expand_struct_forbid_drop(strct: &Struct) -> TokenStream {
+    let ident = &strct.name.rust;
+    let generics = &strct.generics;
+    let span = ident.span();
+    let impl_token = Token![impl](strct.visibility.span);
+
+    quote_spanned! {span=>
+        #impl_token #generics self::Drop for super::#ident #generics {}
+    }
+}
+
 fn expand_enum(enm: &Enum) -> TokenStream {
     let ident = &enm.name.rust;
     let doc = &enm.doc;
@@ -311,6 +331,7 @@ fn expand_enum(enm: &Enum) -> TokenStream {
         }
 
         unsafe impl ::cxx::ExternType for #ident {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Trivial;
         }
@@ -351,6 +372,7 @@ fn expand_cxx_type(ety: &ExternType) -> TokenStream {
         #extern_type_def
 
         unsafe impl #generics ::cxx::ExternType for #ident #generics {
+            #[doc(hidden)]
             type Id = #type_id;
             type Kind = ::cxx::kind::Opaque;
         }
@@ -720,6 +742,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
             let span = derive.span;
             impls.extend(quote_spanned! {span=>
                 unsafe impl #generics ::cxx::ExternType for #ident #generics {
+                    #[doc(hidden)]
                     type Id = #type_id;
                     type Kind = ::cxx::kind::Opaque;
                 }
@@ -785,6 +808,17 @@ fn expand_rust_type_layout(ety: &ExternType) -> TokenStream {
     }
 }
 
+fn expand_forbid(impls: TokenStream) -> TokenStream {
+    quote! {
+        mod forbid {
+            pub trait Drop {}
+            #[allow(drop_bounds)]
+            impl<T: ?::std::marker::Sized + ::std::ops::Drop> self::Drop for T {}
+            #impls
+        }
+    }
+}
+
 fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
     let link_name = mangle::extern_fn(efn, types);
     let local_name = match &efn.receiver {
@@ -1061,10 +1095,12 @@ fn expand_type_alias_verify(alias: &TypeAlias, types: &Types) -> TokenStream {
 }
 
 fn type_id(name: &Pair) -> TokenStream {
-    let path = name.to_fully_qualified();
-    quote! {
-        ::cxx::type_id!(#path)
-    }
+    let namespace_segments = name.namespace.iter();
+    let mut segments = Vec::with_capacity(namespace_segments.len() + 1);
+    segments.extend(namespace_segments.cloned());
+    segments.push(Ident::new(&name.cxx.to_string(), Span::call_site()));
+    let qualified = QualifiedName { segments };
+    crate::type_id::expand(Crate::Cxx, qualified)
 }
 
 fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index fc7828b..a92eae7 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -36,6 +36,7 @@ mod type_id;
 use crate::syntax::file::Module;
 use crate::syntax::namespace::Namespace;
 use crate::syntax::qualified::QualifiedName;
+use crate::type_id::Crate;
 use proc_macro::TokenStream;
 use syn::parse::{Parse, ParseStream, Parser, Result};
 use syn::parse_macro_input;
@@ -73,16 +74,22 @@ pub fn bridge(args: TokenStream, input: TokenStream) -> TokenStream {
         .into()
 }
 
+#[doc(hidden)]
 #[proc_macro]
 pub fn type_id(input: TokenStream) -> TokenStream {
-    struct TypeId(QualifiedName);
+    struct TypeId {
+        krate: Crate,
+        path: QualifiedName,
+    }
 
     impl Parse for TypeId {
         fn parse(input: ParseStream) -> Result<Self> {
-            QualifiedName::parse_quoted_or_unquoted(input).map(TypeId)
+            let krate = input.parse().map(Crate::DollarCrate)?;
+            let path = QualifiedName::parse_quoted_or_unquoted(input)?;
+            Ok(TypeId { krate, path })
         }
     }
 
     let arg = parse_macro_input!(input as TypeId);
-    type_id::expand(arg.0).into()
+    type_id::expand(arg.krate, arg.path).into()
 }
diff --git a/macro/src/type_id.rs b/macro/src/type_id.rs
index 5c5d9cc..74f0c1c 100644
--- a/macro/src/type_id.rs
+++ b/macro/src/type_id.rs
@@ -1,9 +1,23 @@
 use crate::syntax::qualified::QualifiedName;
-use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
+use proc_macro2::{TokenStream, TokenTree};
+use quote::{format_ident, quote, ToTokens};
+
+pub enum Crate {
+    Cxx,
+    DollarCrate(TokenTree),
+}
+
+impl ToTokens for Crate {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        match self {
+            Crate::Cxx => tokens.extend(quote!(::cxx)),
+            Crate::DollarCrate(krate) => krate.to_tokens(tokens),
+        }
+    }
+}
 
 // "folly::File" => `(f, o, l, l, y, (), F, i, l, e)`
-pub fn expand(arg: QualifiedName) -> TokenStream {
+pub fn expand(krate: Crate, arg: QualifiedName) -> TokenStream {
     let mut ids = Vec::new();
 
     for word in arg.segments {
@@ -14,11 +28,11 @@ pub fn expand(arg: QualifiedName) -> TokenStream {
             ids.push(match ch {
                 'A'..='Z' | 'a'..='z' => {
                     let t = format_ident!("{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 '0'..='9' | '_' => {
                     let t = format_ident!("_{}", ch);
-                    quote!(::cxx::#t)
+                    quote!(#krate::#t)
                 }
                 _ => quote!([(); #ch as _]),
             });
diff --git a/src/cxx.cc b/src/cxx.cc
index 0dba805..0f87bfe 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -100,7 +100,7 @@ String::String(const char *s, std::size_t len) {
              len);
 }
 
-String &String::operator=(const String &other) noexcept {
+String &String::operator=(const String &other) & noexcept {
   if (this != &other) {
     cxxbridge1$string$drop(this);
     cxxbridge1$string$clone(this, other);
@@ -108,12 +108,10 @@ String &String::operator=(const String &other) noexcept {
   return *this;
 }
 
-String &String::operator=(String &&other) noexcept {
-  if (this != &other) {
-    cxxbridge1$string$drop(this);
-    this->repr = other.repr;
-    cxxbridge1$string$new(&other);
-  }
+String &String::operator=(String &&other) & noexcept {
+  cxxbridge1$string$drop(this);
+  this->repr = other.repr;
+  cxxbridge1$string$new(&other);
   return *this;
 }
 
@@ -378,7 +376,7 @@ Error::Error(Error &&other) noexcept
 
 Error::~Error() noexcept { delete[] this->msg; }
 
-Error &Error::operator=(const Error &other) {
+Error &Error::operator=(const Error &other) & {
   if (this != &other) {
     std::exception::operator=(other);
     delete[] this->msg;
@@ -391,14 +389,12 @@ Error &Error::operator=(const Error &other) {
   return *this;
 }
 
-Error &Error::operator=(Error &&other) noexcept {
-  if (this != &other) {
-    std::exception::operator=(std::move(other));
-    this->msg = other.msg;
-    this->len = other.len;
-    other.msg = nullptr;
-    other.len = 0;
-  }
+Error &Error::operator=(Error &&other) & noexcept {
+  std::exception::operator=(std::move(other));
+  this->msg = other.msg;
+  this->len = other.len;
+  other.msg = nullptr;
+  other.len = 0;
   return *this;
 }
 
@@ -413,6 +409,21 @@ union MaybeUninit {
 };
 } // namespace
 
+namespace detail {
+// On some platforms size_t is the same C++ type as one of the sized integer
+// types; on others it is a distinct type. Only in the latter case do we need to
+// define a specialized impl of rust::Vec<size_t>, because in the former case it
+// would collide with one of the other specializations.
+using usize_if_unique =
+    typename std::conditional<std::is_same<size_t, uint64_t>::value ||
+                                  std::is_same<size_t, uint32_t>::value,
+                              struct usize_ignore, size_t>::type;
+using isize_if_unique =
+    typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
+                                  std::is_same<rust::isize, int32_t>::value,
+                              struct isize_ignore, rust::isize>::type;
+} // namespace detail
+
 } // namespace cxxbridge1
 } // namespace rust
 
@@ -602,6 +613,8 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(bool, bool)                                                            \
   MACRO(char, char)                                                            \
+  MACRO(usize, rust::detail::usize_if_unique)                                  \
+  MACRO(isize, rust::detail::isize_if_unique)                                  \
   MACRO(string, rust::String)                                                  \
   MACRO(str, rust::Str)
 
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 99e0cb1..35057ac 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -188,6 +188,7 @@ macro_rules! impl_extern_type {
     ($([$kind:ident] $($ty:path = $cxxpath:literal)*)*) => {
         $($(
             unsafe impl ExternType for $ty {
+                #[doc(hidden)]
                 type Id = crate::type_id!($cxxpath);
                 type Kind = $kind;
             }
diff --git a/src/lib.rs b/src/lib.rs
index 0f92253..906d951 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.29")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.32")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
@@ -413,6 +413,7 @@ mod shared_ptr;
 #[path = "cxx_string.rs"]
 mod string;
 mod symbols;
+mod type_id;
 mod unique_ptr;
 mod unwind;
 #[path = "cxx_vector.rs"]
@@ -429,11 +430,6 @@ pub use crate::vector::CxxVector;
 pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
-/// For use in impls of the `ExternType` trait. See [`ExternType`].
-///
-/// [`ExternType`]: trait.ExternType.html
-pub use cxxbridge_macro::type_id;
-
 /// Synonym for `CxxString`.
 ///
 /// To avoid confusion with Rust's standard library string you probably
@@ -466,6 +462,7 @@ pub mod private {
     pub use crate::unwind::catch_unwind;
     pub use crate::vector::VectorElement;
     pub use crate::weak_ptr::WeakPtrTarget;
+    pub use cxxbridge_macro::type_id;
 }
 
 mod actually_private {
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index bda1209..a26a156 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -68,10 +68,12 @@ rust_vec_shims_for_primitive!(u8);
 rust_vec_shims_for_primitive!(u16);
 rust_vec_shims_for_primitive!(u32);
 rust_vec_shims_for_primitive!(u64);
+rust_vec_shims_for_primitive!(usize);
 rust_vec_shims_for_primitive!(i8);
 rust_vec_shims_for_primitive!(i16);
 rust_vec_shims_for_primitive!(i32);
 rust_vec_shims_for_primitive!(i64);
+rust_vec_shims_for_primitive!(isize);
 rust_vec_shims_for_primitive!(f32);
 rust_vec_shims_for_primitive!(f64);
 
diff --git a/src/type_id.rs b/src/type_id.rs
new file mode 100644
index 0000000..bd2b4ea
--- /dev/null
+++ b/src/type_id.rs
@@ -0,0 +1,9 @@
+/// For use in impls of the `ExternType` trait. See [`ExternType`].
+///
+/// [`ExternType`]: trait.ExternType.html
+#[macro_export]
+macro_rules! type_id {
+    ($($path:tt)*) => {
+        $crate::private::type_id! { $crate $($path)* }
+    };
+}
diff --git a/syntax/check.rs b/syntax/check.rs
index e4933d3..052b248 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -392,12 +392,15 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                 false => "",
             };
             let msg = format!(
-                "unnamed receiver type is only allowed if the surrounding \
-                 extern block contains exactly one extern type; \
-                 use `self: &{mutability}TheType`",
+                "unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &{mutability}TheType`",
                 mutability = mutability,
             );
             cx.error(span, msg);
+        } else if cx.types.enums.contains_key(&receiver.ty.rust) {
+            cx.error(
+                span,
+                "unsupported receiver type; C++ does not allow member functions on enums",
+            );
         } else if !cx.types.structs.contains_key(&receiver.ty.rust)
             && !cx.types.cxx.contains(&receiver.ty.rust)
             && !cx.types.rust.contains(&receiver.ty.rust)
diff --git a/syntax/parse.rs b/syntax/parse.rs
index af03248..d030bde 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -146,7 +146,7 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
                 continue;
             }
         };
-        let visibility = visibility_pub(&field.vis, &ident);
+        let visibility = visibility_pub(&field.vis, ident.span());
         let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
         fields.push(Var {
             doc,
@@ -157,8 +157,8 @@ fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) ->
         });
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let struct_token = item.struct_token;
+    let visibility = visibility_pub(&item.vis, struct_token.span);
     let name = pair(namespace, &item.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: item.generics.lt_token,
@@ -221,8 +221,8 @@ fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
         }
     }
 
-    let visibility = visibility_pub(&item.vis, &item.ident);
     let enum_token = item.enum_token;
+    let visibility = visibility_pub(&item.vis, enum_token.span);
     let brace_token = item.brace_token;
 
     let explicit_repr = repr.is_some();
@@ -454,8 +454,8 @@ fn parse_extern_type(
         },
     );
 
-    let visibility = visibility_pub(&foreign_type.vis, &foreign_type.ident);
     let type_token = foreign_type.type_token;
+    let visibility = visibility_pub(&foreign_type.vis, type_token.span);
     let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
     let generics = Lifetimes {
         lt_token: None,
@@ -628,7 +628,10 @@ fn parse_extern_fn(
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
     let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
+    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
+    let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
+    let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
     let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
     let generics = generics.clone();
     let paren_token = foreign_fn.sig.paren_token;
@@ -794,7 +797,7 @@ fn parse_type_alias(
         return Err(Error::new_spanned(span, msg));
     }
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(Api::TypeAlias(TypeAlias {
@@ -874,7 +877,7 @@ fn parse_extern_type_bounded(
         },
     );
 
-    let visibility = visibility_pub(&visibility, &ident);
+    let visibility = visibility_pub(&visibility, type_token.span);
     let name = pair(namespace, &ident, cxx_name, rust_name);
 
     Ok(match lang {
@@ -1355,12 +1358,12 @@ fn parse_return_type(
     }
 }
 
-fn visibility_pub(vis: &Visibility, inherited: &Ident) -> Token![pub] {
+fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
     Token![pub](match vis {
         Visibility::Public(vis) => vis.pub_token.span,
         Visibility::Crate(vis) => vis.crate_token.span,
         Visibility::Restricted(vis) => vis.pub_token.span,
-        Visibility::Inherited => inherited.span(),
+        Visibility::Inherited => inherited,
     })
 }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 25cf26b..669c818 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -835,6 +835,14 @@ extern "C" const char *cxx_run_test() noexcept {
   ASSERT(vec1[0] == 3 && vec1[1] == 4);
   ASSERT(vec2[0] == 1 && vec2[1] == 2);
 
+  // Test Vec<usize> and Vec<isize>. These are weird because on Linux and
+  // Windows size_t is exactly the same C++ type as one of the sized integer
+  // types (typically uint64_t, both of which are defined as unsigned long),
+  // while on macOS it is a distinct type.
+  // https://github.com/dtolnay/cxx/issues/705
+  (void)rust::Vec<size_t>();
+  (void)rust::Vec<rust::isize>();
+
   cxx_test_suite_set_correct();
   return nullptr;
 }
diff --git a/tests/ui/drop_shared.rs b/tests/ui/drop_shared.rs
new file mode 100644
index 0000000..5e3de4a
--- /dev/null
+++ b/tests/ui/drop_shared.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    struct Shared {
+        fd: i32,
+    }
+}
+
+impl Drop for ffi::Shared {
+    fn drop(&mut self) {
+        println!("close({})", self.fd);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/drop_shared.stderr b/tests/ui/drop_shared.stderr
new file mode 100644
index 0000000..47db21e
--- /dev/null
+++ b/tests/ui/drop_shared.stderr
@@ -0,0 +1,8 @@
+error[E0119]: conflicting implementations of trait `ffi::_::forbid::Drop` for type `ffi::Shared`:
+ --> $DIR/drop_shared.rs:3:5
+  |
+1 | #[cxx::bridge]
+  | -------------- first implementation here
+2 | mod ffi {
+3 |     struct Shared {
+  |     ^^^^^^^^^^^^^ conflicting implementation for `ffi::Shared`
diff --git a/tests/ui/enum_match_without_wildcard.stderr b/tests/ui/enum_match_without_wildcard.stderr
index 183aa5e..f43678f 100644
--- a/tests/ui/enum_match_without_wildcard.stderr
+++ b/tests/ui/enum_match_without_wildcard.stderr
@@ -2,7 +2,7 @@ error[E0004]: non-exhaustive patterns: `A { repr: 2_u8..=u8::MAX }` not covered
   --> $DIR/enum_match_without_wildcard.rs:12:11
    |
 3  |     enum A {
-   |          - `ffi::A` defined here
+   |     ------ `ffi::A` defined here
 ...
 12 |     match a {
    |           ^ pattern `A { repr: 2_u8..=u8::MAX }` not covered
diff --git a/tests/ui/enum_receiver.rs b/tests/ui/enum_receiver.rs
new file mode 100644
index 0000000..a27f274
--- /dev/null
+++ b/tests/ui/enum_receiver.rs
@@ -0,0 +1,11 @@
+#[cxx::bridge]
+mod ffi {
+    enum Enum {
+        Variant,
+    }
+    extern "Rust" {
+        fn f(self: &Enum);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/enum_receiver.stderr b/tests/ui/enum_receiver.stderr
new file mode 100644
index 0000000..e09b4e3
--- /dev/null
+++ b/tests/ui/enum_receiver.stderr
@@ -0,0 +1,5 @@
+error: unsupported receiver type; C++ does not allow member functions on enums
+ --> $DIR/enum_receiver.rs:7:20
+  |
+7 |         fn f(self: &Enum);
+  |                    ^^^^^
diff --git a/third-party/BUCK b/third-party/BUCK
index d5a03c2..bef999d 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -57,7 +57,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.8/src/**"]),
+    srcs = glob(["vendor/quote-1.0.9/src/**"]),
     visibility = ["PUBLIC"],
     features = ["proc-macro"],
     deps = [":proc-macro2"],
diff --git a/third-party/BUILD b/third-party/BUILD
index c1ab800..9781d98 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -61,7 +61,7 @@ rust_library(
 
 rust_library(
     name = "quote",
-    srcs = glob(["vendor/quote-1.0.8/src/**"]),
+    srcs = glob(["vendor/quote-1.0.9/src/**"]),
     crate_features = ["proc-macro"],
     visibility = ["//visibility:public"],
     deps = [":proc-macro2"],
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 5a8a4a1..23f34b0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -1,5 +1,7 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "ansi_term"
 version = "0.11.0"
@@ -31,6 +33,9 @@ name = "cc"
 version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
+dependencies = [
+ "jobserver",
+]
 
 [[package]]
 name = "clap"
@@ -59,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.29"
+version = "1.0.32"
 dependencies = [
  "cc",
  "cxx-build",
@@ -74,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.29"
+version = "1.0.32"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -89,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.29"
+version = "0.7.32"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -109,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.29"
+version = "1.0.32"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -120,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.29"
+version = "1.0.32"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.29"
+version = "1.0.32"
 dependencies = [
  "cxx",
  "proc-macro2",
@@ -168,6 +173,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
 
 [[package]]
+name = "jobserver"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
+dependencies = [
+ "libc",
+]
+
+[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -175,9 +189,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.82"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
 
 [[package]]
 name = "link-cplusplus"
@@ -205,9 +219,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
 dependencies = [
  "proc-macro2",
 ]
@@ -252,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.61"
+version = "1.0.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
+checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
 dependencies = [
  "itoa",
  "ryu",
@@ -307,9 +321,9 @@ dependencies = [
 
 [[package]]
 name = "trybuild"
-version = "1.0.39"
+version = "1.0.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c9594b802f041389d2baac680663573dde3103bb4a4926d61d6aba689465978"
+checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b"
 dependencies = [
  "dissimilar",
  "glob",

From 415f23255eb6d3c6104588fec84b6d7e3969b5fa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 17 2021 23:49:39 +0000
Subject: [PATCH 2121/2232] Document the possible arrangements of mangled symbols


---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 901830a..df1260b 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,3 +1,61 @@
+// Mangled symbol arrangements:
+//
+//   (a) One-off internal symbol.
+//          pattern:  {CXXBRIDGE} $ {NAME}
+//          examples:
+//             - cxxbridge1$exception
+//          defining characteristics:
+//             - 2 segments
+//             - starts with cxxbridge
+//
+//   (b) Behavior on a builtin binding without generic parameter.
+//          pattern:  {CXXBRIDGE} $ {TYPE} $ {NAME}
+//          examples:
+//             - cxxbridge1$string$len
+//          defining characteristics:
+//             - 3 segments
+//             - starts with cxxbridge
+//
+//   (c) Behavior on a builtin binding with generic parameter.
+//          pattern:  {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME}
+//          examples:
+//             - cxxbridge1$box$org$rust$Struct$alloc
+//             - cxxbridge1$unique_ptr$std$vector$u8$drop
+//          defining characteristics:
+//             - 4+ segments
+//             - starts with cxxbridge
+//
+//   (d) User-defined extern function.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {NAME}
+//          examples:
+//             - cxxbridge1$new_client
+//             - org$rust$cxxbridge1$new_client
+//          defining characteristics:
+//             - cxxbridge is second from end
+//          FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace
+//
+//   (e) User-defined extern member function.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME}
+//          examples:
+//             - org$cxxbridge1$Struct$get
+//          defining characteristics:
+//             - cxxbridge is third from end
+//          FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names
+//
+//   (f) Operator overload.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME}
+//          examples:
+//             - org$rust$cxxbridge1$Struct$operator$eq
+//          defining characteristics:
+//             - second segment from end is `operator` (not possible in type or namespace names)
+//
+//   (g) Closure trampoline.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
+//          examples:
+//             - org$rust$cxxbridge1$Struct$invoke$f$0
+//          defining characteristics:
+//             - last symbol is `0` (C half) or `1` (Rust half) which are not legal identifiers on their own
+
 use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::{ExternFn, Pair, Types};
 

From 6c39d4b9c88f45ffc7a3b58607483dec12aea651 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 17 2021 23:56:07 +0000
Subject: [PATCH 2122/2232] Document the arrangements of preprocessor variables


---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index df1260b..287b443 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -55,6 +55,23 @@
 //             - org$rust$cxxbridge1$Struct$invoke$f$0
 //          defining characteristics:
 //             - last symbol is `0` (C half) or `1` (Rust half) which are not legal identifiers on their own
+//
+//
+// Mangled preprocessor variable arrangements:
+//
+//   (A) One-off internal variable.
+//          pattern:  {CXXBRIDGE} _ {NAME}
+//          examples:
+//             - CXXBRIDGE1_PANIC
+//             - CXXBRIDGE1_RUST_STRING
+//          defining characteristics:
+//             - NAME does not begin with STRUCT or ENUM
+//
+//   (B) Guard around user-defined type.
+//          pattern:  {CXXBRIDGE} _ {STRUCT or ENUM} _ {NAMESPACE...} $ {TYPE}
+//          examples:
+//             - CXXBRIDGE1_STRUCT_org$rust$Struct
+//             - CXXBRIDGE1_ENUM_Enabled
 
 use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::{ExternFn, Pair, Types};

From 57832124b4c2e3ec193c09d322442f5dd62e06f4 Mon Sep 17 00:00:00 2001
From: Adrian Taylor <adetaylor@chromium.org>
Date: Feb 18 2021 00:11:08 +0000
Subject: [PATCH 2123/2232] Merge fix.


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index d030bde..8f8075a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -627,7 +627,6 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let visibility = visibility_pub(&foreign_fn.vis, &foreign_fn.sig.ident);
     let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);

From e5bb345e8c3189c7456d8ee63cb0f1186339cb42 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 18 2021 00:20:08 +0000
Subject: [PATCH 2124/2232] Merge pull request #723 from dtolnay/mangle


Document the possible arrangements of mangled symbols
---

diff --git a/syntax/mangle.rs b/syntax/mangle.rs
index 901830a..287b443 100644
--- a/syntax/mangle.rs
+++ b/syntax/mangle.rs
@@ -1,3 +1,78 @@
+// Mangled symbol arrangements:
+//
+//   (a) One-off internal symbol.
+//          pattern:  {CXXBRIDGE} $ {NAME}
+//          examples:
+//             - cxxbridge1$exception
+//          defining characteristics:
+//             - 2 segments
+//             - starts with cxxbridge
+//
+//   (b) Behavior on a builtin binding without generic parameter.
+//          pattern:  {CXXBRIDGE} $ {TYPE} $ {NAME}
+//          examples:
+//             - cxxbridge1$string$len
+//          defining characteristics:
+//             - 3 segments
+//             - starts with cxxbridge
+//
+//   (c) Behavior on a builtin binding with generic parameter.
+//          pattern:  {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME}
+//          examples:
+//             - cxxbridge1$box$org$rust$Struct$alloc
+//             - cxxbridge1$unique_ptr$std$vector$u8$drop
+//          defining characteristics:
+//             - 4+ segments
+//             - starts with cxxbridge
+//
+//   (d) User-defined extern function.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {NAME}
+//          examples:
+//             - cxxbridge1$new_client
+//             - org$rust$cxxbridge1$new_client
+//          defining characteristics:
+//             - cxxbridge is second from end
+//          FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace
+//
+//   (e) User-defined extern member function.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME}
+//          examples:
+//             - org$cxxbridge1$Struct$get
+//          defining characteristics:
+//             - cxxbridge is third from end
+//          FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names
+//
+//   (f) Operator overload.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME}
+//          examples:
+//             - org$rust$cxxbridge1$Struct$operator$eq
+//          defining characteristics:
+//             - second segment from end is `operator` (not possible in type or namespace names)
+//
+//   (g) Closure trampoline.
+//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
+//          examples:
+//             - org$rust$cxxbridge1$Struct$invoke$f$0
+//          defining characteristics:
+//             - last symbol is `0` (C half) or `1` (Rust half) which are not legal identifiers on their own
+//
+//
+// Mangled preprocessor variable arrangements:
+//
+//   (A) One-off internal variable.
+//          pattern:  {CXXBRIDGE} _ {NAME}
+//          examples:
+//             - CXXBRIDGE1_PANIC
+//             - CXXBRIDGE1_RUST_STRING
+//          defining characteristics:
+//             - NAME does not begin with STRUCT or ENUM
+//
+//   (B) Guard around user-defined type.
+//          pattern:  {CXXBRIDGE} _ {STRUCT or ENUM} _ {NAMESPACE...} $ {TYPE}
+//          examples:
+//             - CXXBRIDGE1_STRUCT_org$rust$Struct
+//             - CXXBRIDGE1_ENUM_Enabled
+
 use crate::syntax::symbol::{self, Symbol};
 use crate::syntax::{ExternFn, Pair, Types};
 

From 3dafaede930026394649639ac0798aa39d6b439f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Feb 26 2021 04:42:30 +0000
Subject: [PATCH 2125/2232] Resolve inconsistent_struct_constructor style lint


    error: inconsistent struct constructor
       --> gen/cmd/src/app.rs:95:5
        |
    95  | /     Opt {
    96  | |         input,
    97  | |         cxx_impl_annotations,
    98  | |         header,
    99  | |         include,
    100 | |         outputs,
    101 | |     }
        | |_____^ help: try: `Opt { input, header, cxx_impl_annotations, include, outputs }`
        |
        = note: `-D clippy::inconsistent-struct-constructor` implied by `-D clippy::all`
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor

---

diff --git a/gen/cmd/src/app.rs b/gen/cmd/src/app.rs
index e2945a1..c233ad7 100644
--- a/gen/cmd/src/app.rs
+++ b/gen/cmd/src/app.rs
@@ -94,8 +94,8 @@ pub(super) fn from_args() -> Opt {
 
     Opt {
         input,
-        cxx_impl_annotations,
         header,
+        cxx_impl_annotations,
         include,
         outputs,
     }

From 7b783f92debf6106fb4f53e507c16c347ecdd590 Mon Sep 17 00:00:00 2001
From: b05902132 <b05902132@csie.ntu.edu.tw>
Date: Mar 18 2021 18:27:45 +0000
Subject: [PATCH 2126/2232] implment `Ord`, `PartialOrd` and `Hash` for CxxString.


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 8834b49..c132189 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -183,6 +183,38 @@ impl PartialEq<str> for CxxString {
     }
 }
 
+impl Eq for CxxString {}
+
+impl PartialOrd for CxxString {
+    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl PartialOrd<str> for CxxString {
+    fn partial_cmp(&self, other: &str) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl PartialOrd<CxxString> for str {
+    fn partial_cmp(&self, other: &CxxString) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl Ord for CxxString {
+    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+        self.as_bytes().cmp(other.as_bytes())
+    }
+}
+
+impl core::hash::Hash for CxxString {
+    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+        self.as_bytes().hash(state)
+    }
+}
+
 #[doc(hidden)]
 #[repr(C)]
 pub struct StackString {
diff --git a/tests/cxx_string.rs b/tests/cxx_string.rs
index be693cd..3bc0d91 100644
--- a/tests/cxx_string.rs
+++ b/tests/cxx_string.rs
@@ -13,3 +13,34 @@ fn test_async_cxx_string() {
     fn assert_send(_: impl Send) {}
     assert_send(f());
 }
+
+#[test]
+fn test_cmp_rust_str_cxx_string() {
+    use std::cmp::Ordering;
+    fn test_eq(rust_str: &str) {
+        let_cxx_string!(cxx_string = rust_str);
+        assert_eq!(rust_str.partial_cmp(&*cxx_string), Some(Ordering::Equal));
+        assert_eq!((*cxx_string).partial_cmp(rust_str), Some(Ordering::Equal));
+        assert_eq!(*cxx_string, *rust_str);
+        assert_eq!(*rust_str, *cxx_string);
+    }
+
+    fn test_ne(lhs: &str, rhs: &str) {
+        let_cxx_string!(cxx_lhs = lhs);
+        let_cxx_string!(cxx_rhs = rhs);
+        assert_ne!(lhs.partial_cmp(&*cxx_rhs), Some(Ordering::Equal));
+        assert_ne!(rhs.partial_cmp(&*cxx_lhs), Some(Ordering::Equal));
+        assert_ne!((*cxx_lhs).partial_cmp(rhs), Some(Ordering::Equal));
+        assert_ne!((*cxx_rhs).partial_cmp(lhs), Some(Ordering::Equal));
+        assert_ne!(*cxx_lhs, *rhs);
+        assert_ne!(*cxx_rhs, *lhs);
+        assert_ne!(*rhs, *cxx_lhs);
+        assert_ne!(*lhs, *cxx_rhs);
+    }
+    test_eq("abc");
+    test_eq("");
+    test_ne("abc", "Abc");
+    test_ne("abc", "");
+    // test utf8 character
+    test_eq("♡");
+}

From 389887843ca0307dc2370d1134aaa6c6a8b0b0f3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 20:27:59 +0000
Subject: [PATCH 2127/2232] Merge pull request 743 from b05902132/cxx_string_traits


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 8834b49..c132189 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -183,6 +183,38 @@ impl PartialEq<str> for CxxString {
     }
 }
 
+impl Eq for CxxString {}
+
+impl PartialOrd for CxxString {
+    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl PartialOrd<str> for CxxString {
+    fn partial_cmp(&self, other: &str) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl PartialOrd<CxxString> for str {
+    fn partial_cmp(&self, other: &CxxString) -> Option<core::cmp::Ordering> {
+        self.as_bytes().partial_cmp(other.as_bytes())
+    }
+}
+
+impl Ord for CxxString {
+    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+        self.as_bytes().cmp(other.as_bytes())
+    }
+}
+
+impl core::hash::Hash for CxxString {
+    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+        self.as_bytes().hash(state)
+    }
+}
+
 #[doc(hidden)]
 #[repr(C)]
 pub struct StackString {

From 05db2fbc9fc1d77329ed584dea25d43141a47261 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 20:33:27 +0000
Subject: [PATCH 2128/2232] Touch up PR 743


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index c132189..a730768 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,7 +1,9 @@
 use crate::actually_private::Private;
 use alloc::borrow::Cow;
 use alloc::string::String;
+use core::cmp::Ordering;
 use core::fmt::{self, Debug, Display};
+use core::hash::{Hash, Hasher};
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem::MaybeUninit;
 use core::pin::Pin;
@@ -186,32 +188,32 @@ impl PartialEq<str> for CxxString {
 impl Eq for CxxString {}
 
 impl PartialOrd for CxxString {
-    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         self.as_bytes().partial_cmp(other.as_bytes())
     }
 }
 
 impl PartialOrd<str> for CxxString {
-    fn partial_cmp(&self, other: &str) -> Option<core::cmp::Ordering> {
+    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
         self.as_bytes().partial_cmp(other.as_bytes())
     }
 }
 
 impl PartialOrd<CxxString> for str {
-    fn partial_cmp(&self, other: &CxxString) -> Option<core::cmp::Ordering> {
+    fn partial_cmp(&self, other: &CxxString) -> Option<Ordering> {
         self.as_bytes().partial_cmp(other.as_bytes())
     }
 }
 
 impl Ord for CxxString {
-    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
+    fn cmp(&self, other: &Self) -> Ordering {
         self.as_bytes().cmp(other.as_bytes())
     }
 }
 
-impl core::hash::Hash for CxxString {
-    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
-        self.as_bytes().hash(state)
+impl Hash for CxxString {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.as_bytes().hash(state);
     }
 }
 

From 94e205403dcc00c6f8c05eb471ace991e61ef0ee Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 20:33:57 +0000
Subject: [PATCH 2129/2232] Delete CxxString heterogeneous PartialOrd impls


---

diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index a730768..e4dfdf1 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -193,18 +193,6 @@ impl PartialOrd for CxxString {
     }
 }
 
-impl PartialOrd<str> for CxxString {
-    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
-        self.as_bytes().partial_cmp(other.as_bytes())
-    }
-}
-
-impl PartialOrd<CxxString> for str {
-    fn partial_cmp(&self, other: &CxxString) -> Option<Ordering> {
-        self.as_bytes().partial_cmp(other.as_bytes())
-    }
-}
-
 impl Ord for CxxString {
     fn cmp(&self, other: &Self) -> Ordering {
         self.as_bytes().cmp(other.as_bytes())

From 2e43b5122729466b5218ab9f0c9f0c93973d1c66 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 20:35:38 +0000
Subject: [PATCH 2130/2232] Consistently use 'other: &Self' in homogeneous comparison impls


---

diff --git a/gen/src/out.rs b/gen/src/out.rs
index bf880cc..3b4d739 100644
--- a/gen/src/out.rs
+++ b/gen/src/out.rs
@@ -102,7 +102,7 @@ impl<'a> Write for Content<'a> {
 }
 
 impl<'a> PartialEq for Content<'a> {
-    fn eq(&self, _other: &Content) -> bool {
+    fn eq(&self, _other: &Self) -> bool {
         true
     }
 }
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index e4dfdf1..dce7053 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -168,7 +168,7 @@ impl Debug for CxxString {
 }
 
 impl PartialEq for CxxString {
-    fn eq(&self, other: &CxxString) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         self.as_bytes() == other.as_bytes()
     }
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 3a0b3e0..ee4b641 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -6,7 +6,7 @@ use std::mem;
 use std::ops::{Deref, DerefMut};
 
 impl PartialEq for Include {
-    fn eq(&self, other: &Include) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Include {
             path,
             kind,
@@ -61,7 +61,7 @@ impl Hash for Type {
 impl Eq for Type {}
 
 impl PartialEq for Type {
-    fn eq(&self, other: &Type) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         match (self, other) {
             (Type::Ident(lhs), Type::Ident(rhs)) => lhs == rhs,
             (Type::RustBox(lhs), Type::RustBox(rhs)) => lhs == rhs,
@@ -83,7 +83,7 @@ impl PartialEq for Type {
 impl Eq for Lifetimes {}
 
 impl PartialEq for Lifetimes {
-    fn eq(&self, other: &Lifetimes) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Lifetimes {
             lt_token: _,
             lifetimes,
@@ -115,7 +115,7 @@ impl Hash for Lifetimes {
 impl Eq for Ty1 {}
 
 impl PartialEq for Ty1 {
-    fn eq(&self, other: &Ty1) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Ty1 {
             name,
             langle: _,
@@ -148,7 +148,7 @@ impl Hash for Ty1 {
 impl Eq for Ref {}
 
 impl PartialEq for Ref {
-    fn eq(&self, other: &Ref) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Ref {
             pinned,
             ampersand: _,
@@ -192,7 +192,7 @@ impl Hash for Ref {
 impl Eq for SliceRef {}
 
 impl PartialEq for SliceRef {
-    fn eq(&self, other: &SliceRef) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let SliceRef {
             ampersand: _,
             lifetime,
@@ -232,7 +232,7 @@ impl Hash for SliceRef {
 impl Eq for Array {}
 
 impl PartialEq for Array {
-    fn eq(&self, other: &Array) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Array {
             bracket: _,
             inner,
@@ -268,7 +268,7 @@ impl Hash for Array {
 impl Eq for Signature {}
 
 impl PartialEq for Signature {
-    fn eq(&self, other: &Signature) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Signature {
             unsafety,
             fn_token: _,
@@ -349,7 +349,7 @@ impl Hash for Signature {
 impl Eq for Receiver {}
 
 impl PartialEq for Receiver {
-    fn eq(&self, other: &Receiver) -> bool {
+    fn eq(&self, other: &Self) -> bool {
         let Receiver {
             pinned,
             ampersand: _,

From b11e8dd6d5c8b14a79a045d16964f82608fd66e3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 21:09:44 +0000
Subject: [PATCH 2131/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index bef999d..aed26e4 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -7,7 +7,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.66/src/**"]),
+    srcs = glob(["vendor/cc-1.0.67/src/**"]),
     visibility = ["PUBLIC"],
 )
 
@@ -25,7 +25,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.1/src/**"]),
     visibility = ["PUBLIC"],
     deps = [
         ":termcolor",
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.60/src/**"]),
+    srcs = glob(["vendor/syn-1.0.64/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index 9781d98..a31023b 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -11,7 +11,7 @@ rust_library(
 
 rust_library(
     name = "cc",
-    srcs = glob(["vendor/cc-1.0.66/src/**"]),
+    srcs = glob(["vendor/cc-1.0.67/src/**"]),
     visibility = ["//visibility:public"],
 )
 
@@ -29,7 +29,7 @@ rust_library(
 
 rust_library(
     name = "codespan-reporting",
-    srcs = glob(["vendor/codespan-reporting-0.11.0/src/**"]),
+    srcs = glob(["vendor/codespan-reporting-0.11.1/src/**"]),
     visibility = ["//visibility:public"],
     deps = [
         ":termcolor",
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.60/src/**"]),
+    srcs = glob(["vendor/syn-1.0.64/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 23f34b0..dc8bca0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -30,9 +30,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 
 [[package]]
 name = "cc"
-version = "1.0.66"
+version = "1.0.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
+checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
 dependencies = [
  "jobserver",
 ]
@@ -54,9 +54,9 @@ dependencies = [
 
 [[package]]
 name = "codespan-reporting"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6ce42b8998a383572e0a802d859b1f00c79b7b7474e62fff88ee5c2845d9c13"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
 dependencies = [
  "termcolor",
  "unicode-width",
@@ -189,9 +189,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.86"
+version = "0.2.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
 
 [[package]]
 name = "link-cplusplus"
@@ -246,18 +246,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.123"
+version = "1.0.124"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
+checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.123"
+version = "1.0.124"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
+checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -266,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.62"
+version = "1.0.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
+checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
 dependencies = [
  "itoa",
  "ryu",
@@ -283,9 +283,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.60"
+version = "1.0.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
+checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
 dependencies = [
  "proc-macro2",
  "quote",

From 516bb068e49ac94de8e4b840c75f6f0002a73749 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 18 2021 21:11:25 +0000
Subject: [PATCH 2132/2232] Release 1.0.33


---

diff --git a/Cargo.toml b/Cargo.toml
index 357eb05..df7d042 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.32" # remember to update html_root_url
+version = "1.0.33" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.32", path = "macro" }
+cxxbridge-macro = { version = "=1.0.33", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.32", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.33", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.32", path = "gen/build" }
+cxx-build = { version = "=1.0.33", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 6bd957e..e4f8552 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.32"
+version = "1.0.33"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 74e7b2a..d763b3d 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.32"
+version = "1.0.33"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index a62eab8..11f9d1c 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.32"
+version = "1.0.33"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index be389fe..465df6e 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.32"
+version = "0.7.33"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index c17f010..8aa6a28 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.32"
+version = "1.0.33"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 906d951..57bcbfb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -363,7 +363,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.32")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.33")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index dc8bca0..a0d4f7f 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.32"
+version = "1.0.33"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.32"
+version = "1.0.33"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.32"
+version = "0.7.33"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.32"
+version = "1.0.33"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.32"
+version = "1.0.33"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.32"
+version = "1.0.33"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5d12f1d4c5dc3fcd4e7619076ae58b34cdef4f9c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 22 2021 21:59:33 +0000
Subject: [PATCH 2133/2232] Format PR 714 with clang-format 10


This change in formatting seems to be due to https://reviews.llvm.org/D68695.

---

diff --git a/include/cxx.h b/include/cxx.h
index 654b176..36526c6 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -44,8 +44,8 @@ public:
   String(const char *);
   String(const char *, std::size_t);
 
-  String &operator=(const String &) & noexcept;
-  String &operator=(String &&) & noexcept;
+  String &operator=(const String &) &noexcept;
+  String &operator=(String &&) &noexcept;
 
   explicit operator std::string() const;
 
@@ -97,7 +97,7 @@ public:
   Str(const char *);
   Str(const char *, std::size_t);
 
-  Str &operator=(const Str &) & noexcept = default;
+  Str &operator=(const Str &) &noexcept = default;
 
   explicit operator std::string() const;
 
@@ -144,8 +144,8 @@ template <>
 struct copy_assignable_if<false> {
   copy_assignable_if() noexcept = default;
   copy_assignable_if(const copy_assignable_if &) noexcept = default;
-  copy_assignable_if &operator=(const copy_assignable_if &) & noexcept = delete;
-  copy_assignable_if &operator=(copy_assignable_if &&) & noexcept = default;
+  copy_assignable_if &operator=(const copy_assignable_if &) &noexcept = delete;
+  copy_assignable_if &operator=(copy_assignable_if &&) &noexcept = default;
 };
 } // namespace detail
 
@@ -159,8 +159,8 @@ public:
   Slice() noexcept;
   Slice(T *, std::size_t count) noexcept;
 
-  Slice &operator=(const Slice<T> &) & noexcept = default;
-  Slice &operator=(Slice<T> &&) & noexcept = default;
+  Slice &operator=(const Slice<T> &) &noexcept = default;
+  Slice &operator=(Slice<T> &&) &noexcept = default;
 
   T *data() const noexcept;
   std::size_t size() const noexcept;
@@ -248,7 +248,7 @@ public:
   explicit Box(const T &);
   explicit Box(T &&);
 
-  Box &operator=(Box &&) & noexcept;
+  Box &operator=(Box &&) &noexcept;
 
   const T *operator->() const noexcept;
   const T &operator*() const noexcept;
@@ -293,7 +293,7 @@ public:
   Vec(Vec &&) noexcept;
   ~Vec() noexcept;
 
-  Vec &operator=(Vec &&) & noexcept;
+  Vec &operator=(Vec &&) &noexcept;
   Vec &operator=(const Vec &) &;
 
   std::size_t size() const noexcept;
@@ -372,7 +372,7 @@ public:
   ~Error() noexcept override;
 
   Error &operator=(const Error &) &;
-  Error &operator=(Error &&) & noexcept;
+  Error &operator=(Error &&) &noexcept;
 
   const char *what() const noexcept override;
 
@@ -735,7 +735,7 @@ Box<T>::~Box() noexcept {
 }
 
 template <typename T>
-Box<T> &Box<T>::operator=(Box &&other) & noexcept {
+Box<T> &Box<T>::operator=(Box &&other) &noexcept {
   if (this->ptr) {
     this->drop();
   }
@@ -823,7 +823,7 @@ Vec<T>::~Vec() noexcept {
 }
 
 template <typename T>
-Vec<T> &Vec<T>::operator=(Vec &&other) & noexcept {
+Vec<T> &Vec<T>::operator=(Vec &&other) &noexcept {
   this->drop();
   this->repr = other.repr;
   new (&other) Vec();
diff --git a/src/cxx.cc b/src/cxx.cc
index 0f87bfe..218a675 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -100,7 +100,7 @@ String::String(const char *s, std::size_t len) {
              len);
 }
 
-String &String::operator=(const String &other) & noexcept {
+String &String::operator=(const String &other) &noexcept {
   if (this != &other) {
     cxxbridge1$string$drop(this);
     cxxbridge1$string$clone(this, other);
@@ -108,7 +108,7 @@ String &String::operator=(const String &other) & noexcept {
   return *this;
 }
 
-String &String::operator=(String &&other) & noexcept {
+String &String::operator=(String &&other) &noexcept {
   cxxbridge1$string$drop(this);
   this->repr = other.repr;
   cxxbridge1$string$new(&other);
@@ -389,7 +389,7 @@ Error &Error::operator=(const Error &other) & {
   return *this;
 }
 
-Error &Error::operator=(Error &&other) & noexcept {
+Error &Error::operator=(Error &&other) &noexcept {
   std::exception::operator=(std::move(other));
   this->msg = other.msg;
   this->len = other.len;

From de01edf7060a66ba7645087db304d6528b792804 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 22 2021 22:00:59 +0000
Subject: [PATCH 2134/2232] Update C++ formatting to clang-format 11


---

diff --git a/book/src/binding/cxxstring.md b/book/src/binding/cxxstring.md
index 8345eef..0b1d7bb 100644
--- a/book/src/binding/cxxstring.md
+++ b/book/src/binding/cxxstring.md
@@ -88,7 +88,7 @@ public:
   json(const json &) = default;
   json(json &&) = default;
   template <typename... T>
-  json(T &&... value) : value(std::forward<T>(value)...) {}
+  json(T &&...value) : value(std::forward<T>(value)...) {}
 
   bool isNull() const;
   bool isNumber() const;
diff --git a/book/src/binding/vec.md b/book/src/binding/vec.md
index 092e364..948fa67 100644
--- a/book/src/binding/vec.md
+++ b/book/src/binding/vec.md
@@ -46,7 +46,7 @@ public:
   void push_back(const T &value);
   void push_back(T &&value);
   template <typename... Args>
-  void emplace_back(Args &&... args);
+  void emplace_back(Args &&...args);
 
   class iterator;
   iterator begin() noexcept;
diff --git a/include/cxx.h b/include/cxx.h
index 36526c6..7ee7db7 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -316,7 +316,7 @@ public:
   void push_back(const T &value);
   void push_back(T &&value);
   template <typename... Args>
-  void emplace_back(Args &&... args);
+  void emplace_back(Args &&...args);
 
   using iterator = typename Slice<T>::iterator;
   iterator begin() noexcept;
@@ -766,7 +766,7 @@ T &Box<T>::operator*() noexcept {
 
 template <typename T>
 template <typename... Fields>
-Box<T> Box<T>::in_place(Fields &&... fields) {
+Box<T> Box<T>::in_place(Fields &&...fields) {
   allocation alloc;
   auto ptr = alloc.ptr;
   ::new (ptr) T{std::forward<Fields>(fields)...};
@@ -920,7 +920,7 @@ void Vec<T>::push_back(T &&value) {
 
 template <typename T>
 template <typename... Args>
-void Vec<T>::emplace_back(Args &&... args) {
+void Vec<T>::emplace_back(Args &&...args) {
   auto size = this->size();
   this->reserve_total(size + 1);
   ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) +
diff --git a/src/cxx.cc b/src/cxx.cc
index 218a675..c0ef738 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -66,7 +66,7 @@ void panic [[noreturn]] (const char *msg) {
 #endif
 }
 
-template void panic<std::out_of_range>[[noreturn]] (const char *msg);
+template void panic<std::out_of_range> [[noreturn]] (const char *msg);
 
 String::String() noexcept { cxxbridge1$string$new(this); }
 
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 68ec544..3f2b800 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -779,14 +779,14 @@ extern "C" const char *cxx_run_test() noexcept {
   bool (rust::String::*cmp)(const rust::String &) const;
   bool first_first, first_second, sec_second, second_sec;
   for (auto test : {
-    std::tuple<decltype(cmp), bool, bool, bool, bool>
-    {&rust::String::operator==, true, false, false, false},
-    {&rust::String::operator!=, false, true, true, true},
-    {&rust::String::operator<, false, true, true, false},
-    {&rust::String::operator<=, true, true, true, false},
-    {&rust::String::operator>, false, false, false, true},
-    {&rust::String::operator>=, true, false, false, true},
-  }) {
+           std::tuple<decltype(cmp), bool, bool, bool, bool>{
+               &rust::String::operator==, true, false, false, false},
+           {&rust::String::operator!=, false, true, true, true},
+           {&rust::String::operator<, false, true, true, false},
+           {&rust::String::operator<=, true, true, true, false},
+           {&rust::String::operator>, false, false, false, true},
+           {&rust::String::operator>=, true, false, false, true},
+       }) {
     std::tie(cmp, first_first, first_second, sec_second, second_sec) = test;
     ASSERT((first.*cmp)(first) == first_first);
     ASSERT((first.*cmp)(second) == first_second);

From 9fc8138823f56a684de704be6437b4853bdd2929 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:04:37 +0000
Subject: [PATCH 2135/2232] Merge pull request #689 from adetaylor/pointers


Support raw pointers in cxx::bridge.
---

diff --git a/README.md b/README.md
index b3058f6..c5d93ae 100644
--- a/README.md
+++ b/README.md
@@ -333,6 +333,7 @@ returns of functions.
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/book/src/binding/raw_ptr.md b/book/src/binding/raw_ptr.md
new file mode 100644
index 0000000..7ad6475
--- /dev/null
+++ b/book/src/binding/raw_ptr.md
@@ -0,0 +1,68 @@
+{{#title *mut T, *const T — Rust ♡ C++}}
+# *mut T, *const T - Raw Pointers
+
+cxx supports tranfer of raw pointers across the FFI boundary.
+
+Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
+or references. You should resort to using raw pointers only where lifetimes
+are too complicated to model with standard cxx facilities.
+
+As is normal with raw pointers in Rust, you'll need to use `unsafe` when
+working with them. In particular, to pass any raw pointer into a cxx
+bridge function you will need to declare the function `unsafe`, even if
+the overall `extern "C++"` section is already marked as `unsafe`. By calling
+such a function, you're committing that you - the human - know enough about
+the lifetimes of those objects that the compiler doesn't need to do checks.
+
+On the other hand, C++ functions can freely return raw pointers to
+Rust without `unsafe`, but actually using those raw pointers in any way is likely
+to require an `unsafe` keyword.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+
+        include!("tests/ffi/tests.h");
+        //include!("example/include/container.h");
+
+        type ComplexHierarchicContainer;
+
+        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
+        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
+        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
+        // ...
+    }
+}
+
+fn main() {
+    let mut container = ffi17::new_hierarchic_container();
+    cxx::let_cxx_string!(key = "a");
+    let mut subcontainer = container.pin_mut().add_child(&key);
+    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
+    cxx::let_cxx_string!(key2 = "b");
+    cxx::let_cxx_string!(value = "c");
+    subcontainer.add_value(&key2, &value);
+    // ...
+}
+```
+
+```cpp
+// include/container.h
+
+#pragma once
+
+class ComplexHierarchicContainer {
+public:
+    ComplexHierarchicContainer();
+    void add_value(const std::string& key, const std::string& value);
+    ComplexHierarchicContainer* add_child(const std::string& key);
+    // ...
+};
+
+std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 4a765b3..9ba0c41 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -22,6 +22,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 </table>
 
 <br>
diff --git a/gen/src/write.rs b/gen/src/write.rs
index a2ce630..b3911c1 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -222,7 +222,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
             Type::Fn(_) => out.builtin.rust_fn = true,
             Type::SliceRef(_) => out.builtin.rust_slice = true,
             Type::Array(_) => out.include.array = true,
-            Type::Ref(_) | Type::Void(_) => {}
+            Type::Ref(_) | Type::Void(_) | Type::Ptr(_) => {}
         }
     }
 }
@@ -1179,6 +1179,13 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write_type(out, &r.inner);
             write!(out, " &");
         }
+        Type::Ptr(p) => {
+            if !p.mutable {
+                write!(out, "const ");
+            }
+            write_type(out, &p.inner);
+            write!(out, " *");
+        }
         Type::Str(_) => {
             write!(out, "::rust::Str");
         }
@@ -1253,7 +1260,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
         | Type::SliceRef(_)
         | Type::Fn(_)
         | Type::Array(_) => write!(out, " "),
-        Type::Ref(_) => {}
+        Type::Ref(_) | Type::Ptr(_) => {}
         Type::Void(_) => unreachable!(),
     }
 }
diff --git a/syntax/check.rs b/syntax/check.rs
index 2aefbdf..052b248 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -8,6 +8,8 @@ use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
 
+use super::Ptr;
+
 pub(crate) struct Check<'a> {
     apis: &'a [Api],
     types: &'a Types<'a>,
@@ -35,6 +37,7 @@ fn do_typecheck(cx: &mut Check) {
             Type::WeakPtr(ptr) => check_type_weak_ptr(cx, ptr),
             Type::CxxVector(ptr) => check_type_cxx_vector(cx, ptr),
             Type::Ref(ty) => check_type_ref(cx, ty),
+            Type::Ptr(ty) => check_type_ptr(cx, ty),
             Type::Array(array) => check_type_array(cx, array),
             Type::Fn(ty) => check_type_fn(cx, ty),
             Type::SliceRef(ty) => check_type_slice_ref(cx, ty),
@@ -221,7 +224,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     }
 
     match ty.inner {
-        Type::Fn(_) | Type::Void(_) => {}
+        Type::Fn(_) | Type::Void(_) | Type::Ptr(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow references to references");
             return;
@@ -232,6 +235,12 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     cx.error(ty, "unsupported reference type");
 }
 
+fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
+    if let Type::Ident(_) = ty.inner { return }
+
+    cx.error(ty, "unsupported pointer type");
+}
+
 fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
     let supported = !is_unsized(cx, &ty.inner)
         || match &ty.inner {
@@ -558,6 +567,7 @@ fn is_unsized(cx: &mut Check, ty: &Type) -> bool {
         | Type::SharedPtr(_)
         | Type::WeakPtr(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::SliceRef(_) => false,
     }
@@ -631,6 +641,7 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
         Type::SharedPtr(_) => "shared_ptr".to_owned(),
         Type::WeakPtr(_) => "weak_ptr".to_owned(),
         Type::Ref(_) => "reference".to_owned(),
+        Type::Ptr(_) => "raw pointer".to_owned(),
         Type::Str(_) => "&str".to_owned(),
         Type::CxxVector(_) => "C++ vector".to_owned(),
         Type::SliceRef(_) => "slice".to_owned(),
diff --git a/syntax/impls.rs b/syntax/impls.rs
index ee4b641..0cb20ff 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -5,6 +5,8 @@ use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+use super::Ptr;
+
 impl PartialEq for Include {
     fn eq(&self, other: &Self) -> bool {
         let Include {
@@ -47,6 +49,7 @@ impl Hash for Type {
             Type::SharedPtr(t) => t.hash(state),
             Type::WeakPtr(t) => t.hash(state),
             Type::Ref(t) => t.hash(state),
+            Type::Ptr(t) => t.hash(state),
             Type::Str(t) => t.hash(state),
             Type::RustVec(t) => t.hash(state),
             Type::CxxVector(t) => t.hash(state),
@@ -189,6 +192,42 @@ impl Hash for Ref {
     }
 }
 
+impl Eq for Ptr {}
+
+impl PartialEq for Ptr {
+    fn eq(&self, other: &Ptr) -> bool {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        let Ptr {
+            star: _,
+            mutable: mutable2,
+            inner: inner2,
+            mutability: _,
+            constness: _,
+        } = other;
+        mutable == mutable2 && inner == inner2
+    }
+}
+
+impl Hash for Ptr {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let Ptr {
+            star: _,
+            mutable,
+            inner,
+            mutability: _,
+            constness: _,
+        } = self;
+        mutable.hash(state);
+        inner.hash(state);
+    }
+}
+
 impl Eq for SliceRef {}
 
 impl PartialEq for SliceRef {
diff --git a/syntax/improper.rs b/syntax/improper.rs
index d672e7d..6a9b5ac 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -32,6 +32,7 @@ impl<'a> Types<'a> {
                 Definite(false)
             }
             Type::Ref(ty) => self.determine_improper_ctype(&ty.inner),
+            Type::Ptr(ty) => self.determine_improper_ctype(&ty.inner),
             Type::Array(ty) => self.determine_improper_ctype(&ty.inner),
         }
     }
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 30faccc..87e3454 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -204,6 +204,7 @@ pub enum Type {
     SharedPtr(Box<Ty1>),
     WeakPtr(Box<Ty1>),
     Ref(Box<Ref>),
+    Ptr(Box<Ptr>),
     Str(Box<Ref>),
     CxxVector(Box<Ty1>),
     Fn(Box<Signature>),
@@ -229,6 +230,14 @@ pub struct Ref {
     pub mutability: Option<Token![mut]>,
 }
 
+pub struct Ptr {
+    pub star: Token![*],
+    pub mutable: bool,
+    pub inner: Type,
+    pub mutability: Option<Token![mut]>,
+    pub constness: Option<Token![const]>,
+}
+
 pub struct SliceRef {
     pub ampersand: Token![&],
     pub lifetime: Option<Lifetime>,
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 3dd09f5..8f8075a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -11,7 +11,7 @@ use crate::syntax::{
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
-use syn::parse::{ParseStream, Parser};
+use syn::{TypePtr, parse::{ParseStream, Parser}};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
@@ -21,6 +21,8 @@ use syn::{
     TypeReference, Variant as RustVariant, Visibility,
 };
 
+use super::Ptr;
+
 pub mod kw {
     syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
@@ -547,6 +549,7 @@ fn parse_extern_fn(
         ));
     }
 
+    let unsafety = foreign_fn.sig.unsafety;
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -583,6 +586,11 @@ fn parse_extern_fn(
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     let name = pair(Namespace::default(), &ident, None, None);
+                    if let Type::Ptr(_) = &ty {
+                        if unsafety.is_none() {
+                            return Err(Error::new_spanned(arg, "pointer argument requires that the function be marked unsafe"));
+                        }
+                    }
                     args.push_value(Var {
                         doc,
                         attrs,
@@ -966,6 +974,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
         },
         Type::Ident(_)
         | Type::Ref(_)
+        | Type::Ptr(_)
         | Type::Str(_)
         | Type::Fn(_)
         | Type::Void(_)
@@ -1034,6 +1043,7 @@ fn parse_include(input: ParseStream) -> Result<Include> {
 fn parse_type(ty: &RustType) -> Result<Type> {
     match ty {
         RustType::Reference(ty) => parse_type_reference(ty),
+        RustType::Ptr(ty) => parse_type_ptr(ty),
         RustType::Path(ty) => parse_type_path(ty),
         RustType::Array(ty) => parse_type_array(ty),
         RustType::BareFn(ty) => parse_type_fn(ty),
@@ -1085,6 +1095,26 @@ fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
     })))
 }
 
+fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
+    let star = ty.star_token;
+    let mutable = ty.mutability.is_some();
+    let constness = ty.const_token;
+    let mutability = ty.mutability;
+    if !constness.is_some() && !mutable {
+        return Err(Error::new_spanned(ty, "pointer is neither const nor mut"));
+    }
+
+    let inner = parse_type(&ty.elem)?;
+    
+    Ok(Type::Ptr(Box::new(Ptr {
+        star,
+        mutable,
+        inner,
+        mutability,
+        constness,
+    })))
+}
+
 fn parse_type_path(ty: &TypePath) -> Result<Type> {
     let path = &ty.path;
     if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
diff --git a/syntax/pod.rs b/syntax/pod.rs
index e1c4831..0bf152e 100644
--- a/syntax/pod.rs
+++ b/syntax/pod.rs
@@ -29,7 +29,7 @@ impl<'a> Types<'a> {
             | Type::WeakPtr(_)
             | Type::CxxVector(_)
             | Type::Void(_) => false,
-            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+            Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) | Type::Ptr(_) => true,
             Type::Array(array) => self.is_guaranteed_pod(&array.inner),
         }
     }
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index bb04e16..d728ac0 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -7,6 +7,8 @@ use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::{token, Token};
 
+use super::Ptr;
+
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
@@ -27,6 +29,7 @@ impl ToTokens for Type {
             | Type::CxxVector(ty)
             | Type::RustVec(ty) => ty.to_tokens(tokens),
             Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens),
+            Type::Ptr(p) => p.to_tokens(tokens),
             Type::Array(a) => a.to_tokens(tokens),
             Type::Fn(f) => f.to_tokens(tokens),
             Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())),
@@ -100,6 +103,22 @@ impl ToTokens for Ref {
     }
 }
 
+impl ToTokens for Ptr {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let Ptr {
+            star,
+            mutable: _,
+            inner,
+            mutability,
+            constness,
+        } = self;
+        star.to_tokens(tokens);
+        mutability.to_tokens(tokens);
+        constness.to_tokens(tokens);
+        inner.to_tokens(tokens);
+    }
+}
+
 impl ToTokens for SliceRef {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         let SliceRef {
diff --git a/syntax/types.rs b/syntax/types.rs
index 7bf2baf..031dc08 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -51,6 +51,7 @@ impl<'a> Types<'a> {
                 | Type::CxxVector(ty)
                 | Type::RustVec(ty) => visit(all, &ty.inner),
                 Type::Ref(r) => visit(all, &r.inner),
+                Type::Ptr(p) => visit(all, &p.inner),
                 Type::Array(a) => visit(all, &a.inner),
                 Type::SliceRef(s) => visit(all, &s.inner),
                 Type::Fn(f) => {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 32d739d..5f11a6a 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -121,6 +121,8 @@ pub mod ffi {
         fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
         fn c_return_ns_enum(n: u16) -> AEnum;
         fn c_return_nested_ns_enum(n: u16) -> ABEnum;
+        fn c_return_opaque_raw_ptr(n: usize) -> *const C;
+        fn c_return_opaque_mut_raw_ptr(n: usize) -> *mut C;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -161,6 +163,12 @@ pub mod ffi {
         fn c_take_nested_ns_shared(shared: ABShared);
         fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
         fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
+        /// # Unsafety
+        /// To keep clippy happy.
+        unsafe fn c_take_opaque_mut_raw_ptr(c: *mut C) -> usize;
+        /// # Unsafety
+        /// To keep clippy happy.
+        unsafe fn c_take_opaque_raw_ptr(c: *const C) -> usize;
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 3f2b800..5cd1511 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,6 +207,24 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
+const C* c_return_opaque_raw_ptr(size_t c) {
+  return new C(c);
+}
+
+C* c_return_opaque_mut_raw_ptr(size_t c) {
+  return new C(c);
+}
+
+size_t c_take_opaque_raw_ptr(const C* c) {
+  return c->get();
+}
+
+size_t c_take_opaque_mut_raw_ptr(C* c) {
+  size_t result = c->get();
+  delete c;
+  return result;
+}
+
 Borrow::Borrow(const std::string &s) : s(s) {}
 
 void Borrow::const_member() const {}
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index a28c166..3de24e6 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -118,6 +118,8 @@ Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
+const C* c_return_opaque_raw_ptr(size_t n);
+C* c_return_opaque_mut_raw_ptr(size_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -161,6 +163,8 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
+size_t c_take_opaque_raw_ptr(const C* c);
+size_t c_take_opaque_mut_raw_ptr(C* c);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index e0815a6..2c7f763 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -335,3 +335,19 @@ fn test_extern_opaque() {
     check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap()));
     check!(ffi2::c_take_opaque_ns_ptr(f));
 }
+
+#[test]
+fn test_raw_ptr() {
+    let c = ffi::c_return_opaque_mut_raw_ptr(2023);
+    let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) };
+    assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap());
+    // c will be dropped as it's now in a UniquePtr
+
+    let c2 = ffi::c_return_opaque_mut_raw_ptr(2024);
+    assert_eq!(2024, unsafe { ffi::c_take_opaque_raw_ptr(c2) });
+    assert_eq!(2024, unsafe { ffi::c_take_opaque_mut_raw_ptr(c2) }); // deletes c2
+
+    let c3 = ffi::c_return_opaque_raw_ptr(2025);
+    assert_eq!(2025, unsafe { ffi::c_take_opaque_raw_ptr(c3) });
+    assert_eq!(2025, unsafe { ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C) }); // deletes c3
+}
\ No newline at end of file
diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
new file mode 100644
index 0000000..a3b5cc4
--- /dev/null
+++ b/tests/ui/unsupported_ptr.rs
@@ -0,0 +1,40 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn not_unsafe_ptr(c: *mut C);
+    }
+}
+
+#[cxx::bridge]
+mod ffi2 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_neither_const_nor_mut() -> *C;
+    }
+}
+
+#[cxx::bridge]
+mod ffi3 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_ptr() -> *mut *mut C;
+        fn get_ptr_reference() -> *mut & C;
+        fn get_reference_ptr() -> & *mut C;
+    }
+}
+
+#[cxx::bridge]
+mod ffi4 {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
+        fn get_ptr_unique() -> UniquePtr<*mut C>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
new file mode 100644
index 0000000..03756bf
--- /dev/null
+++ b/tests/ui/unsupported_ptr.stderr
@@ -0,0 +1,49 @@
+error: expected mut or const in raw pointer type
+  --> $DIR/unsupported_ptr.rs:15:43
+   |
+15 |         fn get_neither_const_nor_mut() -> *C;
+   |                                           ^ expected mut or const in raw pointer type
+   |
+   = help: use `*mut T` or `*const T` as appropriate
+
+error: pointer argument requires that the function be marked unsafe
+ --> $DIR/unsupported_ptr.rs:6:27
+  |
+6 |         fn not_unsafe_ptr(c: *mut C);
+  |                           ^^^^^^^^^
+
+error: expected `const` or `mut`
+  --> $DIR/unsupported_ptr.rs:15:44
+   |
+15 |         fn get_neither_const_nor_mut() -> *C;
+   |                                            ^
+
+error: unsupported pointer type
+  --> $DIR/unsupported_ptr.rs:24:29
+   |
+24 |         fn get_ptr_ptr() -> *mut *mut C;
+   |                             ^^^^^^^^^^^
+
+error: unsupported pointer type
+  --> $DIR/unsupported_ptr.rs:25:35
+   |
+25 |         fn get_ptr_reference() -> *mut & C;
+   |                                   ^^^^^^^^
+
+error: unsupported reference type
+  --> $DIR/unsupported_ptr.rs:26:35
+   |
+26 |         fn get_reference_ptr() -> & *mut C;
+   |                                   ^^^^^^^^
+
+error: unsupported vector target type
+  --> $DIR/unsupported_ptr.rs:35:42
+   |
+35 |         fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
+   |                                          ^^^^^^^^^^^^^^^^^^
+
+error: unsupported unique_ptr target type
+  --> $DIR/unsupported_ptr.rs:36:32
+   |
+36 |         fn get_ptr_unique() -> UniquePtr<*mut C>;
+   |                                ^^^^^^^^^^^^^^^^^

From 7c3197eba8902bbdab0025c14e5a9819e6f46a5f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:02 +0000
Subject: [PATCH 2136/2232] Format PR 689 with rustfmt


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 052b248..d2c260d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -236,7 +236,9 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
-    if let Type::Ident(_) = ty.inner { return }
+    if let Type::Ident(_) = ty.inner {
+        return;
+    }
 
     cx.error(ty, "unsupported pointer type");
 }
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8f8075a..f234d5a 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -11,9 +11,12 @@ use crate::syntax::{
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
-use syn::{TypePtr, parse::{ParseStream, Parser}};
 use syn::punctuated::Punctuated;
 use syn::{
+    parse::{ParseStream, Parser},
+    TypePtr,
+};
+use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
@@ -588,7 +591,10 @@ fn parse_extern_fn(
                     let name = pair(Namespace::default(), &ident, None, None);
                     if let Type::Ptr(_) = &ty {
                         if unsafety.is_none() {
-                            return Err(Error::new_spanned(arg, "pointer argument requires that the function be marked unsafe"));
+                            return Err(Error::new_spanned(
+                                arg,
+                                "pointer argument requires that the function be marked unsafe",
+                            ));
                         }
                     }
                     args.push_value(Var {
@@ -1105,7 +1111,7 @@ fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
     }
 
     let inner = parse_type(&ty.elem)?;
-    
+
     Ok(Type::Ptr(Box::new(Ptr {
         star,
         mutable,
diff --git a/tests/test.rs b/tests/test.rs
index 2c7f763..f8ed205 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -349,5 +349,7 @@ fn test_raw_ptr() {
 
     let c3 = ffi::c_return_opaque_raw_ptr(2025);
     assert_eq!(2025, unsafe { ffi::c_take_opaque_raw_ptr(c3) });
-    assert_eq!(2025, unsafe { ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C) }); // deletes c3
-}
\ No newline at end of file
+    assert_eq!(2025, unsafe {
+        ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C)
+    }); // deletes c3
+}
diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
index a3b5cc4..1853060 100644
--- a/tests/ui/unsupported_ptr.rs
+++ b/tests/ui/unsupported_ptr.rs
@@ -22,8 +22,8 @@ mod ffi3 {
         type C;
 
         fn get_ptr_ptr() -> *mut *mut C;
-        fn get_ptr_reference() -> *mut & C;
-        fn get_reference_ptr() -> & *mut C;
+        fn get_ptr_reference() -> *mut &C;
+        fn get_reference_ptr() -> &*mut C;
     }
 }
 
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
index 03756bf..09b8a1e 100644
--- a/tests/ui/unsupported_ptr.stderr
+++ b/tests/ui/unsupported_ptr.stderr
@@ -27,14 +27,14 @@ error: unsupported pointer type
 error: unsupported pointer type
   --> $DIR/unsupported_ptr.rs:25:35
    |
-25 |         fn get_ptr_reference() -> *mut & C;
-   |                                   ^^^^^^^^
+25 |         fn get_ptr_reference() -> *mut &C;
+   |                                   ^^^^^^^
 
 error: unsupported reference type
   --> $DIR/unsupported_ptr.rs:26:35
    |
-26 |         fn get_reference_ptr() -> & *mut C;
-   |                                   ^^^^^^^^
+26 |         fn get_reference_ptr() -> &*mut C;
+   |                                   ^^^^^^^
 
 error: unsupported vector target type
   --> $DIR/unsupported_ptr.rs:35:42

From 274c06f495950f9252064dad3125e50f084732ab Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:04 +0000
Subject: [PATCH 2137/2232] Divide up pointer UI tests


---

diff --git a/tests/ui/ptr_missing_unsafe.rs b/tests/ui/ptr_missing_unsafe.rs
new file mode 100644
index 0000000..56f0007
--- /dev/null
+++ b/tests/ui/ptr_missing_unsafe.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn not_unsafe_ptr(c: *mut C);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_missing_unsafe.stderr b/tests/ui/ptr_missing_unsafe.stderr
new file mode 100644
index 0000000..65f53a9
--- /dev/null
+++ b/tests/ui/ptr_missing_unsafe.stderr
@@ -0,0 +1,5 @@
+error: pointer argument requires that the function be marked unsafe
+ --> $DIR/ptr_missing_unsafe.rs:6:27
+  |
+6 |         fn not_unsafe_ptr(c: *mut C);
+  |                           ^^^^^^^^^
diff --git a/tests/ui/ptr_no_const_mut.rs b/tests/ui/ptr_no_const_mut.rs
new file mode 100644
index 0000000..eecec3f
--- /dev/null
+++ b/tests/ui/ptr_no_const_mut.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_neither_const_nor_mut() -> *C;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_no_const_mut.stderr b/tests/ui/ptr_no_const_mut.stderr
new file mode 100644
index 0000000..8a39185
--- /dev/null
+++ b/tests/ui/ptr_no_const_mut.stderr
@@ -0,0 +1,13 @@
+error: expected mut or const in raw pointer type
+ --> $DIR/ptr_no_const_mut.rs:6:43
+  |
+6 |         fn get_neither_const_nor_mut() -> *C;
+  |                                           ^ expected mut or const in raw pointer type
+  |
+  = help: use `*mut T` or `*const T` as appropriate
+
+error: expected `const` or `mut`
+ --> $DIR/ptr_no_const_mut.rs:6:44
+  |
+6 |         fn get_neither_const_nor_mut() -> *C;
+  |                                            ^
diff --git a/tests/ui/ptr_unsupported.rs b/tests/ui/ptr_unsupported.rs
new file mode 100644
index 0000000..ca1580a
--- /dev/null
+++ b/tests/ui/ptr_unsupported.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_to_ptr() -> *mut *mut C;
+        fn get_ptr_to_reference() -> *mut &C;
+        fn get_reference_to_ptr() -> &*mut C;
+        fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+        fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
new file mode 100644
index 0000000..b5e8a78
--- /dev/null
+++ b/tests/ui/ptr_unsupported.stderr
@@ -0,0 +1,29 @@
+error: unsupported pointer type
+ --> $DIR/ptr_unsupported.rs:6:32
+  |
+6 |         fn get_ptr_to_ptr() -> *mut *mut C;
+  |                                ^^^^^^^^^^^
+
+error: unsupported pointer type
+ --> $DIR/ptr_unsupported.rs:7:38
+  |
+7 |         fn get_ptr_to_reference() -> *mut &C;
+  |                                      ^^^^^^^
+
+error: unsupported reference type
+ --> $DIR/ptr_unsupported.rs:8:38
+  |
+8 |         fn get_reference_to_ptr() -> &*mut C;
+  |                                      ^^^^^^^
+
+error: unsupported unique_ptr target type
+ --> $DIR/ptr_unsupported.rs:9:38
+  |
+9 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+  |                                      ^^^^^^^^^^^^^^^^^
+
+error: unsupported vector target type
+  --> $DIR/ptr_unsupported.rs:10:45
+   |
+10 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+   |                                             ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
deleted file mode 100644
index 1853060..0000000
--- a/tests/ui/unsupported_ptr.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-        type C;
-
-        fn not_unsafe_ptr(c: *mut C);
-    }
-}
-
-#[cxx::bridge]
-mod ffi2 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_neither_const_nor_mut() -> *C;
-    }
-}
-
-#[cxx::bridge]
-mod ffi3 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_ptr_ptr() -> *mut *mut C;
-        fn get_ptr_reference() -> *mut &C;
-        fn get_reference_ptr() -> &*mut C;
-    }
-}
-
-#[cxx::bridge]
-mod ffi4 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
-        fn get_ptr_unique() -> UniquePtr<*mut C>;
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
deleted file mode 100644
index 09b8a1e..0000000
--- a/tests/ui/unsupported_ptr.stderr
+++ /dev/null
@@ -1,49 +0,0 @@
-error: expected mut or const in raw pointer type
-  --> $DIR/unsupported_ptr.rs:15:43
-   |
-15 |         fn get_neither_const_nor_mut() -> *C;
-   |                                           ^ expected mut or const in raw pointer type
-   |
-   = help: use `*mut T` or `*const T` as appropriate
-
-error: pointer argument requires that the function be marked unsafe
- --> $DIR/unsupported_ptr.rs:6:27
-  |
-6 |         fn not_unsafe_ptr(c: *mut C);
-  |                           ^^^^^^^^^
-
-error: expected `const` or `mut`
-  --> $DIR/unsupported_ptr.rs:15:44
-   |
-15 |         fn get_neither_const_nor_mut() -> *C;
-   |                                            ^
-
-error: unsupported pointer type
-  --> $DIR/unsupported_ptr.rs:24:29
-   |
-24 |         fn get_ptr_ptr() -> *mut *mut C;
-   |                             ^^^^^^^^^^^
-
-error: unsupported pointer type
-  --> $DIR/unsupported_ptr.rs:25:35
-   |
-25 |         fn get_ptr_reference() -> *mut &C;
-   |                                   ^^^^^^^
-
-error: unsupported reference type
-  --> $DIR/unsupported_ptr.rs:26:35
-   |
-26 |         fn get_reference_ptr() -> &*mut C;
-   |                                   ^^^^^^^
-
-error: unsupported vector target type
-  --> $DIR/unsupported_ptr.rs:35:42
-   |
-35 |         fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
-   |                                          ^^^^^^^^^^^^^^^^^^
-
-error: unsupported unique_ptr target type
-  --> $DIR/unsupported_ptr.rs:36:32
-   |
-36 |         fn get_ptr_unique() -> UniquePtr<*mut C>;
-   |                                ^^^^^^^^^^^^^^^^^

From d0af9d320e8f9615e12537cb180959913fa3bfed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:05 +0000
Subject: [PATCH 2138/2232] Disable missing Unsafety doc comment clippy lint for test suite


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5f11a6a..3736b9e 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -2,6 +2,7 @@
     clippy::boxed_local,
     clippy::just_underscores_and_digits,
     clippy::let_underscore_drop,
+    clippy::missing_safety_doc,
     clippy::must_use_candidate,
     clippy::needless_lifetimes,
     clippy::needless_pass_by_value,
@@ -163,11 +164,7 @@ pub mod ffi {
         fn c_take_nested_ns_shared(shared: ABShared);
         fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
         fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
-        /// # Unsafety
-        /// To keep clippy happy.
         unsafe fn c_take_opaque_mut_raw_ptr(c: *mut C) -> usize;
-        /// # Unsafety
-        /// To keep clippy happy.
         unsafe fn c_take_opaque_raw_ptr(c: *const C) -> usize;
 
         fn c_try_return_void() -> Result<()>;

From 7bb11c30ce6ee43cc3ef6dcf63d158bd7d12421e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:05 +0000
Subject: [PATCH 2139/2232] Sort pointer ffi test functions consistently


---

diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 3736b9e..fcbe153 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -122,8 +122,8 @@ pub mod ffi {
         fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
         fn c_return_ns_enum(n: u16) -> AEnum;
         fn c_return_nested_ns_enum(n: u16) -> ABEnum;
-        fn c_return_opaque_raw_ptr(n: usize) -> *const C;
-        fn c_return_opaque_mut_raw_ptr(n: usize) -> *mut C;
+        fn c_return_const_ptr(n: usize) -> *const C;
+        fn c_return_mut_ptr(n: usize) -> *mut C;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -164,8 +164,8 @@ pub mod ffi {
         fn c_take_nested_ns_shared(shared: ABShared);
         fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
         fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
-        unsafe fn c_take_opaque_mut_raw_ptr(c: *mut C) -> usize;
-        unsafe fn c_take_opaque_raw_ptr(c: *const C) -> usize;
+        unsafe fn c_take_const_ptr(c: *const C) -> usize;
+        unsafe fn c_take_mut_ptr(c: *mut C) -> usize;
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 5cd1511..eb855ea 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,24 +207,14 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
-const C* c_return_opaque_raw_ptr(size_t c) {
+const C* c_return_const_ptr(size_t c) {
   return new C(c);
 }
 
-C* c_return_opaque_mut_raw_ptr(size_t c) {
+C* c_return_mut_ptr(size_t c) {
   return new C(c);
 }
 
-size_t c_take_opaque_raw_ptr(const C* c) {
-  return c->get();
-}
-
-size_t c_take_opaque_mut_raw_ptr(C* c) {
-  size_t result = c->get();
-  delete c;
-  return result;
-}
-
 Borrow::Borrow(const std::string &s) : s(s) {}
 
 void Borrow::const_member() const {}
@@ -526,6 +516,16 @@ void c_take_nested_ns_enum(::A::B::ABEnum e) {
   }
 }
 
+size_t c_take_const_ptr(const C* c) {
+  return c->get();
+}
+
+size_t c_take_mut_ptr(C* c) {
+  size_t result = c->get();
+  delete c;
+  return result;
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3de24e6..8c08e4c 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -118,8 +118,8 @@ Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
-const C* c_return_opaque_raw_ptr(size_t n);
-C* c_return_opaque_mut_raw_ptr(size_t n);
+const C* c_return_const_ptr(size_t n);
+C* c_return_mut_ptr(size_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -163,8 +163,8 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
-size_t c_take_opaque_raw_ptr(const C* c);
-size_t c_take_opaque_mut_raw_ptr(C* c);
+size_t c_take_const_ptr(const C* c);
+size_t c_take_mut_ptr(C* c);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index f8ed205..32b8e83 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -338,18 +338,16 @@ fn test_extern_opaque() {
 
 #[test]
 fn test_raw_ptr() {
-    let c = ffi::c_return_opaque_mut_raw_ptr(2023);
+    let c = ffi::c_return_mut_ptr(2023);
     let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) };
     assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap());
     // c will be dropped as it's now in a UniquePtr
 
-    let c2 = ffi::c_return_opaque_mut_raw_ptr(2024);
-    assert_eq!(2024, unsafe { ffi::c_take_opaque_raw_ptr(c2) });
-    assert_eq!(2024, unsafe { ffi::c_take_opaque_mut_raw_ptr(c2) }); // deletes c2
+    let c2 = ffi::c_return_mut_ptr(2024);
+    assert_eq!(2024, unsafe { ffi::c_take_const_ptr(c2) });
+    assert_eq!(2024, unsafe { ffi::c_take_mut_ptr(c2) }); // deletes c2
 
-    let c3 = ffi::c_return_opaque_raw_ptr(2025);
-    assert_eq!(2025, unsafe { ffi::c_take_opaque_raw_ptr(c3) });
-    assert_eq!(2025, unsafe {
-        ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C)
-    }); // deletes c3
+    let c3 = ffi::c_return_const_ptr(2025);
+    assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) });
+    assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3
 }

From 824d691923433d1a5c4abb760324c2f7a25986ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:06 +0000
Subject: [PATCH 2140/2232] Format PR 689 with clang-format


---

diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index eb855ea..831097d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,13 +207,9 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
-const C* c_return_const_ptr(size_t c) {
-  return new C(c);
-}
+const C *c_return_const_ptr(size_t c) { return new C(c); }
 
-C* c_return_mut_ptr(size_t c) {
-  return new C(c);
-}
+C *c_return_mut_ptr(size_t c) { return new C(c); }
 
 Borrow::Borrow(const std::string &s) : s(s) {}
 
@@ -516,11 +512,9 @@ void c_take_nested_ns_enum(::A::B::ABEnum e) {
   }
 }
 
-size_t c_take_const_ptr(const C* c) {
-  return c->get();
-}
+size_t c_take_const_ptr(const C *c) { return c->get(); }
 
-size_t c_take_mut_ptr(C* c) {
+size_t c_take_mut_ptr(C *c) {
   size_t result = c->get();
   delete c;
   return result;
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 8c08e4c..eaa4361 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -118,8 +118,8 @@ Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
-const C* c_return_const_ptr(size_t n);
-C* c_return_mut_ptr(size_t n);
+const C *c_return_const_ptr(size_t n);
+C *c_return_mut_ptr(size_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -163,8 +163,8 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
-size_t c_take_const_ptr(const C* c);
-size_t c_take_mut_ptr(C* c);
+size_t c_take_const_ptr(const C *c);
+size_t c_take_mut_ptr(C *c);
 
 void c_try_return_void();
 size_t c_try_return_primitive();

From 94909e0a6e4e9cc5d03df6d4f051643bda60faf7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:07 +0000
Subject: [PATCH 2141/2232] Remove duplicate unsafety parse from PR 689


---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index f234d5a..2605218 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -633,7 +633,6 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
     let visibility = visibility_pub(&foreign_fn.vis, inherited_span);

From beba43d024ea73a0a64ba9ab4eecb15120ce71a7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:07 +0000
Subject: [PATCH 2142/2232] Touch up PR 689 imports


---

diff --git a/syntax/check.rs b/syntax/check.rs
index d2c260d..0009eb1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,15 +1,13 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
-    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Receiver,
-    Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Ptr,
+    Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
 
-use super::Ptr;
-
 pub(crate) struct Check<'a> {
     apis: &'a [Api],
     types: &'a Types<'a>,
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 0cb20ff..8b0743b 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,12 +1,10 @@
 use crate::syntax::{
-    Array, ExternFn, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
+    Array, ExternFn, Include, Lifetimes, Ptr, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
-use super::Ptr;
-
 impl PartialEq for Include {
     fn eq(&self, other: &Self) -> bool {
         let Include {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 2605218..0050de9 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,27 +5,22 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
-    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
-    Struct, Ty1, Type, TypeAlias, Var, Variant,
+    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, Signature,
+    SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
+use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
-    parse::{ParseStream, Parser},
-    TypePtr,
-};
-use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
-    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath,
+    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr,
     TypeReference, Variant as RustVariant, Visibility,
 };
 
-use super::Ptr;
-
 pub mod kw {
     syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index d728ac0..13b5cd3 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,14 +1,12 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Receiver, Ref,
-    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Ptr, Receiver,
+    Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::{token, Token};
 
-use super::Ptr;
-
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {

From b70310b76046d51e9c3420c948a4d9ead7d1d69d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:06:08 +0000
Subject: [PATCH 2143/2232] Remove unneeded pointer parse check


A pointer with neither `const` nor `mut` would not have parsed as a
syn::Type::Ptr.

---

diff --git a/syntax/parse.rs b/syntax/parse.rs
index 0050de9..51b5e4b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -1100,9 +1100,6 @@ fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
     let mutable = ty.mutability.is_some();
     let constness = ty.const_token;
     let mutability = ty.mutability;
-    if !constness.is_some() && !mutable {
-        return Err(Error::new_spanned(ty, "pointer is neither const nor mut"));
-    }
 
     let inner = parse_type(&ty.elem)?;
 

From a3ef34f95bc18a8ec7c7c6d8768d002062345221 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:11:58 +0000
Subject: [PATCH 2144/2232] Merge pull request #745 from dtolnay/pointers


Touch up PR 689
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 052b248..0009eb1 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,15 +1,13 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
 use crate::syntax::{
-    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Receiver,
-    Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
+    error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Ptr,
+    Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
 };
 use proc_macro2::{Delimiter, Group, Ident, TokenStream};
 use quote::{quote, ToTokens};
 use std::fmt::Display;
 
-use super::Ptr;
-
 pub(crate) struct Check<'a> {
     apis: &'a [Api],
     types: &'a Types<'a>,
@@ -236,7 +234,9 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
-    if let Type::Ident(_) = ty.inner { return }
+    if let Type::Ident(_) = ty.inner {
+        return;
+    }
 
     cx.error(ty, "unsupported pointer type");
 }
diff --git a/syntax/impls.rs b/syntax/impls.rs
index 0cb20ff..8b0743b 100644
--- a/syntax/impls.rs
+++ b/syntax/impls.rs
@@ -1,12 +1,10 @@
 use crate::syntax::{
-    Array, ExternFn, Include, Lifetimes, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
+    Array, ExternFn, Include, Lifetimes, Ptr, Receiver, Ref, Signature, SliceRef, Ty1, Type, Var,
 };
 use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
-use super::Ptr;
-
 impl PartialEq for Include {
     fn eq(&self, other: &Self) -> bool {
         let Include {
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 8f8075a..51b5e4b 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -5,24 +5,22 @@ use crate::syntax::report::Errors;
 use crate::syntax::Atom::*;
 use crate::syntax::{
     attrs, error, Api, Array, Derive, Doc, Enum, ExternFn, ExternType, ForeignName, Impl, Include,
-    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Receiver, Ref, Signature, SliceRef,
-    Struct, Ty1, Type, TypeAlias, Var, Variant,
+    IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, Signature,
+    SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
 };
 use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
 use quote::{format_ident, quote, quote_spanned};
 use std::mem;
-use syn::{TypePtr, parse::{ParseStream, Parser}};
+use syn::parse::{ParseStream, Parser};
 use syn::punctuated::Punctuated;
 use syn::{
     Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
     GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
     Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
-    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath,
+    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr,
     TypeReference, Variant as RustVariant, Visibility,
 };
 
-use super::Ptr;
-
 pub mod kw {
     syn::custom_keyword!(Pin);
     syn::custom_keyword!(Result);
@@ -588,7 +586,10 @@ fn parse_extern_fn(
                     let name = pair(Namespace::default(), &ident, None, None);
                     if let Type::Ptr(_) = &ty {
                         if unsafety.is_none() {
-                            return Err(Error::new_spanned(arg, "pointer argument requires that the function be marked unsafe"));
+                            return Err(Error::new_spanned(
+                                arg,
+                                "pointer argument requires that the function be marked unsafe",
+                            ));
                         }
                     }
                     args.push_value(Var {
@@ -627,7 +628,6 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
-    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
     let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
@@ -1100,12 +1100,9 @@ fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
     let mutable = ty.mutability.is_some();
     let constness = ty.const_token;
     let mutability = ty.mutability;
-    if !constness.is_some() && !mutable {
-        return Err(Error::new_spanned(ty, "pointer is neither const nor mut"));
-    }
 
     let inner = parse_type(&ty.elem)?;
-    
+
     Ok(Type::Ptr(Box::new(Ptr {
         star,
         mutable,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index d728ac0..13b5cd3 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,14 +1,12 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::{
-    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Receiver, Ref,
-    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+    Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Lifetimes, NamedType, Ptr, Receiver,
+    Ref, Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{quote_spanned, ToTokens};
 use syn::{token, Token};
 
-use super::Ptr;
-
 impl ToTokens for Type {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         match self {
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index 5f11a6a..fcbe153 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -2,6 +2,7 @@
     clippy::boxed_local,
     clippy::just_underscores_and_digits,
     clippy::let_underscore_drop,
+    clippy::missing_safety_doc,
     clippy::must_use_candidate,
     clippy::needless_lifetimes,
     clippy::needless_pass_by_value,
@@ -121,8 +122,8 @@ pub mod ffi {
         fn c_return_nested_ns_ref(shared: &ABShared) -> &usize;
         fn c_return_ns_enum(n: u16) -> AEnum;
         fn c_return_nested_ns_enum(n: u16) -> ABEnum;
-        fn c_return_opaque_raw_ptr(n: usize) -> *const C;
-        fn c_return_opaque_mut_raw_ptr(n: usize) -> *mut C;
+        fn c_return_const_ptr(n: usize) -> *const C;
+        fn c_return_mut_ptr(n: usize) -> *mut C;
 
         fn c_take_primitive(n: usize);
         fn c_take_shared(shared: Shared);
@@ -163,12 +164,8 @@ pub mod ffi {
         fn c_take_nested_ns_shared(shared: ABShared);
         fn c_take_rust_vec_ns_shared(v: Vec<AShared>);
         fn c_take_rust_vec_nested_ns_shared(v: Vec<ABShared>);
-        /// # Unsafety
-        /// To keep clippy happy.
-        unsafe fn c_take_opaque_mut_raw_ptr(c: *mut C) -> usize;
-        /// # Unsafety
-        /// To keep clippy happy.
-        unsafe fn c_take_opaque_raw_ptr(c: *const C) -> usize;
+        unsafe fn c_take_const_ptr(c: *const C) -> usize;
+        unsafe fn c_take_mut_ptr(c: *mut C) -> usize;
 
         fn c_try_return_void() -> Result<()>;
         fn c_try_return_primitive() -> Result<usize>;
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 5cd1511..831097d 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -207,23 +207,9 @@ Enum c_return_enum(uint16_t n) {
   }
 }
 
-const C* c_return_opaque_raw_ptr(size_t c) {
-  return new C(c);
-}
-
-C* c_return_opaque_mut_raw_ptr(size_t c) {
-  return new C(c);
-}
+const C *c_return_const_ptr(size_t c) { return new C(c); }
 
-size_t c_take_opaque_raw_ptr(const C* c) {
-  return c->get();
-}
-
-size_t c_take_opaque_mut_raw_ptr(C* c) {
-  size_t result = c->get();
-  delete c;
-  return result;
-}
+C *c_return_mut_ptr(size_t c) { return new C(c); }
 
 Borrow::Borrow(const std::string &s) : s(s) {}
 
@@ -526,6 +512,14 @@ void c_take_nested_ns_enum(::A::B::ABEnum e) {
   }
 }
 
+size_t c_take_const_ptr(const C *c) { return c->get(); }
+
+size_t c_take_mut_ptr(C *c) {
+  size_t result = c->get();
+  delete c;
+  return result;
+}
+
 void c_try_return_void() {}
 
 size_t c_try_return_primitive() { return 2020; }
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 3de24e6..eaa4361 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -118,8 +118,8 @@ Enum c_return_enum(uint16_t n);
 ::A::AEnum c_return_ns_enum(uint16_t n);
 ::A::B::ABEnum c_return_nested_ns_enum(uint16_t n);
 std::unique_ptr<Borrow> c_return_borrow(const std::string &s);
-const C* c_return_opaque_raw_ptr(size_t n);
-C* c_return_opaque_mut_raw_ptr(size_t n);
+const C *c_return_const_ptr(size_t n);
+C *c_return_mut_ptr(size_t n);
 
 void c_take_primitive(size_t n);
 void c_take_shared(Shared shared);
@@ -163,8 +163,8 @@ void c_take_callback(rust::Fn<size_t(rust::String)> callback);
 void c_take_enum(Enum e);
 void c_take_ns_enum(::A::AEnum e);
 void c_take_nested_ns_enum(::A::B::ABEnum e);
-size_t c_take_opaque_raw_ptr(const C* c);
-size_t c_take_opaque_mut_raw_ptr(C* c);
+size_t c_take_const_ptr(const C *c);
+size_t c_take_mut_ptr(C *c);
 
 void c_try_return_void();
 size_t c_try_return_primitive();
diff --git a/tests/test.rs b/tests/test.rs
index 2c7f763..32b8e83 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -338,16 +338,16 @@ fn test_extern_opaque() {
 
 #[test]
 fn test_raw_ptr() {
-    let c = ffi::c_return_opaque_mut_raw_ptr(2023);
+    let c = ffi::c_return_mut_ptr(2023);
     let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) };
     assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap());
     // c will be dropped as it's now in a UniquePtr
 
-    let c2 = ffi::c_return_opaque_mut_raw_ptr(2024);
-    assert_eq!(2024, unsafe { ffi::c_take_opaque_raw_ptr(c2) });
-    assert_eq!(2024, unsafe { ffi::c_take_opaque_mut_raw_ptr(c2) }); // deletes c2
+    let c2 = ffi::c_return_mut_ptr(2024);
+    assert_eq!(2024, unsafe { ffi::c_take_const_ptr(c2) });
+    assert_eq!(2024, unsafe { ffi::c_take_mut_ptr(c2) }); // deletes c2
 
-    let c3 = ffi::c_return_opaque_raw_ptr(2025);
-    assert_eq!(2025, unsafe { ffi::c_take_opaque_raw_ptr(c3) });
-    assert_eq!(2025, unsafe { ffi::c_take_opaque_mut_raw_ptr(c3 as *mut ffi::C) }); // deletes c3
-}
\ No newline at end of file
+    let c3 = ffi::c_return_const_ptr(2025);
+    assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) });
+    assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3
+}
diff --git a/tests/ui/ptr_missing_unsafe.rs b/tests/ui/ptr_missing_unsafe.rs
new file mode 100644
index 0000000..56f0007
--- /dev/null
+++ b/tests/ui/ptr_missing_unsafe.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn not_unsafe_ptr(c: *mut C);
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_missing_unsafe.stderr b/tests/ui/ptr_missing_unsafe.stderr
new file mode 100644
index 0000000..65f53a9
--- /dev/null
+++ b/tests/ui/ptr_missing_unsafe.stderr
@@ -0,0 +1,5 @@
+error: pointer argument requires that the function be marked unsafe
+ --> $DIR/ptr_missing_unsafe.rs:6:27
+  |
+6 |         fn not_unsafe_ptr(c: *mut C);
+  |                           ^^^^^^^^^
diff --git a/tests/ui/ptr_no_const_mut.rs b/tests/ui/ptr_no_const_mut.rs
new file mode 100644
index 0000000..eecec3f
--- /dev/null
+++ b/tests/ui/ptr_no_const_mut.rs
@@ -0,0 +1,10 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_neither_const_nor_mut() -> *C;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_no_const_mut.stderr b/tests/ui/ptr_no_const_mut.stderr
new file mode 100644
index 0000000..8a39185
--- /dev/null
+++ b/tests/ui/ptr_no_const_mut.stderr
@@ -0,0 +1,13 @@
+error: expected mut or const in raw pointer type
+ --> $DIR/ptr_no_const_mut.rs:6:43
+  |
+6 |         fn get_neither_const_nor_mut() -> *C;
+  |                                           ^ expected mut or const in raw pointer type
+  |
+  = help: use `*mut T` or `*const T` as appropriate
+
+error: expected `const` or `mut`
+ --> $DIR/ptr_no_const_mut.rs:6:44
+  |
+6 |         fn get_neither_const_nor_mut() -> *C;
+  |                                            ^
diff --git a/tests/ui/ptr_unsupported.rs b/tests/ui/ptr_unsupported.rs
new file mode 100644
index 0000000..ca1580a
--- /dev/null
+++ b/tests/ui/ptr_unsupported.rs
@@ -0,0 +1,14 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type C;
+
+        fn get_ptr_to_ptr() -> *mut *mut C;
+        fn get_ptr_to_reference() -> *mut &C;
+        fn get_reference_to_ptr() -> &*mut C;
+        fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+        fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
new file mode 100644
index 0000000..b5e8a78
--- /dev/null
+++ b/tests/ui/ptr_unsupported.stderr
@@ -0,0 +1,29 @@
+error: unsupported pointer type
+ --> $DIR/ptr_unsupported.rs:6:32
+  |
+6 |         fn get_ptr_to_ptr() -> *mut *mut C;
+  |                                ^^^^^^^^^^^
+
+error: unsupported pointer type
+ --> $DIR/ptr_unsupported.rs:7:38
+  |
+7 |         fn get_ptr_to_reference() -> *mut &C;
+  |                                      ^^^^^^^
+
+error: unsupported reference type
+ --> $DIR/ptr_unsupported.rs:8:38
+  |
+8 |         fn get_reference_to_ptr() -> &*mut C;
+  |                                      ^^^^^^^
+
+error: unsupported unique_ptr target type
+ --> $DIR/ptr_unsupported.rs:9:38
+  |
+9 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+  |                                      ^^^^^^^^^^^^^^^^^
+
+error: unsupported vector target type
+  --> $DIR/ptr_unsupported.rs:10:45
+   |
+10 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+   |                                             ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unsupported_ptr.rs b/tests/ui/unsupported_ptr.rs
deleted file mode 100644
index a3b5cc4..0000000
--- a/tests/ui/unsupported_ptr.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-        type C;
-
-        fn not_unsafe_ptr(c: *mut C);
-    }
-}
-
-#[cxx::bridge]
-mod ffi2 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_neither_const_nor_mut() -> *C;
-    }
-}
-
-#[cxx::bridge]
-mod ffi3 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_ptr_ptr() -> *mut *mut C;
-        fn get_ptr_reference() -> *mut & C;
-        fn get_reference_ptr() -> & *mut C;
-    }
-}
-
-#[cxx::bridge]
-mod ffi4 {
-    unsafe extern "C++" {
-        type C;
-
-        fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
-        fn get_ptr_unique() -> UniquePtr<*mut C>;
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/unsupported_ptr.stderr b/tests/ui/unsupported_ptr.stderr
deleted file mode 100644
index 03756bf..0000000
--- a/tests/ui/unsupported_ptr.stderr
+++ /dev/null
@@ -1,49 +0,0 @@
-error: expected mut or const in raw pointer type
-  --> $DIR/unsupported_ptr.rs:15:43
-   |
-15 |         fn get_neither_const_nor_mut() -> *C;
-   |                                           ^ expected mut or const in raw pointer type
-   |
-   = help: use `*mut T` or `*const T` as appropriate
-
-error: pointer argument requires that the function be marked unsafe
- --> $DIR/unsupported_ptr.rs:6:27
-  |
-6 |         fn not_unsafe_ptr(c: *mut C);
-  |                           ^^^^^^^^^
-
-error: expected `const` or `mut`
-  --> $DIR/unsupported_ptr.rs:15:44
-   |
-15 |         fn get_neither_const_nor_mut() -> *C;
-   |                                            ^
-
-error: unsupported pointer type
-  --> $DIR/unsupported_ptr.rs:24:29
-   |
-24 |         fn get_ptr_ptr() -> *mut *mut C;
-   |                             ^^^^^^^^^^^
-
-error: unsupported pointer type
-  --> $DIR/unsupported_ptr.rs:25:35
-   |
-25 |         fn get_ptr_reference() -> *mut & C;
-   |                                   ^^^^^^^^
-
-error: unsupported reference type
-  --> $DIR/unsupported_ptr.rs:26:35
-   |
-26 |         fn get_reference_ptr() -> & *mut C;
-   |                                   ^^^^^^^^
-
-error: unsupported vector target type
-  --> $DIR/unsupported_ptr.rs:35:42
-   |
-35 |         fn get_ptr_vector() -> UniquePtr<CxxVector<*mut C>>;
-   |                                          ^^^^^^^^^^^^^^^^^^
-
-error: unsupported unique_ptr target type
-  --> $DIR/unsupported_ptr.rs:36:32
-   |
-36 |         fn get_ptr_unique() -> UniquePtr<*mut C>;
-   |                                ^^^^^^^^^^^^^^^^^

From 285779635a47ce922afc294bb3bab8c8764f20cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:12:06 +0000
Subject: [PATCH 2145/2232] Defer unsafety check for fn with ptr argument


That error does not need to be fatal at parse time, because the parser
still understands exactly what was written. We accumulate and emit it
alongside other type errors that might be present in the same function
signature.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0009eb1..2c03bdf 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -425,6 +425,13 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                     "passing a function pointer from C++ to Rust is not implemented yet",
                 );
             }
+        } else if let Type::Ptr(_) = arg.ty {
+            if efn.sig.unsafety.is_none() {
+                cx.error(
+                    arg,
+                    "pointer argument requires that the function be marked unsafe",
+                );
+            }
         } else if is_unsized(cx, &arg.ty) {
             let desc = describe(cx, &arg.ty);
             let msg = format!("passing {} by value is not supported", desc);
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 51b5e4b..d792076 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -547,7 +547,6 @@ fn parse_extern_fn(
         ));
     }
 
-    let unsafety = foreign_fn.sig.unsafety;
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -584,14 +583,6 @@ fn parse_extern_fn(
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     let name = pair(Namespace::default(), &ident, None, None);
-                    if let Type::Ptr(_) = &ty {
-                        if unsafety.is_none() {
-                            return Err(Error::new_spanned(
-                                arg,
-                                "pointer argument requires that the function be marked unsafe",
-                            ));
-                        }
-                    }
                     args.push_value(Var {
                         doc,
                         attrs,
@@ -628,6 +619,7 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
+    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
     let visibility = visibility_pub(&foreign_fn.vis, inherited_span);

From b47185f7e32ddd9e0dd425b77de837e1c2397a49 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:13:52 +0000
Subject: [PATCH 2146/2232] Order raw ptrs just above function ptrs in bindings list


---

diff --git a/README.md b/README.md
index c5d93ae..14e5a79 100644
--- a/README.md
+++ b/README.md
@@ -331,9 +331,9 @@ returns of functions.
 <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
-<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 9ba0c41..673008a 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -20,9 +20,9 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
-<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 </table>
 
 <br>

From 420de8713026f4885c2919f9ca33c6de5a7baf20 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:13:52 +0000
Subject: [PATCH 2147/2232] Register raw ptrs page in book table of contents


Otherwise the page does not even get rendered by mdbook.

---

diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 4987694..a8f89bf 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -32,5 +32,6 @@
     - [SharedPtr\<T\> &mdash; std::shared\_ptr\<T\>](binding/sharedptr.md)
     - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
     - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
+    - [*mut T, *const T raw pointers](binding/rawptr.md)
     - [Function pointers](binding/fn.md)
     - [Result\<T\>](binding/result.md)
diff --git a/book/src/binding/raw_ptr.md b/book/src/binding/raw_ptr.md
deleted file mode 100644
index 7ad6475..0000000
--- a/book/src/binding/raw_ptr.md
+++ /dev/null
@@ -1,68 +0,0 @@
-{{#title *mut T, *const T — Rust ♡ C++}}
-# *mut T, *const T - Raw Pointers
-
-cxx supports tranfer of raw pointers across the FFI boundary.
-
-Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
-or references. You should resort to using raw pointers only where lifetimes
-are too complicated to model with standard cxx facilities.
-
-As is normal with raw pointers in Rust, you'll need to use `unsafe` when
-working with them. In particular, to pass any raw pointer into a cxx
-bridge function you will need to declare the function `unsafe`, even if
-the overall `extern "C++"` section is already marked as `unsafe`. By calling
-such a function, you're committing that you - the human - know enough about
-the lifetimes of those objects that the compiler doesn't need to do checks.
-
-On the other hand, C++ functions can freely return raw pointers to
-Rust without `unsafe`, but actually using those raw pointers in any way is likely
-to require an `unsafe` keyword.
-
-## Example
-
-```rust,noplayground
-// src/main.rs
-
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-
-        include!("tests/ffi/tests.h");
-        //include!("example/include/container.h");
-
-        type ComplexHierarchicContainer;
-
-        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
-        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
-        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
-        // ...
-    }
-}
-
-fn main() {
-    let mut container = ffi17::new_hierarchic_container();
-    cxx::let_cxx_string!(key = "a");
-    let mut subcontainer = container.pin_mut().add_child(&key);
-    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
-    cxx::let_cxx_string!(key2 = "b");
-    cxx::let_cxx_string!(value = "c");
-    subcontainer.add_value(&key2, &value);
-    // ...
-}
-```
-
-```cpp
-// include/container.h
-
-#pragma once
-
-class ComplexHierarchicContainer {
-public:
-    ComplexHierarchicContainer();
-    void add_value(const std::string& key, const std::string& value);
-    ComplexHierarchicContainer* add_child(const std::string& key);
-    // ...
-};
-
-std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
-```
diff --git a/book/src/binding/rawptr.md b/book/src/binding/rawptr.md
new file mode 100644
index 0000000..7ad6475
--- /dev/null
+++ b/book/src/binding/rawptr.md
@@ -0,0 +1,68 @@
+{{#title *mut T, *const T — Rust ♡ C++}}
+# *mut T, *const T - Raw Pointers
+
+cxx supports tranfer of raw pointers across the FFI boundary.
+
+Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
+or references. You should resort to using raw pointers only where lifetimes
+are too complicated to model with standard cxx facilities.
+
+As is normal with raw pointers in Rust, you'll need to use `unsafe` when
+working with them. In particular, to pass any raw pointer into a cxx
+bridge function you will need to declare the function `unsafe`, even if
+the overall `extern "C++"` section is already marked as `unsafe`. By calling
+such a function, you're committing that you - the human - know enough about
+the lifetimes of those objects that the compiler doesn't need to do checks.
+
+On the other hand, C++ functions can freely return raw pointers to
+Rust without `unsafe`, but actually using those raw pointers in any way is likely
+to require an `unsafe` keyword.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+
+        include!("tests/ffi/tests.h");
+        //include!("example/include/container.h");
+
+        type ComplexHierarchicContainer;
+
+        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
+        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
+        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
+        // ...
+    }
+}
+
+fn main() {
+    let mut container = ffi17::new_hierarchic_container();
+    cxx::let_cxx_string!(key = "a");
+    let mut subcontainer = container.pin_mut().add_child(&key);
+    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
+    cxx::let_cxx_string!(key2 = "b");
+    cxx::let_cxx_string!(value = "c");
+    subcontainer.add_value(&key2, &value);
+    // ...
+}
+```
+
+```cpp
+// include/container.h
+
+#pragma once
+
+class ComplexHierarchicContainer {
+public:
+    ComplexHierarchicContainer();
+    void add_value(const std::string& key, const std::string& value);
+    ComplexHierarchicContainer* add_child(const std::string& key);
+    // ...
+};
+
+std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 673008a..1e8d684 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -20,7 +20,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
 </table>

From abe4ca47e3eca8b550500098ba54fd181798edeb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:13:52 +0000
Subject: [PATCH 2148/2232] Document restriction on passing raw ptr as argument


---

diff --git a/README.md b/README.md
index 14e5a79..7dd4ded 100644
--- a/README.md
+++ b/README.md
@@ -331,7 +331,7 @@ returns of functions.
 <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
+<tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 </table>
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 1e8d684..bab1e31 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -20,7 +20,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
 </table>

From bbb22b2b4e1365dc290f697956200e013f043da3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:13:52 +0000
Subject: [PATCH 2149/2232] Fix order of Rust version of T* vs const T*


---

diff --git a/book/src/bindings.md b/book/src/bindings.md
index bab1e31..bcb51d8 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -20,7 +20,7 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
-<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*mut T, *const T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
 </table>

From 75b487285fbf91dea6a0b2da6f70ff0614b4b669 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:13:53 +0000
Subject: [PATCH 2150/2232] Add raw pointer to builtin types list in crate-level rustdoc


---

diff --git a/src/lib.rs b/src/lib.rs
index 57bcbfb..f7c694a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -340,6 +340,7 @@
 //! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>

From d6c1cb21f4004f77cc7664e3cfc97cdba8c43ade Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:18:08 +0000
Subject: [PATCH 2151/2232] Merge pull request #746 from dtolnay/pointers


Defer unsafety check for fn with ptr argument
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 0009eb1..2c03bdf 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -425,6 +425,13 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
                     "passing a function pointer from C++ to Rust is not implemented yet",
                 );
             }
+        } else if let Type::Ptr(_) = arg.ty {
+            if efn.sig.unsafety.is_none() {
+                cx.error(
+                    arg,
+                    "pointer argument requires that the function be marked unsafe",
+                );
+            }
         } else if is_unsized(cx, &arg.ty) {
             let desc = describe(cx, &arg.ty);
             let msg = format!("passing {} by value is not supported", desc);
diff --git a/syntax/parse.rs b/syntax/parse.rs
index 51b5e4b..d792076 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -547,7 +547,6 @@ fn parse_extern_fn(
         ));
     }
 
-    let unsafety = foreign_fn.sig.unsafety;
     let mut receiver = None;
     let mut args = Punctuated::new();
     for arg in foreign_fn.sig.inputs.pairs() {
@@ -584,14 +583,6 @@ fn parse_extern_fn(
                     let attrs = OtherAttrs::none();
                     let visibility = Token![pub](ident.span());
                     let name = pair(Namespace::default(), &ident, None, None);
-                    if let Type::Ptr(_) = &ty {
-                        if unsafety.is_none() {
-                            return Err(Error::new_spanned(
-                                arg,
-                                "pointer argument requires that the function be marked unsafe",
-                            ));
-                        }
-                    }
                     args.push_value(Var {
                         doc,
                         attrs,
@@ -628,6 +619,7 @@ fn parse_extern_fn(
     let mut throws_tokens = None;
     let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
     let throws = throws_tokens.is_some();
+    let unsafety = foreign_fn.sig.unsafety;
     let fn_token = foreign_fn.sig.fn_token;
     let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
     let visibility = visibility_pub(&foreign_fn.vis, inherited_span);

From b8682334c8f71f55bd35b6cb2709294cc6e83d92 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:18:18 +0000
Subject: [PATCH 2152/2232] Add failing ui test showing unsafety of fn ptr not enforced


---

diff --git a/tests/ui/ptr_in_fnptr.rs b/tests/ui/ptr_in_fnptr.rs
new file mode 100644
index 0000000..73c97c6
--- /dev/null
+++ b/tests/ui/ptr_in_fnptr.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn f(callback: fn(p: *const u8));
+    }
+}
+
+fn main() {}

From aba7ab1bb097efb3b1a2246ed6e72e00c06ae47e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:18:18 +0000
Subject: [PATCH 2153/2232] Detect pointer argument inside of function pointer


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2c03bdf..5430428 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -272,6 +272,17 @@ fn check_type_fn(cx: &mut Check, ty: &Signature) {
     if ty.throws {
         cx.error(ty, "function pointer returning Result is not supported yet");
     }
+
+    for arg in &ty.args {
+        if let Type::Ptr(_) = arg.ty {
+            if ty.unsafety.is_none() {
+                cx.error(
+                    arg,
+                    "pointer argument requires that the function pointer be marked unsafe",
+                );
+            }
+        }
+    }
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
diff --git a/tests/ui/ptr_in_fnptr.stderr b/tests/ui/ptr_in_fnptr.stderr
new file mode 100644
index 0000000..372d4cd
--- /dev/null
+++ b/tests/ui/ptr_in_fnptr.stderr
@@ -0,0 +1,5 @@
+error: pointer argument requires that the function pointer be marked unsafe
+ --> $DIR/ptr_in_fnptr.rs:4:27
+  |
+4 |         fn f(callback: fn(p: *const u8));
+  |                           ^^^^^^^^^^^^

From ff0ecfb4e1563f639ba89362e243195740cb112e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:22:50 +0000
Subject: [PATCH 2154/2232] Merge pull request #747 from dtolnay/rawptr-doc


Raw pointer doc tweaks
---

diff --git a/README.md b/README.md
index c5d93ae..7dd4ded 100644
--- a/README.md
+++ b/README.md
@@ -331,9 +331,9 @@ returns of functions.
 <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
-<tr><td>*mut T, *const T</td><td>T*, const T*</td><td></td></tr>
 </table>
 
 The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 4987694..a8f89bf 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -32,5 +32,6 @@
     - [SharedPtr\<T\> &mdash; std::shared\_ptr\<T\>](binding/sharedptr.md)
     - [Vec\<T\> &mdash; rust::Vec\<T\>](binding/vec.md)
     - [CxxVector\<T\> &mdash; std::vector\<T\>](binding/cxxvector.md)
+    - [*mut T, *const T raw pointers](binding/rawptr.md)
     - [Function pointers](binding/fn.md)
     - [Result\<T\>](binding/result.md)
diff --git a/book/src/binding/raw_ptr.md b/book/src/binding/raw_ptr.md
deleted file mode 100644
index 7ad6475..0000000
--- a/book/src/binding/raw_ptr.md
+++ /dev/null
@@ -1,68 +0,0 @@
-{{#title *mut T, *const T — Rust ♡ C++}}
-# *mut T, *const T - Raw Pointers
-
-cxx supports tranfer of raw pointers across the FFI boundary.
-
-Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
-or references. You should resort to using raw pointers only where lifetimes
-are too complicated to model with standard cxx facilities.
-
-As is normal with raw pointers in Rust, you'll need to use `unsafe` when
-working with them. In particular, to pass any raw pointer into a cxx
-bridge function you will need to declare the function `unsafe`, even if
-the overall `extern "C++"` section is already marked as `unsafe`. By calling
-such a function, you're committing that you - the human - know enough about
-the lifetimes of those objects that the compiler doesn't need to do checks.
-
-On the other hand, C++ functions can freely return raw pointers to
-Rust without `unsafe`, but actually using those raw pointers in any way is likely
-to require an `unsafe` keyword.
-
-## Example
-
-```rust,noplayground
-// src/main.rs
-
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-
-        include!("tests/ffi/tests.h");
-        //include!("example/include/container.h");
-
-        type ComplexHierarchicContainer;
-
-        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
-        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
-        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
-        // ...
-    }
-}
-
-fn main() {
-    let mut container = ffi17::new_hierarchic_container();
-    cxx::let_cxx_string!(key = "a");
-    let mut subcontainer = container.pin_mut().add_child(&key);
-    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
-    cxx::let_cxx_string!(key2 = "b");
-    cxx::let_cxx_string!(value = "c");
-    subcontainer.add_value(&key2, &value);
-    // ...
-}
-```
-
-```cpp
-// include/container.h
-
-#pragma once
-
-class ComplexHierarchicContainer {
-public:
-    ComplexHierarchicContainer();
-    void add_value(const std::string& key, const std::string& value);
-    ComplexHierarchicContainer* add_child(const std::string& key);
-    // ...
-};
-
-std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
-```
diff --git a/book/src/binding/rawptr.md b/book/src/binding/rawptr.md
new file mode 100644
index 0000000..7ad6475
--- /dev/null
+++ b/book/src/binding/rawptr.md
@@ -0,0 +1,68 @@
+{{#title *mut T, *const T — Rust ♡ C++}}
+# *mut T, *const T - Raw Pointers
+
+cxx supports tranfer of raw pointers across the FFI boundary.
+
+Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
+or references. You should resort to using raw pointers only where lifetimes
+are too complicated to model with standard cxx facilities.
+
+As is normal with raw pointers in Rust, you'll need to use `unsafe` when
+working with them. In particular, to pass any raw pointer into a cxx
+bridge function you will need to declare the function `unsafe`, even if
+the overall `extern "C++"` section is already marked as `unsafe`. By calling
+such a function, you're committing that you - the human - know enough about
+the lifetimes of those objects that the compiler doesn't need to do checks.
+
+On the other hand, C++ functions can freely return raw pointers to
+Rust without `unsafe`, but actually using those raw pointers in any way is likely
+to require an `unsafe` keyword.
+
+## Example
+
+```rust,noplayground
+// src/main.rs
+
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+
+        include!("tests/ffi/tests.h");
+        //include!("example/include/container.h");
+
+        type ComplexHierarchicContainer;
+
+        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
+        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
+        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
+        // ...
+    }
+}
+
+fn main() {
+    let mut container = ffi17::new_hierarchic_container();
+    cxx::let_cxx_string!(key = "a");
+    let mut subcontainer = container.pin_mut().add_child(&key);
+    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
+    cxx::let_cxx_string!(key2 = "b");
+    cxx::let_cxx_string!(value = "c");
+    subcontainer.add_value(&key2, &value);
+    // ...
+}
+```
+
+```cpp
+// include/container.h
+
+#pragma once
+
+class ComplexHierarchicContainer {
+public:
+    ComplexHierarchicContainer();
+    void add_value(const std::string& key, const std::string& value);
+    ComplexHierarchicContainer* add_child(const std::string& key);
+    // ...
+};
+
+std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+```
diff --git a/book/src/bindings.md b/book/src/bindings.md
index 9ba0c41..bcb51d8 100644
--- a/book/src/bindings.md
+++ b/book/src/bindings.md
@@ -20,9 +20,9 @@ returns of extern functions.
 <tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array&lt;T, N&gt;</td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px">Vec&lt;T&gt;</td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec&lt;T&gt;</a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector&lt;T&gt;</a></b></td><td style="padding:3px 6px">std::vector&lt;T&gt;</td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*mut T, *const T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 <tr><td style="padding:3px 6px">fn(T, U) -&gt; V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn&lt;V(T, U)&gt;</a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 <tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result&lt;T&gt;</a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr>
-<tr><td style="padding:3px 6px"><b><a href="binding/raw_ptr.md">*const T, *mut T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"></td></tr>
 </table>
 
 <br>
diff --git a/src/lib.rs b/src/lib.rs
index 57bcbfb..f7c694a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -340,6 +340,7 @@
 //! <tr><td>[T; N]</td><td>std::array&lt;T, N&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td>Vec&lt;T&gt;</td><td>rust::Vec&lt;T&gt;</td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr>
 //! <tr><td><a href="struct.CxxVector.html">CxxVector&lt;T&gt;</a></td><td>std::vector&lt;T&gt;</td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr>
+//! <tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr>
 //! <tr><td>fn(T, U) -&gt; V</td><td>rust::Fn&lt;V(T, U)&gt;</td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr>
 //! <tr><td>Result&lt;T&gt;</td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr>
 //! </table>

From d91d2a8d4a53acd861045b736d270998c3dd9c0f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:23:49 +0000
Subject: [PATCH 2155/2232] Relax restriction on target types of pointer


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2c03bdf..c76ef19 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -234,8 +234,9 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
-    if let Type::Ident(_) = ty.inner {
-        return;
+    match ty.inner {
+        Type::Ref(_) | Type::Ptr(_) | Type::Fn(_) | Type::Void(_) => {}
+        _ => return,
     }
 
     cx.error(ty, "unsupported pointer type");

From 2a2264c483399816fba50f4a232357c6e376c3ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:23:50 +0000
Subject: [PATCH 2156/2232] Add dedicated error message for pointer to reference


---

diff --git a/syntax/check.rs b/syntax/check.rs
index c76ef19..eba6565 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -235,7 +235,11 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
     match ty.inner {
-        Type::Ref(_) | Type::Ptr(_) | Type::Fn(_) | Type::Void(_) => {}
+        Type::Ptr(_) | Type::Fn(_) | Type::Void(_) => {}
+        Type::Ref(_) => {
+            cx.error(ty, "C++ does not allow pointer to reference as a type");
+            return;
+        }
         _ => return,
     }
 
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index b5e8a78..e037faa 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -4,7 +4,7 @@ error: unsupported pointer type
 6 |         fn get_ptr_to_ptr() -> *mut *mut C;
   |                                ^^^^^^^^^^^
 
-error: unsupported pointer type
+error: C++ does not allow pointer to reference as a type
  --> $DIR/ptr_unsupported.rs:7:38
   |
 7 |         fn get_ptr_to_reference() -> *mut &C;

From bd313d5e926ba4a81eabe364cc93fc20c3d310b8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:23:51 +0000
Subject: [PATCH 2157/2232] Add dedicated error message for ptr to ptr and ref to ptr


---

diff --git a/syntax/check.rs b/syntax/check.rs
index eba6565..a4cddfa 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -222,11 +222,15 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     }
 
     match ty.inner {
-        Type::Fn(_) | Type::Void(_) | Type::Ptr(_) => {}
+        Type::Fn(_) | Type::Void(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow references to references");
             return;
         }
+        Type::Ptr(_) => {
+            cx.error(ty, "support for reference to pointer is not implemented yet");
+            return;
+        }
         _ => return,
     }
 
@@ -235,11 +239,15 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
     match ty.inner {
-        Type::Ptr(_) | Type::Fn(_) | Type::Void(_) => {}
+        Type::Fn(_) | Type::Void(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow pointer to reference as a type");
             return;
         }
+        Type::Ptr(_) => {
+            cx.error(ty, "support for pointer to pointer is not implemented yet");
+            return;
+        }
         _ => return,
     }
 
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index e037faa..af5e134 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -1,4 +1,4 @@
-error: unsupported pointer type
+error: support for pointer to pointer is not implemented yet
  --> $DIR/ptr_unsupported.rs:6:32
   |
 6 |         fn get_ptr_to_ptr() -> *mut *mut C;
@@ -10,7 +10,7 @@ error: C++ does not allow pointer to reference as a type
 7 |         fn get_ptr_to_reference() -> *mut &C;
   |                                      ^^^^^^^
 
-error: unsupported reference type
+error: support for reference to pointer is not implemented yet
  --> $DIR/ptr_unsupported.rs:8:38
   |
 8 |         fn get_reference_to_ptr() -> &*mut C;

From d2d225c10cc65c99f4747c5604fd17942239ae39 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:23:51 +0000
Subject: [PATCH 2158/2232] East const to make nested pointer types work


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b3911c1..930ce0b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1173,17 +1173,31 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Ref(r) => {
-            if !r.mutable {
-                write!(out, "const ");
+            if let Type::Ptr(_) = r.inner {
+                write_type_space(out, &r.inner);
+                if !r.mutable {
+                    write!(out, "const");
+                }
+            } else {
+                if !r.mutable {
+                    write!(out, "const ");
+                }
+                write_type(out, &r.inner);
             }
-            write_type(out, &r.inner);
             write!(out, " &");
         }
         Type::Ptr(p) => {
-            if !p.mutable {
-                write!(out, "const ");
+            if let Type::Ptr(_) = p.inner {
+                write_type_space(out, &p.inner);
+                if !p.mutable {
+                    write!(out, "const");
+                }
+            } else {
+                if !p.mutable {
+                    write!(out, "const ");
+                }
+                write_type(out, &p.inner);
             }
-            write_type(out, &p.inner);
             write!(out, " *");
         }
         Type::Str(_) => {
diff --git a/syntax/check.rs b/syntax/check.rs
index a4cddfa..4c6d673 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -227,10 +227,6 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
             cx.error(ty, "C++ does not allow references to references");
             return;
         }
-        Type::Ptr(_) => {
-            cx.error(ty, "support for reference to pointer is not implemented yet");
-            return;
-        }
         _ => return,
     }
 
@@ -244,10 +240,6 @@ fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
             cx.error(ty, "C++ does not allow pointer to reference as a type");
             return;
         }
-        Type::Ptr(_) => {
-            cx.error(ty, "support for pointer to pointer is not implemented yet");
-            return;
-        }
         _ => return,
     }
 
diff --git a/tests/ui/ptr_unsupported.rs b/tests/ui/ptr_unsupported.rs
index ca1580a..9d59c03 100644
--- a/tests/ui/ptr_unsupported.rs
+++ b/tests/ui/ptr_unsupported.rs
@@ -3,9 +3,7 @@ mod ffi {
     unsafe extern "C++" {
         type C;
 
-        fn get_ptr_to_ptr() -> *mut *mut C;
         fn get_ptr_to_reference() -> *mut &C;
-        fn get_reference_to_ptr() -> &*mut C;
         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
     }
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index af5e134..41cea63 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -1,29 +1,17 @@
-error: support for pointer to pointer is not implemented yet
- --> $DIR/ptr_unsupported.rs:6:32
-  |
-6 |         fn get_ptr_to_ptr() -> *mut *mut C;
-  |                                ^^^^^^^^^^^
-
 error: C++ does not allow pointer to reference as a type
- --> $DIR/ptr_unsupported.rs:7:38
-  |
-7 |         fn get_ptr_to_reference() -> *mut &C;
-  |                                      ^^^^^^^
-
-error: support for reference to pointer is not implemented yet
- --> $DIR/ptr_unsupported.rs:8:38
+ --> $DIR/ptr_unsupported.rs:6:38
   |
-8 |         fn get_reference_to_ptr() -> &*mut C;
+6 |         fn get_ptr_to_reference() -> *mut &C;
   |                                      ^^^^^^^
 
 error: unsupported unique_ptr target type
- --> $DIR/ptr_unsupported.rs:9:38
+ --> $DIR/ptr_unsupported.rs:7:38
   |
-9 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+7 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
   |                                      ^^^^^^^^^^^^^^^^^
 
 error: unsupported vector target type
-  --> $DIR/ptr_unsupported.rs:10:45
-   |
-10 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
-   |                                             ^^^^^^^^^^^^^^^^^^
+ --> $DIR/ptr_unsupported.rs:8:45
+  |
+8 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+  |                                             ^^^^^^^^^^^^^^^^^^

From cfdcede8f0108705d1f8a2eee53f690172c9ae1c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:29:12 +0000
Subject: [PATCH 2159/2232] Rewrite raw ptr book page with example involving argc/argv


---

diff --git a/book/src/binding/rawptr.md b/book/src/binding/rawptr.md
index 7ad6475..1794211 100644
--- a/book/src/binding/rawptr.md
+++ b/book/src/binding/rawptr.md
@@ -1,68 +1,100 @@
 {{#title *mut T, *const T — Rust ♡ C++}}
-# *mut T, *const T - Raw Pointers
+# *mut T,&ensp;*const T
 
-cxx supports tranfer of raw pointers across the FFI boundary.
+Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>]
+where possible over raw pointers, but raw pointers are available too as an
+unsafe fallback option.
 
-Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
-or references. You should resort to using raw pointers only where lifetimes
-are too complicated to model with standard cxx facilities.
+[std::unique_ptr\<T\>]: uniqueptr.md
 
-As is normal with raw pointers in Rust, you'll need to use `unsafe` when
-working with them. In particular, to pass any raw pointer into a cxx
-bridge function you will need to declare the function `unsafe`, even if
-the overall `extern "C++"` section is already marked as `unsafe`. By calling
-such a function, you're committing that you - the human - know enough about
-the lifetimes of those objects that the compiler doesn't need to do checks.
+### Restrictions:
 
-On the other hand, C++ functions can freely return raw pointers to
-Rust without `unsafe`, but actually using those raw pointers in any way is likely
-to require an `unsafe` keyword.
+Extern functions and function pointers taking a raw pointer as an argument must
+be declared `unsafe fn` i.e. unsafe to call. The same does not apply to
+functions which only *return* a raw pointer, though presumably doing anything
+useful with the returned pointer is going to involve unsafe code elsewhere
+anyway.
 
 ## Example
 
+This example illustrates making a Rust call to a canonical C-style `main`
+signature involving `char *argv[]`.
+
+```cpp
+// include/args.h
+
+#pragma once
+
+void parseArgs(int argc, char *argv[]);
+```
+
+```cpp
+// src/args.cc
+
+#include "example/include/args.h"
+#include <iostream>
+
+void parseArgs(int argc, char *argv[]) {
+  std::cout << argc << std::endl;
+  for (int i = 0; i < argc; i++) {
+    std::cout << '"' << argv[i] << '"' << std::endl;
+  }
+}
+```
+
 ```rust,noplayground
 // src/main.rs
 
+use std::env;
+use std::ffi::CString;
+use std::os::raw::c_char;
+use std::os::unix::ffi::OsStrExt;
+use std::ptr;
+
 #[cxx::bridge]
 mod ffi {
-    unsafe extern "C++" {
-
-        include!("tests/ffi/tests.h");
-        //include!("example/include/container.h");
+    extern "C++" {
+        include!("example/include/args.h");
 
-        type ComplexHierarchicContainer;
-
-        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
-        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
-        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
-        // ...
+        unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char);
     }
 }
 
 fn main() {
-    let mut container = ffi17::new_hierarchic_container();
-    cxx::let_cxx_string!(key = "a");
-    let mut subcontainer = container.pin_mut().add_child(&key);
-    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
-    cxx::let_cxx_string!(key2 = "b");
-    cxx::let_cxx_string!(value = "c");
-    subcontainer.add_value(&key2, &value);
-    // ...
-}
-```
+    // Convert from OsString to nul-terminated CString, truncating each argument
+    // at the first inner nul byte if present.
+    let args: Vec<CString> = env::args_os()
+        .map(|os_str| {
+            let bytes = os_str.as_bytes();
+            CString::new(bytes).unwrap_or_else(|nul_error| {
+                let nul_position = nul_error.nul_position();
+                let mut bytes = nul_error.into_vec();
+                bytes.truncate(nul_position);
+                CString::new(bytes).unwrap()
+            })
+        })
+        .collect();
 
-```cpp
-// include/container.h
-
-#pragma once
+    // Convert from Vec<CString> of owned strings to Vec<*mut c_char> of
+    // borrowed string pointers.
+    //
+    // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467)
+    // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258
+    // is implemented, and CStr pointers become thin, we can sidestep this step
+    // by accumulating the args as Vec<Box<CStr>> up front, then simply casting
+    // from *mut [Box<CStr>] to *mut [*mut CStr] to *mut *mut c_char.
+    let argc = args.len();
+    let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1);
+    for arg in &args {
+        argv.push(arg.as_ptr() as *mut c_char);
+    }
+    argv.push(ptr::null_mut()); // Nul terminator.
 
-class ComplexHierarchicContainer {
-public:
-    ComplexHierarchicContainer();
-    void add_value(const std::string& key, const std::string& value);
-    ComplexHierarchicContainer* add_child(const std::string& key);
-    // ...
-};
+    unsafe {
+        ffi::parseArgs(argc as i32, argv.as_mut_ptr());
+    }
 
-std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+    // The CStrings go out of scope here. C function must not have held on to
+    // the pointers beyond this point.
+}
 ```

From 1082db666938b05ee806c2fc079dd621da0c946f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:41:05 +0000
Subject: [PATCH 2160/2232] Merge pull request #748 from dtolnay/fnptr-ptr


Detect raw pointer argument inside of function pointer
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 2c03bdf..5430428 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -272,6 +272,17 @@ fn check_type_fn(cx: &mut Check, ty: &Signature) {
     if ty.throws {
         cx.error(ty, "function pointer returning Result is not supported yet");
     }
+
+    for arg in &ty.args {
+        if let Type::Ptr(_) = arg.ty {
+            if ty.unsafety.is_none() {
+                cx.error(
+                    arg,
+                    "pointer argument requires that the function pointer be marked unsafe",
+                );
+            }
+        }
+    }
 }
 
 fn check_api_struct(cx: &mut Check, strct: &Struct) {
diff --git a/tests/ui/ptr_in_fnptr.rs b/tests/ui/ptr_in_fnptr.rs
new file mode 100644
index 0000000..73c97c6
--- /dev/null
+++ b/tests/ui/ptr_in_fnptr.rs
@@ -0,0 +1,8 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        fn f(callback: fn(p: *const u8));
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/ptr_in_fnptr.stderr b/tests/ui/ptr_in_fnptr.stderr
new file mode 100644
index 0000000..372d4cd
--- /dev/null
+++ b/tests/ui/ptr_in_fnptr.stderr
@@ -0,0 +1,5 @@
+error: pointer argument requires that the function pointer be marked unsafe
+ --> $DIR/ptr_in_fnptr.rs:4:27
+  |
+4 |         fn f(callback: fn(p: *const u8));
+  |                           ^^^^^^^^^^^^

From 5f04fda69dec1e4eb8129aace235e289402abfcb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:41:13 +0000
Subject: [PATCH 2161/2232] Merge pull request #750 from dtolnay/pointers


Pointer to pointer, pointer to reference, reference to pointer
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index b3911c1..930ce0b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1173,17 +1173,31 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Ref(r) => {
-            if !r.mutable {
-                write!(out, "const ");
+            if let Type::Ptr(_) = r.inner {
+                write_type_space(out, &r.inner);
+                if !r.mutable {
+                    write!(out, "const");
+                }
+            } else {
+                if !r.mutable {
+                    write!(out, "const ");
+                }
+                write_type(out, &r.inner);
             }
-            write_type(out, &r.inner);
             write!(out, " &");
         }
         Type::Ptr(p) => {
-            if !p.mutable {
-                write!(out, "const ");
+            if let Type::Ptr(_) = p.inner {
+                write_type_space(out, &p.inner);
+                if !p.mutable {
+                    write!(out, "const");
+                }
+            } else {
+                if !p.mutable {
+                    write!(out, "const ");
+                }
+                write_type(out, &p.inner);
             }
-            write_type(out, &p.inner);
             write!(out, " *");
         }
         Type::Str(_) => {
diff --git a/syntax/check.rs b/syntax/check.rs
index 5430428..6ba6565 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -222,7 +222,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
     }
 
     match ty.inner {
-        Type::Fn(_) | Type::Void(_) | Type::Ptr(_) => {}
+        Type::Fn(_) | Type::Void(_) => {}
         Type::Ref(_) => {
             cx.error(ty, "C++ does not allow references to references");
             return;
@@ -234,8 +234,13 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
 }
 
 fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
-    if let Type::Ident(_) = ty.inner {
-        return;
+    match ty.inner {
+        Type::Fn(_) | Type::Void(_) => {}
+        Type::Ref(_) => {
+            cx.error(ty, "C++ does not allow pointer to reference as a type");
+            return;
+        }
+        _ => return,
     }
 
     cx.error(ty, "unsupported pointer type");
diff --git a/tests/ui/ptr_unsupported.rs b/tests/ui/ptr_unsupported.rs
index ca1580a..9d59c03 100644
--- a/tests/ui/ptr_unsupported.rs
+++ b/tests/ui/ptr_unsupported.rs
@@ -3,9 +3,7 @@ mod ffi {
     unsafe extern "C++" {
         type C;
 
-        fn get_ptr_to_ptr() -> *mut *mut C;
         fn get_ptr_to_reference() -> *mut &C;
-        fn get_reference_to_ptr() -> &*mut C;
         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
     }
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index b5e8a78..41cea63 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -1,29 +1,17 @@
-error: unsupported pointer type
- --> $DIR/ptr_unsupported.rs:6:32
+error: C++ does not allow pointer to reference as a type
+ --> $DIR/ptr_unsupported.rs:6:38
   |
-6 |         fn get_ptr_to_ptr() -> *mut *mut C;
-  |                                ^^^^^^^^^^^
-
-error: unsupported pointer type
- --> $DIR/ptr_unsupported.rs:7:38
-  |
-7 |         fn get_ptr_to_reference() -> *mut &C;
-  |                                      ^^^^^^^
-
-error: unsupported reference type
- --> $DIR/ptr_unsupported.rs:8:38
-  |
-8 |         fn get_reference_to_ptr() -> &*mut C;
+6 |         fn get_ptr_to_reference() -> *mut &C;
   |                                      ^^^^^^^
 
 error: unsupported unique_ptr target type
- --> $DIR/ptr_unsupported.rs:9:38
+ --> $DIR/ptr_unsupported.rs:7:38
   |
-9 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
+7 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
   |                                      ^^^^^^^^^^^^^^^^^
 
 error: unsupported vector target type
-  --> $DIR/ptr_unsupported.rs:10:45
-   |
-10 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
-   |                                             ^^^^^^^^^^^^^^^^^^
+ --> $DIR/ptr_unsupported.rs:8:45
+  |
+8 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;
+  |                                             ^^^^^^^^^^^^^^^^^^

From f3e52f29f00f338c4c421a23086f40728ae0654e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:43:00 +0000
Subject: [PATCH 2162/2232] Merge pull request #751 from dtolnay/argv


Rewrite raw ptr book page with example involving argc/argv
---

diff --git a/book/src/binding/rawptr.md b/book/src/binding/rawptr.md
index 7ad6475..1794211 100644
--- a/book/src/binding/rawptr.md
+++ b/book/src/binding/rawptr.md
@@ -1,68 +1,100 @@
 {{#title *mut T, *const T — Rust ♡ C++}}
-# *mut T, *const T - Raw Pointers
+# *mut T,&ensp;*const T
 
-cxx supports tranfer of raw pointers across the FFI boundary.
+Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>]
+where possible over raw pointers, but raw pointers are available too as an
+unsafe fallback option.
 
-Generally, it's better to use the bindings for [std::unique_ptr\<T\>](uniqueptr.md)
-or references. You should resort to using raw pointers only where lifetimes
-are too complicated to model with standard cxx facilities.
+[std::unique_ptr\<T\>]: uniqueptr.md
 
-As is normal with raw pointers in Rust, you'll need to use `unsafe` when
-working with them. In particular, to pass any raw pointer into a cxx
-bridge function you will need to declare the function `unsafe`, even if
-the overall `extern "C++"` section is already marked as `unsafe`. By calling
-such a function, you're committing that you - the human - know enough about
-the lifetimes of those objects that the compiler doesn't need to do checks.
+### Restrictions:
 
-On the other hand, C++ functions can freely return raw pointers to
-Rust without `unsafe`, but actually using those raw pointers in any way is likely
-to require an `unsafe` keyword.
+Extern functions and function pointers taking a raw pointer as an argument must
+be declared `unsafe fn` i.e. unsafe to call. The same does not apply to
+functions which only *return* a raw pointer, though presumably doing anything
+useful with the returned pointer is going to involve unsafe code elsewhere
+anyway.
 
 ## Example
 
+This example illustrates making a Rust call to a canonical C-style `main`
+signature involving `char *argv[]`.
+
+```cpp
+// include/args.h
+
+#pragma once
+
+void parseArgs(int argc, char *argv[]);
+```
+
+```cpp
+// src/args.cc
+
+#include "example/include/args.h"
+#include <iostream>
+
+void parseArgs(int argc, char *argv[]) {
+  std::cout << argc << std::endl;
+  for (int i = 0; i < argc; i++) {
+    std::cout << '"' << argv[i] << '"' << std::endl;
+  }
+}
+```
+
 ```rust,noplayground
 // src/main.rs
 
+use std::env;
+use std::ffi::CString;
+use std::os::raw::c_char;
+use std::os::unix::ffi::OsStrExt;
+use std::ptr;
+
 #[cxx::bridge]
 mod ffi {
-    unsafe extern "C++" {
-
-        include!("tests/ffi/tests.h");
-        //include!("example/include/container.h");
+    extern "C++" {
+        include!("example/include/args.h");
 
-        type ComplexHierarchicContainer;
-
-        fn new_hierarchic_container() -> UniquePtr<ComplexHierarchicContainer>;
-        fn add_value(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString, value: &CxxString);
-        fn add_child(self: Pin<&mut ComplexHierarchicContainer>, key: &CxxString) -> *mut ComplexHierarchicContainer;
-        // ...
+        unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char);
     }
 }
 
 fn main() {
-    let mut container = ffi17::new_hierarchic_container();
-    cxx::let_cxx_string!(key = "a");
-    let mut subcontainer = container.pin_mut().add_child(&key);
-    let mut subcontainer = unsafe { std::pin::Pin::new_unchecked(subcontainer.as_mut().unwrap()) };
-    cxx::let_cxx_string!(key2 = "b");
-    cxx::let_cxx_string!(value = "c");
-    subcontainer.add_value(&key2, &value);
-    // ...
-}
-```
+    // Convert from OsString to nul-terminated CString, truncating each argument
+    // at the first inner nul byte if present.
+    let args: Vec<CString> = env::args_os()
+        .map(|os_str| {
+            let bytes = os_str.as_bytes();
+            CString::new(bytes).unwrap_or_else(|nul_error| {
+                let nul_position = nul_error.nul_position();
+                let mut bytes = nul_error.into_vec();
+                bytes.truncate(nul_position);
+                CString::new(bytes).unwrap()
+            })
+        })
+        .collect();
 
-```cpp
-// include/container.h
-
-#pragma once
+    // Convert from Vec<CString> of owned strings to Vec<*mut c_char> of
+    // borrowed string pointers.
+    //
+    // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467)
+    // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258
+    // is implemented, and CStr pointers become thin, we can sidestep this step
+    // by accumulating the args as Vec<Box<CStr>> up front, then simply casting
+    // from *mut [Box<CStr>] to *mut [*mut CStr] to *mut *mut c_char.
+    let argc = args.len();
+    let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1);
+    for arg in &args {
+        argv.push(arg.as_ptr() as *mut c_char);
+    }
+    argv.push(ptr::null_mut()); // Nul terminator.
 
-class ComplexHierarchicContainer {
-public:
-    ComplexHierarchicContainer();
-    void add_value(const std::string& key, const std::string& value);
-    ComplexHierarchicContainer* add_child(const std::string& key);
-    // ...
-};
+    unsafe {
+        ffi::parseArgs(argc as i32, argv.as_mut_ptr());
+    }
 
-std::unique_ptr<ComplexHierarchicContainer> new_hierarchic_container();
+    // The CStrings go out of scope here. C function must not have held on to
+    // the pointers beyond this point.
+}
 ```

From 6aeaca628dab04edd6e57b4d1f97ee701838822d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:43:08 +0000
Subject: [PATCH 2163/2232] Disable lint jobs on pull requests


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 86f58a6..c3d4bfc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,6 +94,7 @@ jobs:
   clippy:
     name: Clippy
     runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
@@ -102,6 +103,7 @@ jobs:
   clang-tidy:
     name: Clang Tidy
     runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
     steps:
       - uses: actions/checkout@v2
       - name: Install clang-tidy

From dec9392b65852e695232a8122e8a51ca4db5eeba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 02:54:36 +0000
Subject: [PATCH 2164/2232] Merge pull request #752 from dtolnay/noprlint


Disable lint jobs on pull requests
---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 86f58a6..c3d4bfc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -94,6 +94,7 @@ jobs:
   clippy:
     name: Clippy
     runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
     steps:
       - uses: actions/checkout@v2
       - uses: dtolnay/rust-toolchain@clippy
@@ -102,6 +103,7 @@ jobs:
   clang-tidy:
     name: Clang Tidy
     runs-on: ubuntu-latest
+    if: github.event_name != 'pull_request'
     steps:
       - uses: actions/checkout@v2
       - name: Install clang-tidy

From 2982d73777af6acb344a24ad16f829de34e230c8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 03:10:18 +0000
Subject: [PATCH 2165/2232] Handle pointer cast of non-ffi-safe pointer target types


Previously:

    error: `extern` block uses type `String`, which is not FFI-safe
      --> src/main.rs:13:27
       |
    13 |         unsafe fn test(x: *mut String);
       |                           ^^^^^^^^^^^ not FFI-safe

---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6d414c3..0a88a04 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -512,6 +512,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 },
                 _ => quote!(#var),
             },
+            Type::Ptr(ty) => {
+                if types.is_considered_improper_ctype(&ty.inner) {
+                    quote!(#var.cast())
+                } else {
+                    quote!(#var)
+                }
+            }
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
             Type::SliceRef(ty) => match ty.mutable {
                 false => quote!(::cxx::private::RustSlice::from_ref(#var)),
@@ -608,6 +615,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     }
                     _ => call,
                 },
+                Type::Ptr(ty) => {
+                    if types.is_considered_improper_ctype(&ty.inner) {
+                        quote!(#call.cast())
+                    } else {
+                        call
+                    }
+                }
                 Type::Str(_) => quote!(#call.as_str()),
                 Type::SliceRef(slice) => {
                     let inner = &slice.inner;
@@ -1572,6 +1586,15 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
                 _ => quote!(#ty),
             }
         }
+        Type::Ptr(ty) => {
+            if proper && types.is_considered_improper_ctype(&ty.inner) {
+                let mutability = ty.mutability;
+                let constness = ty.constness;
+                quote!(*#mutability #constness ::std::ffi::c_void)
+            } else {
+                quote!(#ty)
+            }
+        }
         Type::Str(_) => quote!(::cxx::private::RustStr),
         Type::SliceRef(_) => quote!(::cxx::private::RustSlice),
         _ => quote!(#ty),

From c1b34d7b31c11ec58b1c5ce550c532d7afea54dc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 03:17:40 +0000
Subject: [PATCH 2166/2232] Merge pull request #753 from dtolnay/ptrcast


Handle pointer cast of non-ffi-safe pointer target types
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6d414c3..0a88a04 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -512,6 +512,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                 },
                 _ => quote!(#var),
             },
+            Type::Ptr(ty) => {
+                if types.is_considered_improper_ctype(&ty.inner) {
+                    quote!(#var.cast())
+                } else {
+                    quote!(#var)
+                }
+            }
             Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
             Type::SliceRef(ty) => match ty.mutable {
                 false => quote!(::cxx::private::RustSlice::from_ref(#var)),
@@ -608,6 +615,13 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     }
                     _ => call,
                 },
+                Type::Ptr(ty) => {
+                    if types.is_considered_improper_ctype(&ty.inner) {
+                        quote!(#call.cast())
+                    } else {
+                        call
+                    }
+                }
                 Type::Str(_) => quote!(#call.as_str()),
                 Type::SliceRef(slice) => {
                     let inner = &slice.inner;
@@ -1572,6 +1586,15 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
                 _ => quote!(#ty),
             }
         }
+        Type::Ptr(ty) => {
+            if proper && types.is_considered_improper_ctype(&ty.inner) {
+                let mutability = ty.mutability;
+                let constness = ty.constness;
+                quote!(*#mutability #constness ::std::ffi::c_void)
+            } else {
+                quote!(#ty)
+            }
+        }
         Type::Str(_) => quote!(::cxx::private::RustStr),
         Type::SliceRef(_) => quote!(::cxx::private::RustSlice),
         _ => quote!(#ty),

From 574206a9ef83e95d90923f4a8ee438f3893a2e98 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 03:18:41 +0000
Subject: [PATCH 2167/2232] Lockfile update


---

diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index a0d4f7f..936a5a0 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -189,9 +189,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.90"
+version = "0.2.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae"
+checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
 
 [[package]]
 name = "link-cplusplus"
@@ -246,18 +246,18 @@ checksum = "7e114536316b51a5aa7a0e59fc49661fd263c5507dd08bd28de052e57626ce69"
 
 [[package]]
 name = "serde"
-version = "1.0.124"
+version = "1.0.125"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f"
+checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.124"
+version = "1.0.125"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b"
+checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
 dependencies = [
  "proc-macro2",
  "quote",

From c37a665e042077925871dfd1206f410a570e1068 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 23 2021 03:19:09 +0000
Subject: [PATCH 2168/2232] Release 1.0.34


---

diff --git a/Cargo.toml b/Cargo.toml
index df7d042..70ac78d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.33" # remember to update html_root_url
+version = "1.0.34" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.33", path = "macro" }
+cxxbridge-macro = { version = "=1.0.34", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.33", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.34", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.33", path = "gen/build" }
+cxx-build = { version = "=1.0.34", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index e4f8552..8d9daeb 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.33"
+version = "1.0.34"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index d763b3d..dfa5aa6 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.33"
+version = "1.0.34"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 11f9d1c..e7e1c85 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.33"
+version = "1.0.34"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 465df6e..fd94124 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.33"
+version = "0.7.34"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 8aa6a28..fef8670 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.33"
+version = "1.0.34"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index f7c694a..8282ea3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.33")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.34")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 936a5a0..76bcb7c 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.33"
+version = "1.0.34"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.33"
+version = "1.0.34"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.33"
+version = "0.7.34"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.33"
+version = "1.0.34"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.33"
+version = "1.0.34"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.33"
+version = "1.0.34"
 dependencies = [
  "cxx",
  "proc-macro2",

From 4be66f9ec8ed623df99f0b5a0092c36f456d0d45 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 24 2021 19:47:29 +0000
Subject: [PATCH 2169/2232] Remove .clang-tidy link to issue #500


The issue has been closed and we are probably keeping the remaining set
of suppressions.

---

diff --git a/.clang-tidy b/.clang-tidy
index b94f5a9..a1db8d3 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,6 +1,4 @@
 Checks:
-  # TODO: many of these need to be resolved.
-  # https://github.com/dtolnay/cxx/issues/500
   clang-analyzer-*,
   clang-diagnostic-*,
   cppcoreguidelines-*,

From 35c6c4b25cdb861414cff3cd4b0fdadf749db99c Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 24 2021 19:48:06 +0000
Subject: [PATCH 2170/2232] Update to clang-tidy 11


---

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c3d4bfc..3fafd9b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -107,6 +107,6 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - name: Install clang-tidy
-        run: sudo apt-get install clang-tidy-10
+        run: sudo apt-get install clang-tidy-11
       - name: Run clang-tidy
-        run: clang-tidy-10 src/cxx.cc --warnings-as-errors=*
+        run: clang-tidy-11 src/cxx.cc --warnings-as-errors=*

From dda0c77b1520d8bbbb243c8bb39dfae52d5c2570 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 24 2021 19:48:06 +0000
Subject: [PATCH 2171/2232] Update bazel build to rustc 1.50.0


---

diff --git a/WORKSPACE b/WORKSPACE
index 8de7e1a..17a0af5 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,7 +17,7 @@ load("@rules_rust//rust:repositories.bzl", "rust_repositories")
 
 rust_repositories(
     edition = "2018",
-    version = "1.49.0",
+    version = "1.50.0",
 )
 
 vendor(

From 395e20f64c1846fc866c210a70c06e87031dc2ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 24 2021 19:48:47 +0000
Subject: [PATCH 2172/2232] Suppress cppcoreguidelines-pro-type-varargs lint from clang-tidy


I don't understand why this specific lint is triggering in the two cases below
but the code seems fine.

    include/cxx.h:882:3: error: do not declare variables of type va_list; use variadic templates instead [cppcoreguidelines-pro-type-vararg,-warnings-as-errors]
      auto data = reinterpret_cast<char *>(this->data());
      ^
    src/cxx.cc:355:3: error: do not declare variables of type va_list; use variadic templates instead [cppcoreguidelines-pro-type-vararg,-warnings-as-errors]
      char *copy = new char[len];
      ^

---

diff --git a/.clang-tidy b/.clang-tidy
index a1db8d3..b0a6da9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -10,6 +10,7 @@ Checks:
   -cppcoreguidelines-pro-type-const-cast,
   -cppcoreguidelines-pro-type-member-init,
   -cppcoreguidelines-pro-type-reinterpret-cast,
+  -cppcoreguidelines-pro-type-vararg,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
   -modernize-use-equals-default,

From 3090721172f12f5f88c1853f177c9441e2e1789e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 24 2021 20:00:11 +0000
Subject: [PATCH 2173/2232] Merge pull request #758 from dtolnay/clang-tidy-11


Update to clang-tidy 11
---

diff --git a/.clang-tidy b/.clang-tidy
index a1db8d3..b0a6da9 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -10,6 +10,7 @@ Checks:
   -cppcoreguidelines-pro-type-const-cast,
   -cppcoreguidelines-pro-type-member-init,
   -cppcoreguidelines-pro-type-reinterpret-cast,
+  -cppcoreguidelines-pro-type-vararg,
   -cppcoreguidelines-special-member-functions,
   -modernize-use-default-member-init,
   -modernize-use-equals-default,
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c3d4bfc..3fafd9b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -107,6 +107,6 @@ jobs:
     steps:
       - uses: actions/checkout@v2
       - name: Install clang-tidy
-        run: sudo apt-get install clang-tidy-10
+        run: sudo apt-get install clang-tidy-11
       - name: Run clang-tidy
-        run: clang-tidy-10 src/cxx.cc --warnings-as-errors=*
+        run: clang-tidy-11 src/cxx.cc --warnings-as-errors=*

From ac5af50ab33ee4d31db423510ec55370669fbf60 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 04:30:15 +0000
Subject: [PATCH 2174/2232] Replace 'static dyn Display with a formatter fn in printing type names


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 0a88a04..49b8927 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1276,7 +1276,9 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1361,7 +1363,9 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1418,7 +1422,9 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1487,7 +1493,9 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d78ee47..c9c7d78 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -5,7 +5,7 @@ use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use crate::string::CxxString;
 use core::ffi::c_void;
-use core::fmt::{self, Debug, Display};
+use core::fmt::{self, Debug};
 use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
@@ -263,32 +263,11 @@ where
     }
 }
 
-pub(crate) struct TypeName<T> {
-    element: PhantomData<T>,
-}
-
-impl<T> TypeName<T> {
-    pub const fn new() -> Self {
-        TypeName {
-            element: PhantomData,
-        }
-    }
-}
-
-impl<T> Display for TypeName<T>
-where
-    T: VectorElement,
-{
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        write!(formatter, "CxxVector<{}>", T::__NAME)
-    }
-}
-
 // Methods are private; not intended to be implemented outside of cxxbridge
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement: Sized {
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
     unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
     fn __unique_ptr_null() -> *mut c_void;
@@ -303,7 +282,9 @@ macro_rules! impl_vector_element {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
diff --git a/src/fmt.rs b/src/fmt.rs
new file mode 100644
index 0000000..db14a7c
--- /dev/null
+++ b/src/fmt.rs
@@ -0,0 +1,16 @@
+use std::fmt::{self, Display};
+
+pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display {
+    DisplayInvoke(fmt)
+}
+
+struct DisplayInvoke<T>(T);
+
+impl<T> Display for DisplayInvoke<T>
+where
+    T: Fn(&mut fmt::Formatter) -> fmt::Result,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        (self.0)(formatter)
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8282ea3..fb00d94 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -402,6 +402,7 @@ mod macros;
 
 mod exception;
 mod extern_type;
+mod fmt;
 mod function;
 mod opaque;
 mod result;
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index b3a1b1c..5893035 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,3 +1,4 @@
+use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
 use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
@@ -119,7 +120,10 @@ where
     fn deref(&self) -> &Self::Target {
         match self.as_ref() {
             Some(target) => target,
-            None => panic!("called deref on a null SharedPtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref on a null SharedPtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -152,7 +156,7 @@ where
 // codebase.
 pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     unsafe fn __null(new: *mut c_void);
     #[doc(hidden)]
@@ -177,7 +181,9 @@ pub unsafe trait SharedPtrTarget {
 macro_rules! impl_shared_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl SharedPtrTarget for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 0f9fa8f..1603881 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,6 +1,7 @@
+use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
-use crate::vector::{self, CxxVector, VectorElement};
+use crate::vector::{CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -77,7 +78,10 @@ where
     pub fn pin_mut(&mut self) -> Pin<&mut T> {
         match self.as_mut() {
             Some(target) => target,
-            None => panic!("called pin_mut on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called pin_mut on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 
@@ -127,7 +131,10 @@ where
     fn deref(&self) -> &Self::Target {
         match self.as_ref() {
             Some(target) => target,
-            None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -139,7 +146,10 @@ where
     fn deref_mut(&mut self) -> &mut Self::Target {
         match self.as_mut() {
             Some(target) => Pin::into_inner(target),
-            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref_mut on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -172,7 +182,7 @@ where
 // codebase.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
@@ -209,7 +219,9 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
-    const __NAME: &'static dyn Display = &"CxxString";
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("CxxString")
+    }
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe {
@@ -237,7 +249,9 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
     T: VectorElement + 'static,
 {
-    const __NAME: &'static dyn Display = &vector::TypeName::<T>::new();
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "CxxVector<{}>", display(T::__typename))
+    }
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index 7fc4c78..ba74461 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -1,7 +1,7 @@
 use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
 use crate::string::CxxString;
 use core::ffi::c_void;
-use core::fmt::{self, Debug, Display};
+use core::fmt::{self, Debug};
 use core::marker::PhantomData;
 use core::mem::MaybeUninit;
 
@@ -95,7 +95,7 @@ where
 // codebase.
 pub unsafe trait WeakPtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     unsafe fn __null(new: *mut c_void);
     #[doc(hidden)]
@@ -111,7 +111,9 @@ pub unsafe trait WeakPtrTarget {
 macro_rules! impl_weak_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl WeakPtrTarget for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {

From 3def522a2fcbe230f3957b5408ee526f71383b2f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 04:31:43 +0000
Subject: [PATCH 2175/2232] Support non-static vector element types inside of unique ptr


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 1603881..2d16a45 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -247,7 +247,7 @@ unsafe impl UniquePtrTarget for CxxString {
 
 unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
-    T: VectorElement + 'static,
+    T: VectorElement,
 {
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "CxxVector<{}>", display(T::__typename))

From c27a656c98ce5a37f6826ef55c5bed31d1e13d0f Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 04:39:35 +0000
Subject: [PATCH 2176/2232] Merge pull request #760 from dtolnay/vecnonstatic


Support non-static vector element types inside of unique ptr
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 0a88a04..49b8927 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1276,7 +1276,9 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1361,7 +1363,9 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1418,7 +1422,9 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1487,7 +1493,9 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
-            const __NAME: &'static dyn ::std::fmt::Display = &#name;
+            fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                f.write_str(#name)
+            }
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d78ee47..c9c7d78 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -5,7 +5,7 @@ use crate::extern_type::ExternType;
 use crate::kind::Trivial;
 use crate::string::CxxString;
 use core::ffi::c_void;
-use core::fmt::{self, Debug, Display};
+use core::fmt::{self, Debug};
 use core::iter::FusedIterator;
 use core::marker::{PhantomData, PhantomPinned};
 use core::mem;
@@ -263,32 +263,11 @@ where
     }
 }
 
-pub(crate) struct TypeName<T> {
-    element: PhantomData<T>,
-}
-
-impl<T> TypeName<T> {
-    pub const fn new() -> Self {
-        TypeName {
-            element: PhantomData,
-        }
-    }
-}
-
-impl<T> Display for TypeName<T>
-where
-    T: VectorElement,
-{
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-        write!(formatter, "CxxVector<{}>", T::__NAME)
-    }
-}
-
 // Methods are private; not intended to be implemented outside of cxxbridge
 // codebase.
 #[doc(hidden)]
 pub unsafe trait VectorElement: Sized {
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     fn __vector_size(v: &CxxVector<Self>) -> usize;
     unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
     fn __unique_ptr_null() -> *mut c_void;
@@ -303,7 +282,9 @@ macro_rules! impl_vector_element {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
diff --git a/src/fmt.rs b/src/fmt.rs
new file mode 100644
index 0000000..db14a7c
--- /dev/null
+++ b/src/fmt.rs
@@ -0,0 +1,16 @@
+use std::fmt::{self, Display};
+
+pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display {
+    DisplayInvoke(fmt)
+}
+
+struct DisplayInvoke<T>(T);
+
+impl<T> Display for DisplayInvoke<T>
+where
+    T: Fn(&mut fmt::Formatter) -> fmt::Result,
+{
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        (self.0)(formatter)
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8282ea3..fb00d94 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -402,6 +402,7 @@ mod macros;
 
 mod exception;
 mod extern_type;
+mod fmt;
 mod function;
 mod opaque;
 mod result;
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index b3a1b1c..5893035 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,3 +1,4 @@
+use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
 use crate::weak_ptr::{WeakPtr, WeakPtrTarget};
@@ -119,7 +120,10 @@ where
     fn deref(&self) -> &Self::Target {
         match self.as_ref() {
             Some(target) => target,
-            None => panic!("called deref on a null SharedPtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref on a null SharedPtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -152,7 +156,7 @@ where
 // codebase.
 pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     unsafe fn __null(new: *mut c_void);
     #[doc(hidden)]
@@ -177,7 +181,9 @@ pub unsafe trait SharedPtrTarget {
 macro_rules! impl_shared_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl SharedPtrTarget for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 0f9fa8f..2d16a45 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,6 +1,7 @@
+use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
-use crate::vector::{self, CxxVector, VectorElement};
+use crate::vector::{CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
@@ -77,7 +78,10 @@ where
     pub fn pin_mut(&mut self) -> Pin<&mut T> {
         match self.as_mut() {
             Some(target) => target,
-            None => panic!("called pin_mut on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called pin_mut on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 
@@ -127,7 +131,10 @@ where
     fn deref(&self) -> &Self::Target {
         match self.as_ref() {
             Some(target) => target,
-            None => panic!("called deref on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -139,7 +146,10 @@ where
     fn deref_mut(&mut self) -> &mut Self::Target {
         match self.as_mut() {
             Some(target) => Pin::into_inner(target),
-            None => panic!("called deref_mut on a null UniquePtr<{}>", T::__NAME),
+            None => panic!(
+                "called deref_mut on a null UniquePtr<{}>",
+                display(T::__typename),
+            ),
         }
     }
 }
@@ -172,7 +182,7 @@ where
 // codebase.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     fn __null() -> *mut c_void;
     #[doc(hidden)]
@@ -209,7 +219,9 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
-    const __NAME: &'static dyn Display = &"CxxString";
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("CxxString")
+    }
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe {
@@ -235,9 +247,11 @@ unsafe impl UniquePtrTarget for CxxString {
 
 unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
-    T: VectorElement + 'static,
+    T: VectorElement,
 {
-    const __NAME: &'static dyn Display = &vector::TypeName::<T>::new();
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "CxxVector<{}>", display(T::__typename))
+    }
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index 7fc4c78..ba74461 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -1,7 +1,7 @@
 use crate::shared_ptr::{SharedPtr, SharedPtrTarget};
 use crate::string::CxxString;
 use core::ffi::c_void;
-use core::fmt::{self, Debug, Display};
+use core::fmt::{self, Debug};
 use core::marker::PhantomData;
 use core::mem::MaybeUninit;
 
@@ -95,7 +95,7 @@ where
 // codebase.
 pub unsafe trait WeakPtrTarget {
     #[doc(hidden)]
-    const __NAME: &'static dyn Display;
+    fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     #[doc(hidden)]
     unsafe fn __null(new: *mut c_void);
     #[doc(hidden)]
@@ -111,7 +111,9 @@ pub unsafe trait WeakPtrTarget {
 macro_rules! impl_weak_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl WeakPtrTarget for $ty {
-            const __NAME: &'static dyn Display = &$name;
+            fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
+                f.write_str($name)
+            }
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {

From c2c1e3bc25126332ab99c37d66755886f238e84a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 04:55:24 +0000
Subject: [PATCH 2177/2232] No-inline documentation of CxxVector within cxx::vector module


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c9c7d78..a8422d4 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -13,9 +13,6 @@ use core::pin::Pin;
 use core::ptr;
 use core::slice;
 
-#[doc(inline)]
-pub use crate::Vector;
-
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
 /// # Invariants
diff --git a/src/lib.rs b/src/lib.rs
index fb00d94..acb28fb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -400,6 +400,7 @@ extern crate std;
 #[macro_use]
 mod macros;
 
+mod cxx_vector;
 mod exception;
 mod extern_type;
 mod fmt;
@@ -418,17 +419,15 @@ mod symbols;
 mod type_id;
 mod unique_ptr;
 mod unwind;
-#[path = "cxx_vector.rs"]
 pub mod vector;
 mod weak_ptr;
 
+pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
 pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
-#[doc(inline)]
-pub use crate::vector::CxxVector;
 pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
@@ -449,6 +448,7 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
@@ -462,7 +462,6 @@ pub mod private {
     pub use crate::string::StackString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
-    pub use crate::vector::VectorElement;
     pub use crate::weak_ptr::WeakPtrTarget;
     pub use cxxbridge_macro::type_id;
 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 2d16a45..9133783 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,7 +1,7 @@
+use crate::cxx_vector::{CxxVector, VectorElement};
 use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
-use crate::vector::{CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
diff --git a/src/vector.rs b/src/vector.rs
new file mode 100644
index 0000000..47eb60d
--- /dev/null
+++ b/src/vector.rs
@@ -0,0 +1,8 @@
+//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
+//! itself is exposed at the crate root.
+
+pub use crate::cxx_vector::{Iter, IterMut};
+#[doc(no_inline)]
+pub use crate::CxxVector;
+#[doc(inline)]
+pub use crate::Vector;

From 676bb463840c9d5bef87cdd7fe99528d23ec603d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 05:05:01 +0000
Subject: [PATCH 2178/2232] Make rustdoc Re-exports section show external-facing type name


---

diff --git a/src/vector.rs b/src/vector.rs
index 47eb60d..6963c3d 100644
--- a/src/vector.rs
+++ b/src/vector.rs
@@ -2,7 +2,7 @@
 //! itself is exposed at the crate root.
 
 pub use crate::cxx_vector::{Iter, IterMut};
-#[doc(no_inline)]
-pub use crate::CxxVector;
 #[doc(inline)]
 pub use crate::Vector;
+#[doc(no_inline)]
+pub use cxx::CxxVector;

From d83dfe15de4f246aa019981403bc4f41557e9175 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 05:11:39 +0000
Subject: [PATCH 2179/2232] Merge pull request #761 from dtolnay/vecdoc


No-inline documentation of CxxVector within cxx::vector module
---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index c9c7d78..a8422d4 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -13,9 +13,6 @@ use core::pin::Pin;
 use core::ptr;
 use core::slice;
 
-#[doc(inline)]
-pub use crate::Vector;
-
 /// Binding to C++ `std::vector<T, std::allocator<T>>`.
 ///
 /// # Invariants
diff --git a/src/lib.rs b/src/lib.rs
index fb00d94..acb28fb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -400,6 +400,7 @@ extern crate std;
 #[macro_use]
 mod macros;
 
+mod cxx_vector;
 mod exception;
 mod extern_type;
 mod fmt;
@@ -418,17 +419,15 @@ mod symbols;
 mod type_id;
 mod unique_ptr;
 mod unwind;
-#[path = "cxx_vector.rs"]
 pub mod vector;
 mod weak_ptr;
 
+pub use crate::cxx_vector::CxxVector;
 pub use crate::exception::Exception;
 pub use crate::extern_type::{kind, ExternType};
 pub use crate::shared_ptr::SharedPtr;
 pub use crate::string::CxxString;
 pub use crate::unique_ptr::UniquePtr;
-#[doc(inline)]
-pub use crate::vector::CxxVector;
 pub use crate::weak_ptr::WeakPtr;
 pub use cxxbridge_macro::bridge;
 
@@ -449,6 +448,7 @@ pub type Vector<T> = CxxVector<T>;
 // Not public API.
 #[doc(hidden)]
 pub mod private {
+    pub use crate::cxx_vector::VectorElement;
     pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
     pub use crate::function::FatFunction;
     pub use crate::opaque::Opaque;
@@ -462,7 +462,6 @@ pub mod private {
     pub use crate::string::StackString;
     pub use crate::unique_ptr::UniquePtrTarget;
     pub use crate::unwind::catch_unwind;
-    pub use crate::vector::VectorElement;
     pub use crate::weak_ptr::WeakPtrTarget;
     pub use cxxbridge_macro::type_id;
 }
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 2d16a45..9133783 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -1,7 +1,7 @@
+use crate::cxx_vector::{CxxVector, VectorElement};
 use crate::fmt::display;
 use crate::kind::Trivial;
 use crate::string::CxxString;
-use crate::vector::{CxxVector, VectorElement};
 use crate::ExternType;
 use core::ffi::c_void;
 use core::fmt::{self, Debug, Display};
diff --git a/src/vector.rs b/src/vector.rs
new file mode 100644
index 0000000..6963c3d
--- /dev/null
+++ b/src/vector.rs
@@ -0,0 +1,8 @@
+//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
+//! itself is exposed at the crate root.
+
+pub use crate::cxx_vector::{Iter, IterMut};
+#[doc(inline)]
+pub use crate::Vector;
+#[doc(no_inline)]
+pub use cxx::CxxVector;

From 906b68dbcb6ea08291df0b67c3526cfa9c840bfe Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:00:07 +0000
Subject: [PATCH 2180/2232] Add cxx::memory module re-exporting Shared/UniquePtr


---

diff --git a/src/lib.rs b/src/lib.rs
index acb28fb..d6be52c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -405,6 +405,7 @@ mod exception;
 mod extern_type;
 mod fmt;
 mod function;
+pub mod memory;
 mod opaque;
 mod result;
 mod rust_slice;
diff --git a/src/memory.rs b/src/memory.rs
new file mode 100644
index 0000000..42f1f76
--- /dev/null
+++ b/src/memory.rs
@@ -0,0 +1,2 @@
+#[doc(no_inline)]
+pub use cxx::{SharedPtr, UniquePtr};

From 3690e65e412dc719fc7d750f5d58ffe28b94f5cb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:01:07 +0000
Subject: [PATCH 2181/2232] Make memory and vector trait bounds publicly nameable


---

diff --git a/src/memory.rs b/src/memory.rs
index 42f1f76..80b8f6f 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,2 +1,4 @@
+pub use crate::shared_ptr::SharedPtrTarget;
+pub use crate::unique_ptr::UniquePtrTarget;
 #[doc(no_inline)]
 pub use cxx::{SharedPtr, UniquePtr};
diff --git a/src/vector.rs b/src/vector.rs
index 6963c3d..d360207 100644
--- a/src/vector.rs
+++ b/src/vector.rs
@@ -1,7 +1,7 @@
 //! Less used details of `CxxVector` are exposed in this module. `CxxVector`
 //! itself is exposed at the crate root.
 
-pub use crate::cxx_vector::{Iter, IterMut};
+pub use crate::cxx_vector::{Iter, IterMut, VectorElement};
 #[doc(inline)]
 pub use crate::Vector;
 #[doc(no_inline)]

From 751ee02ffb557c9244af12d49f4173e8d0be3a41 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:02:20 +0000
Subject: [PATCH 2182/2232] Tweak cxx::vector and cxx::memory module-level doc


---

diff --git a/src/memory.rs b/src/memory.rs
index 80b8f6f..441d3d8 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -1,3 +1,7 @@
+//! Less used details of `UniquePtr` and `SharedPtr`.
+//!
+//! The pointer types themselves are exposed at the crate root.
+
 pub use crate::shared_ptr::SharedPtrTarget;
 pub use crate::unique_ptr::UniquePtrTarget;
 #[doc(no_inline)]
diff --git a/src/vector.rs b/src/vector.rs
index d360207..4afd487 100644
--- a/src/vector.rs
+++ b/src/vector.rs
@@ -1,5 +1,6 @@
-//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
-//! itself is exposed at the crate root.
+//! Less used details of `CxxVector`.
+//!
+//! `CxxVector` itself is exposed at the crate root.
 
 pub use crate::cxx_vector::{Iter, IterMut, VectorElement};
 #[doc(inline)]

From 71b8d38f215bfc24b33b3bac0674a403806cf483 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:03:48 +0000
Subject: [PATCH 2183/2232] Document VectorElement trait


---

diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index a8422d4..b7ea110 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -260,9 +260,34 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
-#[doc(hidden)]
+/// Trait bound for types which may be used as the `T` inside of a
+/// `CxxVector<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
+/// in generic code.
+///
+/// ```
+/// use cxx::vector::{CxxVector, VectorElement};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
+/// where
+///     T: VectorElement + Display,
+/// {
+///     println!("the vector elements are:");
+///     for element in vector {
+///         println!("  • {}", element);
+///     }
+/// }
+/// ```
+///
+/// Writing the same generic function without a `VectorElement` trait bound
+/// would not compile.
 pub unsafe trait VectorElement: Sized {
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
     fn __vector_size(v: &CxxVector<Self>) -> usize;

From cccf068b209ba6c6b5306e8fc0f7fc50d55f0697 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:04:03 +0000
Subject: [PATCH 2184/2232] Document UniquePtrTarget trait


---

diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 9133783..bc326dc 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -178,8 +178,31 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
+/// Trait bound for types which may be used as the `T` inside of a
+/// `UniquePtr<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: UniquePtrTarget` may be necessary when manipulating
+/// [`UniquePtr`] in generic code.
+///
+/// ```
+/// use cxx::memory::{UniquePtr, UniquePtrTarget};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
+/// where
+///     T: UniquePtrTarget + Display,
+/// {
+///     println!("the unique_ptr points to: {}", *ptr);
+/// }
+/// ```
+///
+/// Writing the same generic function without a `UniquePtrTarget` trait bound
+/// would not compile.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;

From 9291d52a37bce8c274860457369fa6b31c943f07 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:04:44 +0000
Subject: [PATCH 2185/2232] Document SharedPtrTarget trait


---

diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 5893035..e7ae997 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -152,8 +152,31 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
+/// Trait bound for types which may be used as the `T` inside of a
+/// `SharedPtr<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: SharedPtrTarget` may be necessary when manipulating
+/// [`SharedPtr`] in generic code.
+///
+/// ```
+/// use cxx::memory::{SharedPtr, SharedPtrTarget};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_ptr<T>(ptr: SharedPtr<T>)
+/// where
+///     T: SharedPtrTarget + Display,
+/// {
+///     println!("the shared_ptr points to: {}", *ptr);
+/// }
+/// ```
+///
+/// Writing the same generic function without a `SharedPtrTarget` trait bound
+/// would not compile.
 pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;

From b99359bbf31b083573d25b4762d33a3113455444 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:05:22 +0000
Subject: [PATCH 2186/2232] Hide all private trait methods from rustdoc


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 49b8927..042fdcb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1255,6 +1255,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
+            #[doc(hidden)]
             fn __new(value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_uninit]
@@ -1276,9 +1277,11 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1289,6 +1292,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 repr
             }
             #new_method
+            #[doc(hidden)]
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
@@ -1298,6 +1302,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 __raw(&mut repr, raw.cast());
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
@@ -1305,6 +1310,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __get(&repr).cast()
             }
+            #[doc(hidden)]
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
@@ -1312,6 +1318,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __release(&mut repr).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(mut repr: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1344,6 +1351,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
+            #[doc(hidden)]
             unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_uninit]
@@ -1363,9 +1371,11 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1374,6 +1384,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 __null(new);
             }
             #new_method
+            #[doc(hidden)]
             unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_clone]
@@ -1381,6 +1392,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
@@ -1388,6 +1400,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __get(this).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1422,9 +1435,11 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1432,6 +1447,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_clone]
@@ -1439,6 +1455,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_downgrade]
@@ -1446,6 +1463,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __downgrade(shared, weak);
             }
+            #[doc(hidden)]
             unsafe fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_upgrade]
@@ -1453,6 +1471,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __upgrade(weak, shared);
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1493,9 +1512,11 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
@@ -1503,6 +1524,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 unsafe { __vector_size(v) }
             }
+            #[doc(hidden)]
             unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
@@ -1510,6 +1532,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __get_unchecked(v, pos)
             }
+            #[doc(hidden)]
             fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_null]
@@ -1519,6 +1542,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 unsafe { __unique_ptr_null(&mut repr) }
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_raw]
@@ -1528,6 +1552,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 __unique_ptr_raw(&mut repr, raw);
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_get]
@@ -1535,6 +1560,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __unique_ptr_get(&repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_release]
@@ -1542,6 +1568,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __unique_ptr_release(&mut repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_drop(mut repr: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_unique_ptr_drop]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index b7ea110..1643341 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -289,13 +289,21 @@ where
 /// Writing the same generic function without a `VectorElement` trait bound
 /// would not compile.
 pub unsafe trait VectorElement: Sized {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
+    #[doc(hidden)]
     fn __vector_size(v: &CxxVector<Self>) -> usize;
+    #[doc(hidden)]
     unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
+    #[doc(hidden)]
     fn __unique_ptr_null() -> *mut c_void;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
@@ -304,9 +312,11 @@ macro_rules! impl_vector_element {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
@@ -316,6 +326,7 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
+            #[doc(hidden)]
             unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                 extern "C" {
                     attr! {
@@ -325,6 +336,7 @@ macro_rules! impl_vector_element {
                 }
                 __get_unchecked(v, pos)
             }
+            #[doc(hidden)]
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
@@ -336,6 +348,7 @@ macro_rules! impl_vector_element {
                 unsafe { __unique_ptr_null(&mut repr) }
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
@@ -347,6 +360,7 @@ macro_rules! impl_vector_element {
                 __unique_ptr_raw(&mut repr, raw);
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
@@ -356,6 +370,7 @@ macro_rules! impl_vector_element {
                 }
                 __unique_ptr_get(&repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
@@ -365,6 +380,7 @@ macro_rules! impl_vector_element {
                 }
                 __unique_ptr_release(&mut repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index e7ae997..66b988b 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -204,9 +204,11 @@ pub unsafe trait SharedPtrTarget {
 macro_rules! impl_shared_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl SharedPtrTarget for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -216,6 +218,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __new(value: Self, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -225,6 +228,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __uninit(new).cast::<$ty>().write(value);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const c_void, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -234,6 +238,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __get(this: *const c_void) -> *const Self {
                 extern "C" {
                     attr! {
@@ -243,6 +248,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __get(this).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index bc326dc..836f467 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -242,9 +242,11 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str("CxxString")
     }
+    #[doc(hidden)]
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe {
@@ -252,17 +254,21 @@ unsafe impl UniquePtrTarget for CxxString {
         }
         repr
     }
+    #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unique_ptr_std_string_raw(&mut repr, raw);
         repr
     }
+    #[doc(hidden)]
     unsafe fn __get(repr: *mut c_void) -> *const Self {
         unique_ptr_std_string_get(&repr)
     }
+    #[doc(hidden)]
     unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
         unique_ptr_std_string_release(&mut repr)
     }
+    #[doc(hidden)]
     unsafe fn __drop(mut repr: *mut c_void) {
         unique_ptr_std_string_drop(&mut repr);
     }
@@ -272,21 +278,27 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
     T: VectorElement,
 {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "CxxVector<{}>", display(T::__typename))
     }
+    #[doc(hidden)]
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }
+    #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
         T::__unique_ptr_raw(raw)
     }
+    #[doc(hidden)]
     unsafe fn __get(repr: *mut c_void) -> *const Self {
         T::__unique_ptr_get(repr)
     }
+    #[doc(hidden)]
     unsafe fn __release(repr: *mut c_void) -> *mut Self {
         T::__unique_ptr_release(repr)
     }
+    #[doc(hidden)]
     unsafe fn __drop(repr: *mut c_void) {
         T::__unique_ptr_drop(repr);
     }
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index ba74461..8291d59 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -111,9 +111,11 @@ pub unsafe trait WeakPtrTarget {
 macro_rules! impl_weak_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl WeakPtrTarget for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -123,6 +125,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const c_void, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -132,6 +135,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -141,6 +145,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __downgrade(shared, weak);
             }
+            #[doc(hidden)]
             unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -150,6 +155,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __upgrade(weak, shared);
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {

From 453da7ff7deaaa0f821000731cff16e1b9517dd6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:09:16 +0000
Subject: [PATCH 2187/2232] Update ui test with public path of UniquePtrTarget


---

diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
index 5686cf1..03093eb 100644
--- a/tests/ui/unique_ptr_twice.stderr
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
+error[E0119]: conflicting implementations of trait `cxx::memory::UniquePtrTarget` for type `here::C`:
   --> $DIR/unique_ptr_twice.rs:16:5
    |
 7  |     impl UniquePtr<C> {}

From b90097b55780cc622c356b8a46b347fe4a80ebaa Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:17:30 +0000
Subject: [PATCH 2188/2232] Merge pull request #762 from dtolnay/traits


Make memory and vector trait bounds publicly nameable
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 49b8927..042fdcb 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1255,6 +1255,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
+            #[doc(hidden)]
             fn __new(value: Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_uninit]
@@ -1276,9 +1277,11 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             fn __null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1289,6 +1292,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 repr
             }
             #new_method
+            #[doc(hidden)]
             unsafe fn __raw(raw: *mut Self) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_raw]
@@ -1298,6 +1302,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 __raw(&mut repr, raw.cast());
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __get(repr: *mut ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
@@ -1305,6 +1310,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __get(&repr).cast()
             }
+            #[doc(hidden)]
             unsafe fn __release(mut repr: *mut ::std::ffi::c_void) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_release]
@@ -1312,6 +1318,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __release(&mut repr).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(mut repr: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1344,6 +1351,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         || types.aliases.contains_key(ident);
     let new_method = if can_construct_from_value {
         Some(quote! {
+            #[doc(hidden)]
             unsafe fn __new(value: Self, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_uninit]
@@ -1363,9 +1371,11 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1374,6 +1384,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 __null(new);
             }
             #new_method
+            #[doc(hidden)]
             unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_clone]
@@ -1381,6 +1392,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __get(this: *const ::std::ffi::c_void) -> *const Self {
                 extern "C" {
                     #[link_name = #link_get]
@@ -1388,6 +1400,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
                 }
                 __get(this).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1422,9 +1435,11 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_null]
@@ -1432,6 +1447,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const ::std::ffi::c_void, new: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_clone]
@@ -1439,6 +1455,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __downgrade(shared: *const ::std::ffi::c_void, weak: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_downgrade]
@@ -1446,6 +1463,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __downgrade(shared, weak);
             }
+            #[doc(hidden)]
             unsafe fn __upgrade(weak: *const ::std::ffi::c_void, shared: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_upgrade]
@@ -1453,6 +1471,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
                 }
                 __upgrade(weak, shared);
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_drop]
@@ -1493,9 +1512,11 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
 
     quote_spanned! {end_span=>
         #unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
+            #[doc(hidden)]
             fn __typename(f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 f.write_str(#name)
             }
+            #[doc(hidden)]
             fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
                 extern "C" {
                     #[link_name = #link_size]
@@ -1503,6 +1524,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 unsafe { __vector_size(v) }
             }
+            #[doc(hidden)]
             unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
                 extern "C" {
                     #[link_name = #link_get_unchecked]
@@ -1510,6 +1532,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __get_unchecked(v, pos)
             }
+            #[doc(hidden)]
             fn __unique_ptr_null() -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_null]
@@ -1519,6 +1542,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 unsafe { __unique_ptr_null(&mut repr) }
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
                 extern "C" {
                     #[link_name = #link_unique_ptr_raw]
@@ -1528,6 +1552,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 __unique_ptr_raw(&mut repr, raw);
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_get]
@@ -1535,6 +1560,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __unique_ptr_get(&repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
                 extern "C" {
                     #[link_name = #link_unique_ptr_release]
@@ -1542,6 +1568,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
                 }
                 __unique_ptr_release(&mut repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_drop(mut repr: *mut ::std::ffi::c_void) {
                 extern "C" {
                     #[link_name = #link_unique_ptr_drop]
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index a8422d4..1643341 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -260,17 +260,50 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
-#[doc(hidden)]
+/// Trait bound for types which may be used as the `T` inside of a
+/// `CxxVector<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`]
+/// in generic code.
+///
+/// ```
+/// use cxx::vector::{CxxVector, VectorElement};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_vector<T>(vector: &CxxVector<T>)
+/// where
+///     T: VectorElement + Display,
+/// {
+///     println!("the vector elements are:");
+///     for element in vector {
+///         println!("  • {}", element);
+///     }
+/// }
+/// ```
+///
+/// Writing the same generic function without a `VectorElement` trait bound
+/// would not compile.
 pub unsafe trait VectorElement: Sized {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
+    #[doc(hidden)]
     fn __vector_size(v: &CxxVector<Self>) -> usize;
+    #[doc(hidden)]
     unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self;
+    #[doc(hidden)]
     fn __unique_ptr_null() -> *mut c_void;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self>;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_release(repr: *mut c_void) -> *mut CxxVector<Self>;
+    #[doc(hidden)]
     unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
@@ -279,9 +312,11 @@ macro_rules! impl_vector_element {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
@@ -291,6 +326,7 @@ macro_rules! impl_vector_element {
                 }
                 unsafe { __vector_size(v) }
             }
+            #[doc(hidden)]
             unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
                 extern "C" {
                     attr! {
@@ -300,6 +336,7 @@ macro_rules! impl_vector_element {
                 }
                 __get_unchecked(v, pos)
             }
+            #[doc(hidden)]
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
@@ -311,6 +348,7 @@ macro_rules! impl_vector_element {
                 unsafe { __unique_ptr_null(&mut repr) }
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
@@ -322,6 +360,7 @@ macro_rules! impl_vector_element {
                 __unique_ptr_raw(&mut repr, raw);
                 repr
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
@@ -331,6 +370,7 @@ macro_rules! impl_vector_element {
                 }
                 __unique_ptr_get(&repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
@@ -340,6 +380,7 @@ macro_rules! impl_vector_element {
                 }
                 __unique_ptr_release(&mut repr)
             }
+            #[doc(hidden)]
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/lib.rs b/src/lib.rs
index acb28fb..d6be52c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -405,6 +405,7 @@ mod exception;
 mod extern_type;
 mod fmt;
 mod function;
+pub mod memory;
 mod opaque;
 mod result;
 mod rust_slice;
diff --git a/src/memory.rs b/src/memory.rs
new file mode 100644
index 0000000..441d3d8
--- /dev/null
+++ b/src/memory.rs
@@ -0,0 +1,8 @@
+//! Less used details of `UniquePtr` and `SharedPtr`.
+//!
+//! The pointer types themselves are exposed at the crate root.
+
+pub use crate::shared_ptr::SharedPtrTarget;
+pub use crate::unique_ptr::UniquePtrTarget;
+#[doc(no_inline)]
+pub use cxx::{SharedPtr, UniquePtr};
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 5893035..66b988b 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -152,8 +152,31 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
+/// Trait bound for types which may be used as the `T` inside of a
+/// `SharedPtr<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: SharedPtrTarget` may be necessary when manipulating
+/// [`SharedPtr`] in generic code.
+///
+/// ```
+/// use cxx::memory::{SharedPtr, SharedPtrTarget};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_ptr<T>(ptr: SharedPtr<T>)
+/// where
+///     T: SharedPtrTarget + Display,
+/// {
+///     println!("the shared_ptr points to: {}", *ptr);
+/// }
+/// ```
+///
+/// Writing the same generic function without a `SharedPtrTarget` trait bound
+/// would not compile.
 pub unsafe trait SharedPtrTarget {
     #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
@@ -181,9 +204,11 @@ pub unsafe trait SharedPtrTarget {
 macro_rules! impl_shared_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl SharedPtrTarget for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -193,6 +218,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __new(value: Self, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -202,6 +228,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __uninit(new).cast::<$ty>().write(value);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const c_void, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -211,6 +238,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __get(this: *const c_void) -> *const Self {
                 extern "C" {
                     attr! {
@@ -220,6 +248,7 @@ macro_rules! impl_shared_ptr_target {
                 }
                 __get(this).cast()
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 9133783..836f467 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -178,8 +178,31 @@ where
     }
 }
 
-// Methods are private; not intended to be implemented outside of cxxbridge
-// codebase.
+/// Trait bound for types which may be used as the `T` inside of a
+/// `UniquePtr<T>` in generic code.
+///
+/// This trait has no publicly callable or implementable methods. Implementing
+/// it outside of the CXX codebase is not supported.
+///
+/// # Example
+///
+/// A bound `T: UniquePtrTarget` may be necessary when manipulating
+/// [`UniquePtr`] in generic code.
+///
+/// ```
+/// use cxx::memory::{UniquePtr, UniquePtrTarget};
+/// use std::fmt::Display;
+///
+/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>)
+/// where
+///     T: UniquePtrTarget + Display,
+/// {
+///     println!("the unique_ptr points to: {}", *ptr);
+/// }
+/// ```
+///
+/// Writing the same generic function without a `UniquePtrTarget` trait bound
+/// would not compile.
 pub unsafe trait UniquePtrTarget {
     #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result;
@@ -219,9 +242,11 @@ extern "C" {
 }
 
 unsafe impl UniquePtrTarget for CxxString {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str("CxxString")
     }
+    #[doc(hidden)]
     fn __null() -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unsafe {
@@ -229,17 +254,21 @@ unsafe impl UniquePtrTarget for CxxString {
         }
         repr
     }
+    #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
         let mut repr = ptr::null_mut::<c_void>();
         unique_ptr_std_string_raw(&mut repr, raw);
         repr
     }
+    #[doc(hidden)]
     unsafe fn __get(repr: *mut c_void) -> *const Self {
         unique_ptr_std_string_get(&repr)
     }
+    #[doc(hidden)]
     unsafe fn __release(mut repr: *mut c_void) -> *mut Self {
         unique_ptr_std_string_release(&mut repr)
     }
+    #[doc(hidden)]
     unsafe fn __drop(mut repr: *mut c_void) {
         unique_ptr_std_string_drop(&mut repr);
     }
@@ -249,21 +278,27 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
 where
     T: VectorElement,
 {
+    #[doc(hidden)]
     fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "CxxVector<{}>", display(T::__typename))
     }
+    #[doc(hidden)]
     fn __null() -> *mut c_void {
         T::__unique_ptr_null()
     }
+    #[doc(hidden)]
     unsafe fn __raw(raw: *mut Self) -> *mut c_void {
         T::__unique_ptr_raw(raw)
     }
+    #[doc(hidden)]
     unsafe fn __get(repr: *mut c_void) -> *const Self {
         T::__unique_ptr_get(repr)
     }
+    #[doc(hidden)]
     unsafe fn __release(repr: *mut c_void) -> *mut Self {
         T::__unique_ptr_release(repr)
     }
+    #[doc(hidden)]
     unsafe fn __drop(repr: *mut c_void) {
         T::__unique_ptr_drop(repr);
     }
diff --git a/src/vector.rs b/src/vector.rs
index 6963c3d..4afd487 100644
--- a/src/vector.rs
+++ b/src/vector.rs
@@ -1,7 +1,8 @@
-//! Less used details of `CxxVector` are exposed in this module. `CxxVector`
-//! itself is exposed at the crate root.
+//! Less used details of `CxxVector`.
+//!
+//! `CxxVector` itself is exposed at the crate root.
 
-pub use crate::cxx_vector::{Iter, IterMut};
+pub use crate::cxx_vector::{Iter, IterMut, VectorElement};
 #[doc(inline)]
 pub use crate::Vector;
 #[doc(no_inline)]
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index ba74461..8291d59 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -111,9 +111,11 @@ pub unsafe trait WeakPtrTarget {
 macro_rules! impl_weak_ptr_target {
     ($segment:expr, $name:expr, $ty:ty) => {
         unsafe impl WeakPtrTarget for $ty {
+            #[doc(hidden)]
             fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
                 f.write_str($name)
             }
+            #[doc(hidden)]
             unsafe fn __null(new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -123,6 +125,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __null(new);
             }
+            #[doc(hidden)]
             unsafe fn __clone(this: *const c_void, new: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -132,6 +135,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __clone(this, new);
             }
+            #[doc(hidden)]
             unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -141,6 +145,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __downgrade(shared, weak);
             }
+            #[doc(hidden)]
             unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
                 extern "C" {
                     attr! {
@@ -150,6 +155,7 @@ macro_rules! impl_weak_ptr_target {
                 }
                 __upgrade(weak, shared);
             }
+            #[doc(hidden)]
             unsafe fn __drop(this: *mut c_void) {
                 extern "C" {
                     attr! {
diff --git a/tests/ui/unique_ptr_twice.stderr b/tests/ui/unique_ptr_twice.stderr
index 5686cf1..03093eb 100644
--- a/tests/ui/unique_ptr_twice.stderr
+++ b/tests/ui/unique_ptr_twice.stderr
@@ -1,4 +1,4 @@
-error[E0119]: conflicting implementations of trait `cxx::private::UniquePtrTarget` for type `here::C`:
+error[E0119]: conflicting implementations of trait `cxx::memory::UniquePtrTarget` for type `here::C`:
   --> $DIR/unique_ptr_twice.rs:16:5
    |
 7  |     impl UniquePtr<C> {}

From b2a799a8d9b286c5880f2405c6c160978b9d6854 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 25 2021 06:19:23 +0000
Subject: [PATCH 2189/2232] Release 1.0.35


---

diff --git a/Cargo.toml b/Cargo.toml
index 70ac78d..12ce823 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.34" # remember to update html_root_url
+version = "1.0.35" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.34", path = "macro" }
+cxxbridge-macro = { version = "=1.0.35", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.34", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.35", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.34", path = "gen/build" }
+cxx-build = { version = "=1.0.35", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 8d9daeb..66c35f9 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.34"
+version = "1.0.35"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index dfa5aa6..a60f2fc 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.34"
+version = "1.0.35"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index e7e1c85..eb68872 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.34"
+version = "1.0.35"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index fd94124..073fb11 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.34"
+version = "0.7.35"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index fef8670..c6bb164 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.34"
+version = "1.0.35"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index d6be52c..aef3760 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.34")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.35")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 76bcb7c..efb726d 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.34"
+version = "1.0.35"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.34"
+version = "1.0.35"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.34"
+version = "0.7.35"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.34"
+version = "1.0.35"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.34"
+version = "1.0.35"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.34"
+version = "1.0.35"
 dependencies = [
  "cxx",
  "proc-macro2",

From ccd269d95c590d713ff30b540eddb992fdfaba12 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 03:58:41 +0000
Subject: [PATCH 2190/2232] Omit most builtins if bridge explicitly includes "rust/cxx.h"


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 378467b..60bbf43 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -48,6 +48,11 @@ pub(super) fn write(out: &mut OutFile) {
     let builtin = &mut out.builtin;
     let out = &mut builtin.content;
 
+    let cxx_header = include
+        .custom
+        .iter()
+        .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h");
+
     if builtin.rust_string {
         include.array = true;
         include.cstdint = true;
@@ -126,51 +131,54 @@ pub(super) fn write(out: &mut OutFile) {
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    writeln!(out, "// #include \"rust/cxx.h\"");
 
-    ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
+    if !cxx_header {
+        writeln!(out, "// #include \"rust/cxx.h\"");
 
-    if builtin.rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
+        ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
 
-    if builtin.friend_impl {
-        out.begin_block(Block::AnonymousNamespace);
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl;");
-        out.end_block(Block::AnonymousNamespace);
-    }
+        if builtin.rust_string {
+            out.next_section();
+            writeln!(out, "struct unsafe_bitcopy_t;");
+        }
 
-    out.next_section();
-    if builtin.rust_str && !builtin.rust_string {
-        writeln!(out, "class String;");
-    }
-    if builtin.layout && !builtin.opaque {
-        writeln!(out, "class Opaque;");
-    }
+        if builtin.friend_impl {
+            out.begin_block(Block::AnonymousNamespace);
+            writeln!(out, "template <typename T>");
+            writeln!(out, "class impl;");
+            out.end_block(Block::AnonymousNamespace);
+        }
 
-    if builtin.rust_slice {
         out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t size_of();");
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t align_of();");
-    }
+        if builtin.rust_str && !builtin.rust_string {
+            writeln!(out, "class String;");
+        }
+        if builtin.layout && !builtin.opaque {
+            writeln!(out, "class Opaque;");
+        }
+
+        if builtin.rust_slice {
+            out.next_section();
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t size_of();");
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t align_of();");
+        }
 
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
-    ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
-    ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
-    ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+        ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
+        ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
+        ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
+        ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+        ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
+        ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
+        ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
+        ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
+        ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+        ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
+        ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
+        ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
+        ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+    }
 
     if builtin.rust_str_new_unchecked {
         out.next_section();

From 5e14b10b0ca9d34d403249d698dbefbb529f54da Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 04:17:10 +0000
Subject: [PATCH 2191/2232] Move cxx header search to method of Includes


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 60bbf43..adcd048 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -48,11 +48,6 @@ pub(super) fn write(out: &mut OutFile) {
     let builtin = &mut out.builtin;
     let out = &mut builtin.content;
 
-    let cxx_header = include
-        .custom
-        .iter()
-        .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h");
-
     if builtin.rust_string {
         include.array = true;
         include.cstdint = true;
@@ -132,6 +127,7 @@ pub(super) fn write(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
 
+    let cxx_header = include.has_cxx_header();
     if !cxx_header {
         writeln!(out, "// #include \"rust/cxx.h\"");
 
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 93ce60b..029b08d 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -50,6 +50,12 @@ impl<'a> Includes<'a> {
     pub fn insert(&mut self, include: impl Into<Include>) {
         self.custom.push(include.into());
     }
+
+    pub fn has_cxx_header(&self) -> bool {
+        self.custom
+            .iter()
+            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
+    }
 }
 
 pub(super) fn write(out: &mut OutFile) {

From 06d3220ed6f78ec30f4b2b711c64d3e7b9c03469 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 04:24:22 +0000
Subject: [PATCH 2192/2232] Reduce several standard library includes if cxx.h is included


---

diff --git a/gen/src/include.rs b/gen/src/include.rs
index 029b08d..2f59f97 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -61,6 +61,7 @@ impl<'a> Includes<'a> {
 pub(super) fn write(out: &mut OutFile) {
     let header = out.header;
     let include = &mut out.include;
+    let cxx_header = include.has_cxx_header();
     let out = &mut include.content;
 
     if header {
@@ -101,69 +102,69 @@ pub(super) fn write(out: &mut OutFile) {
         content: _,
     } = *include;
 
-    if algorithm {
+    if algorithm && !cxx_header {
         writeln!(out, "#include <algorithm>");
     }
-    if array {
+    if array && !cxx_header {
         writeln!(out, "#include <array>");
     }
-    if cassert {
+    if cassert && !cxx_header {
         writeln!(out, "#include <cassert>");
     }
-    if cstddef {
+    if cstddef && !cxx_header {
         writeln!(out, "#include <cstddef>");
     }
-    if cstdint {
+    if cstdint && !cxx_header {
         writeln!(out, "#include <cstdint>");
     }
     if cstring {
         writeln!(out, "#include <cstring>");
     }
-    if exception {
+    if exception && !cxx_header {
         writeln!(out, "#include <exception>");
     }
     if functional {
         writeln!(out, "#include <functional>");
     }
-    if initializer_list {
+    if initializer_list && !cxx_header {
         writeln!(out, "#include <initializer_list>");
     }
-    if iterator {
+    if iterator && !cxx_header {
         writeln!(out, "#include <iterator>");
     }
     if memory {
         writeln!(out, "#include <memory>");
     }
-    if new {
+    if new && !cxx_header {
         writeln!(out, "#include <new>");
     }
-    if string {
+    if string && !cxx_header {
         writeln!(out, "#include <string>");
     }
-    if type_traits {
+    if type_traits && !cxx_header {
         writeln!(out, "#include <type_traits>");
     }
-    if utility {
+    if utility && !cxx_header {
         writeln!(out, "#include <utility>");
     }
-    if vector {
+    if vector && !cxx_header {
         writeln!(out, "#include <vector>");
     }
-    if basetsd {
+    if basetsd && !cxx_header {
         writeln!(out, "#if defined(_WIN32)");
         writeln!(out, "#include <basetsd.h>");
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         if basetsd {
             writeln!(out, "#else");
         } else {
             writeln!(out, "#if not defined(_WIN32)");
         }
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         writeln!(out, "#include <sys/types.h>");
     }
-    if basetsd || sys_types {
+    if (basetsd || sys_types) && !cxx_header {
         writeln!(out, "#endif");
     }
 }

From fbcd8fd9326fa889312c158d980ea80a647c84dc Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 04:36:13 +0000
Subject: [PATCH 2193/2232] Merge pull request #769 from dtolnay/include


Omit most builtins if bridge explicitly includes "rust/cxx.h"
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 378467b..adcd048 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -126,51 +126,55 @@ pub(super) fn write(out: &mut OutFile) {
 
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
-    writeln!(out, "// #include \"rust/cxx.h\"");
 
-    ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
+    let cxx_header = include.has_cxx_header();
+    if !cxx_header {
+        writeln!(out, "// #include \"rust/cxx.h\"");
 
-    if builtin.rust_string {
-        out.next_section();
-        writeln!(out, "struct unsafe_bitcopy_t;");
-    }
+        ifndef::write(out, builtin.panic, "CXXBRIDGE1_PANIC");
 
-    if builtin.friend_impl {
-        out.begin_block(Block::AnonymousNamespace);
-        writeln!(out, "template <typename T>");
-        writeln!(out, "class impl;");
-        out.end_block(Block::AnonymousNamespace);
-    }
+        if builtin.rust_string {
+            out.next_section();
+            writeln!(out, "struct unsafe_bitcopy_t;");
+        }
 
-    out.next_section();
-    if builtin.rust_str && !builtin.rust_string {
-        writeln!(out, "class String;");
-    }
-    if builtin.layout && !builtin.opaque {
-        writeln!(out, "class Opaque;");
-    }
+        if builtin.friend_impl {
+            out.begin_block(Block::AnonymousNamespace);
+            writeln!(out, "template <typename T>");
+            writeln!(out, "class impl;");
+            out.end_block(Block::AnonymousNamespace);
+        }
 
-    if builtin.rust_slice {
         out.next_section();
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t size_of();");
-        writeln!(out, "template <typename T>");
-        writeln!(out, "::std::size_t align_of();");
-    }
+        if builtin.rust_str && !builtin.rust_string {
+            writeln!(out, "class String;");
+        }
+        if builtin.layout && !builtin.opaque {
+            writeln!(out, "class Opaque;");
+        }
+
+        if builtin.rust_slice {
+            out.next_section();
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t size_of();");
+            writeln!(out, "template <typename T>");
+            writeln!(out, "::std::size_t align_of();");
+        }
 
-    ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
-    ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
-    ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
-    ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
-    ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
-    ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
-    ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
-    ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
-    ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
-    ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
-    ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
-    ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
-    ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+        ifndef::write(out, builtin.rust_string, "CXXBRIDGE1_RUST_STRING");
+        ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
+        ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
+        ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+        ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
+        ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
+        ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
+        ifndef::write(out, builtin.rust_error, "CXXBRIDGE1_RUST_ERROR");
+        ifndef::write(out, builtin.rust_isize, "CXXBRIDGE1_RUST_ISIZE");
+        ifndef::write(out, builtin.opaque, "CXXBRIDGE1_RUST_OPAQUE");
+        ifndef::write(out, builtin.is_complete, "CXXBRIDGE1_IS_COMPLETE");
+        ifndef::write(out, builtin.layout, "CXXBRIDGE1_LAYOUT");
+        ifndef::write(out, builtin.relocatable, "CXXBRIDGE1_RELOCATABLE");
+    }
 
     if builtin.rust_str_new_unchecked {
         out.next_section();
diff --git a/gen/src/include.rs b/gen/src/include.rs
index 93ce60b..2f59f97 100644
--- a/gen/src/include.rs
+++ b/gen/src/include.rs
@@ -50,11 +50,18 @@ impl<'a> Includes<'a> {
     pub fn insert(&mut self, include: impl Into<Include>) {
         self.custom.push(include.into());
     }
+
+    pub fn has_cxx_header(&self) -> bool {
+        self.custom
+            .iter()
+            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
+    }
 }
 
 pub(super) fn write(out: &mut OutFile) {
     let header = out.header;
     let include = &mut out.include;
+    let cxx_header = include.has_cxx_header();
     let out = &mut include.content;
 
     if header {
@@ -95,69 +102,69 @@ pub(super) fn write(out: &mut OutFile) {
         content: _,
     } = *include;
 
-    if algorithm {
+    if algorithm && !cxx_header {
         writeln!(out, "#include <algorithm>");
     }
-    if array {
+    if array && !cxx_header {
         writeln!(out, "#include <array>");
     }
-    if cassert {
+    if cassert && !cxx_header {
         writeln!(out, "#include <cassert>");
     }
-    if cstddef {
+    if cstddef && !cxx_header {
         writeln!(out, "#include <cstddef>");
     }
-    if cstdint {
+    if cstdint && !cxx_header {
         writeln!(out, "#include <cstdint>");
     }
     if cstring {
         writeln!(out, "#include <cstring>");
     }
-    if exception {
+    if exception && !cxx_header {
         writeln!(out, "#include <exception>");
     }
     if functional {
         writeln!(out, "#include <functional>");
     }
-    if initializer_list {
+    if initializer_list && !cxx_header {
         writeln!(out, "#include <initializer_list>");
     }
-    if iterator {
+    if iterator && !cxx_header {
         writeln!(out, "#include <iterator>");
     }
     if memory {
         writeln!(out, "#include <memory>");
     }
-    if new {
+    if new && !cxx_header {
         writeln!(out, "#include <new>");
     }
-    if string {
+    if string && !cxx_header {
         writeln!(out, "#include <string>");
     }
-    if type_traits {
+    if type_traits && !cxx_header {
         writeln!(out, "#include <type_traits>");
     }
-    if utility {
+    if utility && !cxx_header {
         writeln!(out, "#include <utility>");
     }
-    if vector {
+    if vector && !cxx_header {
         writeln!(out, "#include <vector>");
     }
-    if basetsd {
+    if basetsd && !cxx_header {
         writeln!(out, "#if defined(_WIN32)");
         writeln!(out, "#include <basetsd.h>");
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         if basetsd {
             writeln!(out, "#else");
         } else {
             writeln!(out, "#if not defined(_WIN32)");
         }
     }
-    if sys_types {
+    if sys_types && !cxx_header {
         writeln!(out, "#include <sys/types.h>");
     }
-    if basetsd || sys_types {
+    if (basetsd || sys_types) && !cxx_header {
         writeln!(out, "#endif");
     }
 }

From c5b42c57ab0c44c7504aca68303fe26e8cff96df Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 17:40:15 +0000
Subject: [PATCH 2194/2232] Lockfile update


---

diff --git a/third-party/BUCK b/third-party/BUCK
index aed26e4..dddccee 100644
--- a/third-party/BUCK
+++ b/third-party/BUCK
@@ -72,7 +72,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.64/src/**"]),
+    srcs = glob(["vendor/syn-1.0.65/src/**"]),
     visibility = ["PUBLIC"],
     features = [
         "clone-impls",
diff --git a/third-party/BUILD b/third-party/BUILD
index a31023b..3ea9295 100644
--- a/third-party/BUILD
+++ b/third-party/BUILD
@@ -76,7 +76,7 @@ rust_library(
 
 rust_library(
     name = "syn",
-    srcs = glob(["vendor/syn-1.0.64/src/**"]),
+    srcs = glob(["vendor/syn-1.0.65/src/**"]),
     crate_features = [
         "clone-impls",
         "derive",
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index efb726d..4c406b8 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -283,9 +283,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
 [[package]]
 name = "syn"
-version = "1.0.64"
+version = "1.0.65"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f"
+checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
 dependencies = [
  "proc-macro2",
  "quote",

From ceb1ca9213c361d487e6be1e1f03a6e6e663055a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 17:41:14 +0000
Subject: [PATCH 2195/2232] Release 1.0.36


---

diff --git a/Cargo.toml b/Cargo.toml
index 12ce823..649d50f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.35" # remember to update html_root_url
+version = "1.0.36" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.35", path = "macro" }
+cxxbridge-macro = { version = "=1.0.36", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.35", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.36", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.35", path = "gen/build" }
+cxx-build = { version = "=1.0.36", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 66c35f9..4ba6b0e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.35"
+version = "1.0.36"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index a60f2fc..a3e5c4c 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.35"
+version = "1.0.36"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index eb68872..400abb0 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.35"
+version = "1.0.36"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 073fb11..7fd2a00 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.35"
+version = "0.7.36"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index c6bb164..dc0cebc 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.35"
+version = "1.0.36"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index aef3760..87d664c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.35")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.36")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 4c406b8..23aee54 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.35"
+version = "1.0.36"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.35"
+version = "1.0.36"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.35"
+version = "0.7.36"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.35"
+version = "1.0.36"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.35"
+version = "1.0.36"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.35"
+version = "1.0.36"
 dependencies = [
  "cxx",
  "proc-macro2",

From a9449375d03b74f8a46fadf70f261373598d30f3 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 20:42:46 +0000
Subject: [PATCH 2196/2232] Fix warning on unused unsafe_bitcopy variable


---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index adcd048..36e51d5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -15,6 +15,7 @@ pub struct Builtins<'a> {
     pub opaque: bool,
     pub layout: bool,
     pub unsafe_bitcopy: bool,
+    pub unsafe_bitcopy_t: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
     pub maybe_uninit: bool,
@@ -74,7 +75,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.utility = true;
         builtin.panic = true;
         builtin.rust_slice = true;
-        builtin.unsafe_bitcopy = true;
+        builtin.unsafe_bitcopy_t = true;
     }
 
     if builtin.rust_slice {
@@ -124,6 +125,10 @@ pub(super) fn write(out: &mut OutFile) {
         include.type_traits = true;
     }
 
+    if builtin.unsafe_bitcopy {
+        builtin.unsafe_bitcopy_t = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
 
@@ -165,6 +170,7 @@ pub(super) fn write(out: &mut OutFile) {
         ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
         ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
         ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+        ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
         ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
         ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
         ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
diff --git a/include/cxx.h b/include/cxx.h
index 7ee7db7..45ec64b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -484,12 +484,15 @@ Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept {
 }
 #endif // CXXBRIDGE1_RUST_FN
 
-#ifndef CXXBRIDGE1_RUST_BITCOPY
-#define CXXBRIDGE1_RUST_BITCOPY
+#ifndef CXXBRIDGE1_RUST_BITCOPY_T
+#define CXXBRIDGE1_RUST_BITCOPY_T
 struct unsafe_bitcopy_t final {
   explicit unsafe_bitcopy_t() = default;
 };
+#endif // CXXBRIDGE1_RUST_BITCOPY_T
 
+#ifndef CXXBRIDGE1_RUST_BITCOPY
+#define CXXBRIDGE1_RUST_BITCOPY
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE1_RUST_BITCOPY
 

From 07892531272c45dcbe39428bdcf0eefd6c729ea0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 20:49:38 +0000
Subject: [PATCH 2197/2232] Merge pull request #773 from dtolnay/bitcopy


Fix warning on unused unsafe_bitcopy variable
---

diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index adcd048..36e51d5 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -15,6 +15,7 @@ pub struct Builtins<'a> {
     pub opaque: bool,
     pub layout: bool,
     pub unsafe_bitcopy: bool,
+    pub unsafe_bitcopy_t: bool,
     pub rust_error: bool,
     pub manually_drop: bool,
     pub maybe_uninit: bool,
@@ -74,7 +75,7 @@ pub(super) fn write(out: &mut OutFile) {
         include.utility = true;
         builtin.panic = true;
         builtin.rust_slice = true;
-        builtin.unsafe_bitcopy = true;
+        builtin.unsafe_bitcopy_t = true;
     }
 
     if builtin.rust_slice {
@@ -124,6 +125,10 @@ pub(super) fn write(out: &mut OutFile) {
         include.type_traits = true;
     }
 
+    if builtin.unsafe_bitcopy {
+        builtin.unsafe_bitcopy_t = true;
+    }
+
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
 
@@ -165,6 +170,7 @@ pub(super) fn write(out: &mut OutFile) {
         ifndef::write(out, builtin.rust_str, "CXXBRIDGE1_RUST_STR");
         ifndef::write(out, builtin.rust_slice, "CXXBRIDGE1_RUST_SLICE");
         ifndef::write(out, builtin.rust_box, "CXXBRIDGE1_RUST_BOX");
+        ifndef::write(out, builtin.unsafe_bitcopy_t, "CXXBRIDGE1_RUST_BITCOPY_T");
         ifndef::write(out, builtin.unsafe_bitcopy, "CXXBRIDGE1_RUST_BITCOPY");
         ifndef::write(out, builtin.rust_vec, "CXXBRIDGE1_RUST_VEC");
         ifndef::write(out, builtin.rust_fn, "CXXBRIDGE1_RUST_FN");
diff --git a/include/cxx.h b/include/cxx.h
index 7ee7db7..45ec64b 100644
--- a/include/cxx.h
+++ b/include/cxx.h
@@ -484,12 +484,15 @@ Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept {
 }
 #endif // CXXBRIDGE1_RUST_FN
 
-#ifndef CXXBRIDGE1_RUST_BITCOPY
-#define CXXBRIDGE1_RUST_BITCOPY
+#ifndef CXXBRIDGE1_RUST_BITCOPY_T
+#define CXXBRIDGE1_RUST_BITCOPY_T
 struct unsafe_bitcopy_t final {
   explicit unsafe_bitcopy_t() = default;
 };
+#endif // CXXBRIDGE1_RUST_BITCOPY_T
 
+#ifndef CXXBRIDGE1_RUST_BITCOPY
+#define CXXBRIDGE1_RUST_BITCOPY
 constexpr unsafe_bitcopy_t unsafe_bitcopy{};
 #endif // CXXBRIDGE1_RUST_BITCOPY
 

From ddfb7cdb39f59558115e2009d09c01d897b22f5d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:07:05 +0000
Subject: [PATCH 2198/2232] Add ui test of checking mutable return from a shared reference argument


---

diff --git a/tests/ui/mut_return.rs b/tests/ui/mut_return.rs
new file mode 100644
index 0000000..74a5c69
--- /dev/null
+++ b/tests/ui/mut_return.rs
@@ -0,0 +1,11 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Thing;
+
+        fn f(t: &Thing) -> Pin<&mut CxxString>;
+        unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
new file mode 100644
index 0000000..27043d7
--- /dev/null
+++ b/tests/ui/mut_return.stderr
@@ -0,0 +1,11 @@
+error: &mut return type is not allowed unless there is a &mut argument
+ --> $DIR/mut_return.rs:6:9
+  |
+6 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: &mut return type is not allowed unless there is a &mut argument
+ --> $DIR/mut_return.rs:7:16
+  |
+7 |         unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
+  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From 2dec4215e3bb959a03231de7019bfeaf60f799cf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:07:54 +0000
Subject: [PATCH 2199/2232] Include unsafe token in notional span of extern fn signatures


---

diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 13b5cd3..c1a06a2 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -204,6 +204,7 @@ impl ToTokens for Enum {
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
+        self.unsafety.to_tokens(tokens);
         self.sig.fn_token.to_tokens(tokens);
         self.semi_token.to_tokens(tokens);
     }
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
index 27043d7..6b091d7 100644
--- a/tests/ui/mut_return.stderr
+++ b/tests/ui/mut_return.stderr
@@ -5,7 +5,7 @@ error: &mut return type is not allowed unless there is a &mut argument
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: &mut return type is not allowed unless there is a &mut argument
- --> $DIR/mut_return.rs:7:16
+ --> $DIR/mut_return.rs:7:9
   |
 7 |         unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
-  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From 04376c7d94d2331f1851ea4563c8920e1b6335a0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:08:48 +0000
Subject: [PATCH 2200/2232] Permit mut from ref in unsafe-to-call signatures


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6ba6565..1e52c2e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -508,6 +508,11 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
 }
 
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
+    if efn.sig.unsafety.is_some() {
+        // Unrestricted as long as the function is made unsafe-to-call.
+        return;
+    }
+
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutable => {}
         _ => return,
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
index 6b091d7..d6ddb88 100644
--- a/tests/ui/mut_return.stderr
+++ b/tests/ui/mut_return.stderr
@@ -3,9 +3,3 @@ error: &mut return type is not allowed unless there is a &mut argument
   |
 6 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: &mut return type is not allowed unless there is a &mut argument
- --> $DIR/mut_return.rs:7:9
-  |
-7 |         unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
-  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From b226ad1c6be34bb21a8a3ca503f8b320e7a98590 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:14:17 +0000
Subject: [PATCH 2201/2232] Merge pull request #775 from dtolnay/mutfromref


Permit mut from ref in unsafe-to-call signatures
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 6ba6565..1e52c2e 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -508,6 +508,11 @@ fn check_api_impl(cx: &mut Check, imp: &Impl) {
 }
 
 fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
+    if efn.sig.unsafety.is_some() {
+        // Unrestricted as long as the function is made unsafe-to-call.
+        return;
+    }
+
     match &efn.ret {
         Some(Type::Ref(ty)) if ty.mutable => {}
         _ => return,
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index 13b5cd3..c1a06a2 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -204,6 +204,7 @@ impl ToTokens for Enum {
 impl ToTokens for ExternFn {
     fn to_tokens(&self, tokens: &mut TokenStream) {
         // Notional token range for error reporting purposes.
+        self.unsafety.to_tokens(tokens);
         self.sig.fn_token.to_tokens(tokens);
         self.semi_token.to_tokens(tokens);
     }
diff --git a/tests/ui/mut_return.rs b/tests/ui/mut_return.rs
new file mode 100644
index 0000000..74a5c69
--- /dev/null
+++ b/tests/ui/mut_return.rs
@@ -0,0 +1,11 @@
+#[cxx::bridge]
+mod ffi {
+    unsafe extern "C++" {
+        type Thing;
+
+        fn f(t: &Thing) -> Pin<&mut CxxString>;
+        unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
new file mode 100644
index 0000000..d6ddb88
--- /dev/null
+++ b/tests/ui/mut_return.stderr
@@ -0,0 +1,5 @@
+error: &mut return type is not allowed unless there is a &mut argument
+ --> $DIR/mut_return.rs:6:9
+  |
+6 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From 4a024613f1d127d9afc48c6e29aff089c52681ff Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:14:24 +0000
Subject: [PATCH 2202/2232] Fix wording of unsupported vector element type error


Vectors have elements, not targets. (Pointers, like unique_ptr and
shared_ptr, have targets -- matching the terminology of Target in the
std::ops::Deref trait.)

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 1e52c2e..807847c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -199,7 +199,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
         }
     }
 
-    cx.error(ptr, "unsupported vector target type");
+    cx.error(ptr, "unsupported vector element type");
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index 41cea63..a3e9343 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -10,7 +10,7 @@ error: unsupported unique_ptr target type
 7 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
   |                                      ^^^^^^^^^^^^^^^^^
 
-error: unsupported vector target type
+error: unsupported vector element type
  --> $DIR/ptr_unsupported.rs:8:45
   |
 8 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;

From ee8aa278fa2214dcdc777ea9570a5f783ff06940 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:20:29 +0000
Subject: [PATCH 2203/2232] Merge pull request #776 from dtolnay/vecelement


Fix wording of unsupported vector element type error
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 1e52c2e..807847c 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -199,7 +199,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
         }
     }
 
-    cx.error(ptr, "unsupported vector target type");
+    cx.error(ptr, "unsupported vector element type");
 }
 
 fn check_type_ref(cx: &mut Check, ty: &Ref) {
diff --git a/tests/ui/ptr_unsupported.stderr b/tests/ui/ptr_unsupported.stderr
index 41cea63..a3e9343 100644
--- a/tests/ui/ptr_unsupported.stderr
+++ b/tests/ui/ptr_unsupported.stderr
@@ -10,7 +10,7 @@ error: unsupported unique_ptr target type
 7 |         fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>;
   |                                      ^^^^^^^^^^^^^^^^^
 
-error: unsupported vector target type
+error: unsupported vector element type
  --> $DIR/ptr_unsupported.rs:8:45
   |
 8 |         fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>;

From a17230db8c57ffd760dec2f6e735775c628c70cd Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:36:51 +0000
Subject: [PATCH 2204/2232] Factor out Type traversal to a Visit trait


---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 87e3454..5422681 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -27,6 +27,7 @@ mod tokens;
 mod toposort;
 pub mod trivial;
 pub mod types;
+mod visit;
 
 use self::attrs::OtherAttrs;
 use self::discriminant::Discriminant;
diff --git a/syntax/types.rs b/syntax/types.rs
index 031dc08..196a1db 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -5,6 +5,7 @@ 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::visit::{self, Visit};
 use crate::syntax::{
     toposort, Api, Atom, Enum, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias,
 };
@@ -41,28 +42,16 @@ impl<'a> Types<'a> {
         let toposorted_structs = Vec::new();
 
         fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) {
-            all.insert(ty);
-            match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
-                Type::RustBox(ty)
-                | Type::UniquePtr(ty)
-                | Type::SharedPtr(ty)
-                | Type::WeakPtr(ty)
-                | Type::CxxVector(ty)
-                | Type::RustVec(ty) => visit(all, &ty.inner),
-                Type::Ref(r) => visit(all, &r.inner),
-                Type::Ptr(p) => visit(all, &p.inner),
-                Type::Array(a) => visit(all, &a.inner),
-                Type::SliceRef(s) => visit(all, &s.inner),
-                Type::Fn(f) => {
-                    if let Some(ret) = &f.ret {
-                        visit(all, ret);
-                    }
-                    for arg in &f.args {
-                        visit(all, &arg.ty);
-                    }
+            struct CollectTypes<'s, 'a>(&'s mut OrderedSet<&'a Type>);
+
+            impl<'s, 'a> Visit<'a> for CollectTypes<'s, 'a> {
+                fn visit_type(&mut self, ty: &'a Type) {
+                    self.0.insert(ty);
+                    visit::visit_type(self, ty);
                 }
             }
+
+            CollectTypes(all).visit_type(ty);
         }
 
         let mut add_resolution = |name: &'a Pair, generics: &'a Lifetimes| {
diff --git a/syntax/visit.rs b/syntax/visit.rs
new file mode 100644
index 0000000..2f31378
--- /dev/null
+++ b/syntax/visit.rs
@@ -0,0 +1,34 @@
+use crate::syntax::Type;
+
+pub trait Visit<'a> {
+    fn visit_type(&mut self, ty: &'a Type) {
+        visit_type(self, ty);
+    }
+}
+
+pub fn visit_type<'a, V>(visitor: &mut V, ty: &'a Type)
+where
+    V: Visit<'a> + ?Sized,
+{
+    match ty {
+        Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
+        Type::RustBox(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
+        | Type::CxxVector(ty)
+        | Type::RustVec(ty) => visitor.visit_type(&ty.inner),
+        Type::Ref(r) => visitor.visit_type(&r.inner),
+        Type::Ptr(p) => visitor.visit_type(&p.inner),
+        Type::Array(a) => visitor.visit_type(&a.inner),
+        Type::SliceRef(s) => visitor.visit_type(&s.inner),
+        Type::Fn(fun) => {
+            if let Some(ret) = &fun.ret {
+                visitor.visit_type(ret);
+            }
+            for arg in &fun.args {
+                visitor.visit_type(&arg.ty);
+            }
+        }
+    }
+}

From 7eee043035d2fa4160d249371562c5325535c6ba Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:46:57 +0000
Subject: [PATCH 2205/2232] Merge pull request #777 from dtolnay/visit


Factor out Type traversal to a Visit trait
---

diff --git a/syntax/mod.rs b/syntax/mod.rs
index 87e3454..5422681 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -27,6 +27,7 @@ mod tokens;
 mod toposort;
 pub mod trivial;
 pub mod types;
+mod visit;
 
 use self::attrs::OtherAttrs;
 use self::discriminant::Discriminant;
diff --git a/syntax/types.rs b/syntax/types.rs
index 031dc08..196a1db 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -5,6 +5,7 @@ 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::visit::{self, Visit};
 use crate::syntax::{
     toposort, Api, Atom, Enum, ExternType, Impl, Lifetimes, Pair, Struct, Type, TypeAlias,
 };
@@ -41,28 +42,16 @@ impl<'a> Types<'a> {
         let toposorted_structs = Vec::new();
 
         fn visit<'a>(all: &mut OrderedSet<&'a Type>, ty: &'a Type) {
-            all.insert(ty);
-            match ty {
-                Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
-                Type::RustBox(ty)
-                | Type::UniquePtr(ty)
-                | Type::SharedPtr(ty)
-                | Type::WeakPtr(ty)
-                | Type::CxxVector(ty)
-                | Type::RustVec(ty) => visit(all, &ty.inner),
-                Type::Ref(r) => visit(all, &r.inner),
-                Type::Ptr(p) => visit(all, &p.inner),
-                Type::Array(a) => visit(all, &a.inner),
-                Type::SliceRef(s) => visit(all, &s.inner),
-                Type::Fn(f) => {
-                    if let Some(ret) = &f.ret {
-                        visit(all, ret);
-                    }
-                    for arg in &f.args {
-                        visit(all, &arg.ty);
-                    }
+            struct CollectTypes<'s, 'a>(&'s mut OrderedSet<&'a Type>);
+
+            impl<'s, 'a> Visit<'a> for CollectTypes<'s, 'a> {
+                fn visit_type(&mut self, ty: &'a Type) {
+                    self.0.insert(ty);
+                    visit::visit_type(self, ty);
                 }
             }
+
+            CollectTypes(all).visit_type(ty);
         }
 
         let mut add_resolution = |name: &'a Pair, generics: &'a Lifetimes| {
diff --git a/syntax/visit.rs b/syntax/visit.rs
new file mode 100644
index 0000000..2f31378
--- /dev/null
+++ b/syntax/visit.rs
@@ -0,0 +1,34 @@
+use crate::syntax::Type;
+
+pub trait Visit<'a> {
+    fn visit_type(&mut self, ty: &'a Type) {
+        visit_type(self, ty);
+    }
+}
+
+pub fn visit_type<'a, V>(visitor: &mut V, ty: &'a Type)
+where
+    V: Visit<'a> + ?Sized,
+{
+    match ty {
+        Type::Ident(_) | Type::Str(_) | Type::Void(_) => {}
+        Type::RustBox(ty)
+        | Type::UniquePtr(ty)
+        | Type::SharedPtr(ty)
+        | Type::WeakPtr(ty)
+        | Type::CxxVector(ty)
+        | Type::RustVec(ty) => visitor.visit_type(&ty.inner),
+        Type::Ref(r) => visitor.visit_type(&r.inner),
+        Type::Ptr(p) => visitor.visit_type(&p.inner),
+        Type::Array(a) => visitor.visit_type(&a.inner),
+        Type::SliceRef(s) => visitor.visit_type(&s.inner),
+        Type::Fn(fun) => {
+            if let Some(ret) = &fun.ret {
+                visitor.visit_type(ret);
+            }
+            for arg in &fun.args {
+                visitor.visit_type(&arg.ty);
+            }
+        }
+    }
+}

From 944521ad0f062aefeb8e9445c7b0c2089d99a4a9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:58:38 +0000
Subject: [PATCH 2206/2232] Add some more mut return ui tests


---

diff --git a/tests/ui/mut_return.rs b/tests/ui/mut_return.rs
index 74a5c69..aef3680 100644
--- a/tests/ui/mut_return.rs
+++ b/tests/ui/mut_return.rs
@@ -1,10 +1,16 @@
 #[cxx::bridge]
 mod ffi {
+    extern "Rust" {
+        type Mut<'a>;
+    }
+
     unsafe extern "C++" {
         type Thing;
 
         fn f(t: &Thing) -> Pin<&mut CxxString>;
         unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
+        fn h(t: Box<Mut>) -> Pin<&mut CxxString>;
+        fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>;
     }
 }
 
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
index d6ddb88..76ac7db 100644
--- a/tests/ui/mut_return.stderr
+++ b/tests/ui/mut_return.stderr
@@ -1,5 +1,17 @@
 error: &mut return type is not allowed unless there is a &mut argument
- --> $DIR/mut_return.rs:6:9
-  |
-6 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
-  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $DIR/mut_return.rs:10:9
+   |
+10 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: &mut return type is not allowed unless there is a &mut argument
+  --> $DIR/mut_return.rs:12:9
+   |
+12 |         fn h(t: Box<Mut>) -> Pin<&mut CxxString>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: &mut return type is not allowed unless there is a &mut argument
+  --> $DIR/mut_return.rs:13:9
+   |
+13 |         fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From b55bd6392b74d734464702aa22f08d79bca95434 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 21:59:14 +0000
Subject: [PATCH 2207/2232] Allow mutable return reference on signatures with any lifetime in argument


---

diff --git a/syntax/check.rs b/syntax/check.rs
index 807847c..591e53d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
+use crate::syntax::visit::{self, Visit};
 use crate::syntax::{
     error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Ptr,
     Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
@@ -518,20 +519,45 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
         _ => return,
     }
 
-    if let Some(r) = &efn.receiver {
-        if r.mutable {
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutable {
+            return;
+        }
+        let resolve = cx.types.resolve(&receiver.ty);
+        if !resolve.generics.lifetimes.is_empty() {
             return;
         }
     }
 
-    for arg in &efn.args {
-        if let Type::Ref(ty) = &arg.ty {
-            if ty.mutable {
-                return;
-            }
+    struct FindLifetimeMut<'a> {
+        cx: &'a Check<'a>,
+        found: bool,
+    }
+
+    impl<'t, 'a> Visit<'t> for FindLifetimeMut<'a> {
+        fn visit_type(&mut self, ty: &'t Type) {
+            self.found |= match ty {
+                Type::Ref(ty) => ty.mutable,
+                Type::Ident(ident) => {
+                    let resolve = self.cx.types.resolve(ident);
+                    !resolve.generics.lifetimes.is_empty()
+                }
+                _ => false,
+            };
+            visit::visit_type(self, ty);
         }
     }
 
+    let mut visitor = FindLifetimeMut { cx, found: false };
+
+    for arg in &efn.args {
+        visitor.visit_type(&arg.ty);
+    }
+
+    if visitor.found {
+        return;
+    }
+
     cx.error(
         efn,
         "&mut return type is not allowed unless there is a &mut argument",
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
index 76ac7db..5845eb8 100644
--- a/tests/ui/mut_return.stderr
+++ b/tests/ui/mut_return.stderr
@@ -3,15 +3,3 @@ error: &mut return type is not allowed unless there is a &mut argument
    |
 10 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: &mut return type is not allowed unless there is a &mut argument
-  --> $DIR/mut_return.rs:12:9
-   |
-12 |         fn h(t: Box<Mut>) -> Pin<&mut CxxString>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: &mut return type is not allowed unless there is a &mut argument
-  --> $DIR/mut_return.rs:13:9
-   |
-13 |         fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From 5b97fc4e062d3e28b2547acc973681177f2eec31 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:05:21 +0000
Subject: [PATCH 2208/2232] Merge pull request #779 from dtolnay/mut


Allow mutable return reference on signatures with any lifetime in argument
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 807847c..591e53d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -1,5 +1,6 @@
 use crate::syntax::atom::Atom::{self, *};
 use crate::syntax::report::Errors;
+use crate::syntax::visit::{self, Visit};
 use crate::syntax::{
     error, ident, trivial, Api, Array, Enum, ExternFn, ExternType, Impl, Lang, NamedType, Ptr,
     Receiver, Ref, Signature, SliceRef, Struct, Trait, Ty1, Type, TypeAlias, Types,
@@ -518,20 +519,45 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
         _ => return,
     }
 
-    if let Some(r) = &efn.receiver {
-        if r.mutable {
+    if let Some(receiver) = &efn.receiver {
+        if receiver.mutable {
+            return;
+        }
+        let resolve = cx.types.resolve(&receiver.ty);
+        if !resolve.generics.lifetimes.is_empty() {
             return;
         }
     }
 
-    for arg in &efn.args {
-        if let Type::Ref(ty) = &arg.ty {
-            if ty.mutable {
-                return;
-            }
+    struct FindLifetimeMut<'a> {
+        cx: &'a Check<'a>,
+        found: bool,
+    }
+
+    impl<'t, 'a> Visit<'t> for FindLifetimeMut<'a> {
+        fn visit_type(&mut self, ty: &'t Type) {
+            self.found |= match ty {
+                Type::Ref(ty) => ty.mutable,
+                Type::Ident(ident) => {
+                    let resolve = self.cx.types.resolve(ident);
+                    !resolve.generics.lifetimes.is_empty()
+                }
+                _ => false,
+            };
+            visit::visit_type(self, ty);
         }
     }
 
+    let mut visitor = FindLifetimeMut { cx, found: false };
+
+    for arg in &efn.args {
+        visitor.visit_type(&arg.ty);
+    }
+
+    if visitor.found {
+        return;
+    }
+
     cx.error(
         efn,
         "&mut return type is not allowed unless there is a &mut argument",
diff --git a/tests/ui/mut_return.rs b/tests/ui/mut_return.rs
index 74a5c69..aef3680 100644
--- a/tests/ui/mut_return.rs
+++ b/tests/ui/mut_return.rs
@@ -1,10 +1,16 @@
 #[cxx::bridge]
 mod ffi {
+    extern "Rust" {
+        type Mut<'a>;
+    }
+
     unsafe extern "C++" {
         type Thing;
 
         fn f(t: &Thing) -> Pin<&mut CxxString>;
         unsafe fn g(t: &Thing) -> Pin<&mut CxxString>;
+        fn h(t: Box<Mut>) -> Pin<&mut CxxString>;
+        fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>;
     }
 }
 
diff --git a/tests/ui/mut_return.stderr b/tests/ui/mut_return.stderr
index d6ddb88..5845eb8 100644
--- a/tests/ui/mut_return.stderr
+++ b/tests/ui/mut_return.stderr
@@ -1,5 +1,5 @@
 error: &mut return type is not allowed unless there is a &mut argument
- --> $DIR/mut_return.rs:6:9
-  |
-6 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
-  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  --> $DIR/mut_return.rs:10:9
+   |
+10 |         fn f(t: &Thing) -> Pin<&mut CxxString>;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

From 47b820940c234adeb953c8b61d4771964782b154 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:05:28 +0000
Subject: [PATCH 2209/2232] Remove multiple arg lifetimes check


This was made obsolete by support for explicit lifetime annotations
in cxx 1.0.26.

---

diff --git a/syntax/check.rs b/syntax/check.rs
index 591e53d..5d02fa8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -469,8 +469,6 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if efn.lang == Lang::Cxx {
         check_mut_return_restriction(cx, efn);
     }
-
-    check_multiple_arg_lifetimes(cx, efn);
 }
 
 fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
@@ -564,35 +562,6 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     );
 }
 
-fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
-    if efn.lang == Lang::Cxx && efn.trusted {
-        return;
-    }
-
-    match &efn.ret {
-        Some(Type::Ref(_)) => {}
-        _ => return,
-    }
-
-    let mut reference_args = 0;
-    for arg in &efn.args {
-        if let Type::Ref(_) = &arg.ty {
-            reference_args += 1;
-        }
-    }
-
-    if efn.receiver.is_some() {
-        reference_args += 1;
-    }
-
-    if reference_args != 1 {
-        cx.error(
-            efn,
-            "functions that return a reference must take exactly one input reference",
-        );
-    }
-}
-
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"

From 3d656f87aa463a7716e9dcfb61c42662ca36b3df Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:10:54 +0000
Subject: [PATCH 2210/2232] Merge pull request #780 from dtolnay/argref


Remove multiple arg lifetimes check
---

diff --git a/syntax/check.rs b/syntax/check.rs
index 591e53d..5d02fa8 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -469,8 +469,6 @@ fn check_api_fn(cx: &mut Check, efn: &ExternFn) {
     if efn.lang == Lang::Cxx {
         check_mut_return_restriction(cx, efn);
     }
-
-    check_multiple_arg_lifetimes(cx, efn);
 }
 
 fn check_api_type_alias(cx: &mut Check, alias: &TypeAlias) {
@@ -564,35 +562,6 @@ fn check_mut_return_restriction(cx: &mut Check, efn: &ExternFn) {
     );
 }
 
-fn check_multiple_arg_lifetimes(cx: &mut Check, efn: &ExternFn) {
-    if efn.lang == Lang::Cxx && efn.trusted {
-        return;
-    }
-
-    match &efn.ret {
-        Some(Type::Ref(_)) => {}
-        _ => return,
-    }
-
-    let mut reference_args = 0;
-    for arg in &efn.args {
-        if let Type::Ref(_) = &arg.ty {
-            reference_args += 1;
-        }
-    }
-
-    if efn.receiver.is_some() {
-        reference_args += 1;
-    }
-
-    if reference_args != 1 {
-        cx.error(
-            efn,
-            "functions that return a reference must take exactly one input reference",
-        );
-    }
-}
-
 fn check_reserved_name(cx: &mut Check, ident: &Ident) {
     if ident == "Box"
         || ident == "UniquePtr"

From 6edd2d2a5968dbea1e4c11c725ee4ec2ecff95a0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:13:41 +0000
Subject: [PATCH 2211/2232] Add a void ptr cast for extern type aliases containing Rust-native types


---

diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6a9b5ac..f19eb86 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -19,7 +19,7 @@ impl<'a> Types<'a> {
                 } else if let Some(strct) = self.structs.get(ident) {
                     Depends(&strct.name.rust) // iterate to fixed-point
                 } else {
-                    Definite(self.rust.contains(ident))
+                    Definite(self.rust.contains(ident) || self.aliases.contains_key(ident))
                 }
             }
             Type::RustBox(_)

From f014a358e1cf0af716e737979e9cc979658f8cc1 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:20:01 +0000
Subject: [PATCH 2212/2232] Merge pull request #781 from dtolnay/aliascast


Add a void ptr cast for extern type aliases containing Rust-native types
---

diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6a9b5ac..f19eb86 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -19,7 +19,7 @@ impl<'a> Types<'a> {
                 } else if let Some(strct) = self.structs.get(ident) {
                     Depends(&strct.name.rust) // iterate to fixed-point
                 } else {
-                    Definite(self.rust.contains(ident))
+                    Definite(self.rust.contains(ident) || self.aliases.contains_key(ident))
                 }
             }
             Type::RustBox(_)

From 04955f4f0c1900e2ec52141f9291b8939723f7bf Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 22:20:43 +0000
Subject: [PATCH 2213/2232] Release 1.0.37


---

diff --git a/Cargo.toml b/Cargo.toml
index 649d50f..d38bb11 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.36" # remember to update html_root_url
+version = "1.0.37" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.36", path = "macro" }
+cxxbridge-macro = { version = "=1.0.37", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.36", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.37", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.36", path = "gen/build" }
+cxx-build = { version = "=1.0.37", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 4ba6b0e..370420e 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.36"
+version = "1.0.37"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index a3e5c4c..71e1570 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.36"
+version = "1.0.37"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 400abb0..1bb3498 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.36"
+version = "1.0.37"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 7fd2a00..a43e142 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.36"
+version = "0.7.37"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index dc0cebc..747553e 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.36"
+version = "1.0.37"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 87d664c..c1e0324 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.36")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.37")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index 23aee54..ef0723e 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.36"
+version = "1.0.37"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.36"
+version = "1.0.37"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.36"
+version = "0.7.37"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.36"
+version = "1.0.37"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.36"
+version = "1.0.37"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.36"
+version = "1.0.37"
 dependencies = [
  "cxx",
  "proc-macro2",

From 5d6429d212a840835ed8fcae5a5366d32b761b72 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 23:20:11 +0000
Subject: [PATCH 2214/2232] Factor out ptr/reference target type write


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 930ce0b..d3052ba 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1173,31 +1173,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Ref(r) => {
-            if let Type::Ptr(_) = r.inner {
-                write_type_space(out, &r.inner);
-                if !r.mutable {
-                    write!(out, "const");
-                }
-            } else {
-                if !r.mutable {
-                    write!(out, "const ");
-                }
-                write_type(out, &r.inner);
-            }
+            write_pointee_type(out, &r.inner, r.mutable);
             write!(out, " &");
         }
         Type::Ptr(p) => {
-            if let Type::Ptr(_) = p.inner {
-                write_type_space(out, &p.inner);
-                if !p.mutable {
-                    write!(out, "const");
-                }
-            } else {
-                if !p.mutable {
-                    write!(out, "const ");
-                }
-                write_type(out, &p.inner);
-            }
+            write_pointee_type(out, &p.inner, p.mutable);
             write!(out, " *");
         }
         Type::Str(_) => {
@@ -1235,6 +1215,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+// Write just the T type behind a &T or &mut T or *const T or *mut T.
+fn write_pointee_type(out: &mut OutFile, inner: &Type, mutable: bool) {
+    if let Type::Ptr(_) = inner {
+        write_type_space(out, inner);
+        if !mutable {
+            write!(out, "const");
+        }
+    } else {
+        if !mutable {
+            write!(out, "const ");
+        }
+        write_type(out, inner);
+    }
+}
+
 fn write_atom(out: &mut OutFile, atom: Atom) {
     match atom {
         Bool => write!(out, "bool"),

From 201cb747af0d7b2325b10ec66a953d92a7f96a28 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 23:29:54 +0000
Subject: [PATCH 2215/2232] Make reference type into pointer inside of MaybeUninit


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index d3052ba..7b0b49b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -873,7 +873,13 @@ fn write_rust_function_decl_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &sig.ret);
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(ret) => {
+                write_pointee_type(out, &ret.inner, ret.mutable);
+                write!(out, " *");
+            }
+            ret => write_type_space(out, ret),
+        }
         write!(out, "*return$");
         needs_comma = true;
     }
@@ -968,7 +974,13 @@ fn write_rust_function_shim_impl(
     if indirect_return {
         out.builtin.maybe_uninit = true;
         write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(ret) => {
+                write_pointee_type(out, &ret.inner, ret.mutable);
+                write!(out, " *");
+            }
+            ret => write_type(out, ret),
+        }
         writeln!(out, "> return$;");
         write!(out, "  ");
     } else if let Some(ret) = &sig.ret {
@@ -1051,8 +1063,15 @@ fn write_rust_function_shim_impl(
         writeln!(out, "  }}");
     }
     if indirect_return {
-        out.include.utility = true;
-        writeln!(out, "  return ::std::move(return$.value);");
+        write!(out, "  return ");
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(_) => write!(out, "*return$.value"),
+            _ => {
+                out.include.utility = true;
+                write!(out, "::std::move(return$.value)");
+            }
+        }
+        writeln!(out, ";");
     }
     writeln!(out, "}}");
 }

From 42b565b1d595caac8f5b015d84cfb034270861d8 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 26 2021 23:38:22 +0000
Subject: [PATCH 2216/2232] Merge pull request #784 from dtolnay/refresult


Support reference return type from fallible Rust function
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 930ce0b..7b0b49b 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -873,7 +873,13 @@ fn write_rust_function_decl_impl(
         if needs_comma {
             write!(out, ", ");
         }
-        write_return_type(out, &sig.ret);
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(ret) => {
+                write_pointee_type(out, &ret.inner, ret.mutable);
+                write!(out, " *");
+            }
+            ret => write_type_space(out, ret),
+        }
         write!(out, "*return$");
         needs_comma = true;
     }
@@ -968,7 +974,13 @@ fn write_rust_function_shim_impl(
     if indirect_return {
         out.builtin.maybe_uninit = true;
         write!(out, "::rust::MaybeUninit<");
-        write_type(out, sig.ret.as_ref().unwrap());
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(ret) => {
+                write_pointee_type(out, &ret.inner, ret.mutable);
+                write!(out, " *");
+            }
+            ret => write_type(out, ret),
+        }
         writeln!(out, "> return$;");
         write!(out, "  ");
     } else if let Some(ret) = &sig.ret {
@@ -1051,8 +1063,15 @@ fn write_rust_function_shim_impl(
         writeln!(out, "  }}");
     }
     if indirect_return {
-        out.include.utility = true;
-        writeln!(out, "  return ::std::move(return$.value);");
+        write!(out, "  return ");
+        match sig.ret.as_ref().unwrap() {
+            Type::Ref(_) => write!(out, "*return$.value"),
+            _ => {
+                out.include.utility = true;
+                write!(out, "::std::move(return$.value)");
+            }
+        }
+        writeln!(out, ";");
     }
     writeln!(out, "}}");
 }
@@ -1173,31 +1192,11 @@ fn write_type(out: &mut OutFile, ty: &Type) {
             write!(out, ">");
         }
         Type::Ref(r) => {
-            if let Type::Ptr(_) = r.inner {
-                write_type_space(out, &r.inner);
-                if !r.mutable {
-                    write!(out, "const");
-                }
-            } else {
-                if !r.mutable {
-                    write!(out, "const ");
-                }
-                write_type(out, &r.inner);
-            }
+            write_pointee_type(out, &r.inner, r.mutable);
             write!(out, " &");
         }
         Type::Ptr(p) => {
-            if let Type::Ptr(_) = p.inner {
-                write_type_space(out, &p.inner);
-                if !p.mutable {
-                    write!(out, "const");
-                }
-            } else {
-                if !p.mutable {
-                    write!(out, "const ");
-                }
-                write_type(out, &p.inner);
-            }
+            write_pointee_type(out, &p.inner, p.mutable);
             write!(out, " *");
         }
         Type::Str(_) => {
@@ -1235,6 +1234,21 @@ fn write_type(out: &mut OutFile, ty: &Type) {
     }
 }
 
+// Write just the T type behind a &T or &mut T or *const T or *mut T.
+fn write_pointee_type(out: &mut OutFile, inner: &Type, mutable: bool) {
+    if let Type::Ptr(_) = inner {
+        write_type_space(out, inner);
+        if !mutable {
+            write!(out, "const");
+        }
+    } else {
+        if !mutable {
+            write!(out, "const ");
+        }
+        write_type(out, inner);
+    }
+}
+
 fn write_atom(out: &mut OutFile, atom: Atom) {
     match atom {
         Bool => write!(out, "bool"),

From ff3205444f37479773826e35923743237a043bae Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 03:56:01 +0000
Subject: [PATCH 2217/2232] Suppress wrong_self_convention clippy false positive


https://github.com/rust-lang/rust-clippy/issues/6983

    warning: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
       --> macro/src/syntax/discriminant.rs:194:18
        |
    194 |     fn to_tokens(&self, tokens: &mut TokenStream) {
        |                  ^^^^^
        |
        = note: `#[warn(clippy::wrong_self_convention)]` on by default
        = help: consider choosing a less ambiguous name
        = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#wrong_self_convention

---

diff --git a/gen/build/src/lib.rs b/gen/build/src/lib.rs
index fda387d..63b2cf6 100644
--- a/gen/build/src/lib.rs
+++ b/gen/build/src/lib.rs
@@ -72,7 +72,9 @@
     clippy::too_many_arguments,
     clippy::too_many_lines,
     clippy::toplevel_ref_arg,
-    clippy::upper_case_acronyms
+    clippy::upper_case_acronyms,
+    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
+    clippy::wrong_self_convention
 )]
 
 mod cfg;
diff --git a/gen/cmd/src/main.rs b/gen/cmd/src/main.rs
index e8b6ead..f419dad 100644
--- a/gen/cmd/src/main.rs
+++ b/gen/cmd/src/main.rs
@@ -22,7 +22,9 @@
     clippy::struct_excessive_bools,
     clippy::too_many_arguments,
     clippy::too_many_lines,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
+    clippy::wrong_self_convention
 )]
 
 mod app;
diff --git a/gen/lib/src/lib.rs b/gen/lib/src/lib.rs
index 4329628..e3eca5e 100644
--- a/gen/lib/src/lib.rs
+++ b/gen/lib/src/lib.rs
@@ -31,7 +31,9 @@
     clippy::struct_excessive_bools,
     clippy::too_many_arguments,
     clippy::too_many_lines,
-    clippy::toplevel_ref_arg
+    clippy::toplevel_ref_arg,
+    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
+    clippy::wrong_self_convention
 )]
 
 mod error;
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index a92eae7..c24a607 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -23,7 +23,9 @@
     clippy::too_many_arguments,
     clippy::too_many_lines,
     clippy::toplevel_ref_arg,
-    clippy::useless_let_if_seq
+    clippy::useless_let_if_seq,
+    // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
+    clippy::wrong_self_convention
 )]
 
 extern crate proc_macro;

From 7238e8d11694d72ab7e49b122f59b915d0e2e8ad Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:04:27 +0000
Subject: [PATCH 2218/2232] Add test of passing by alias type by pin mut ref


---

diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index cd9fc2b..089a5c5 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -32,6 +32,9 @@ pub mod ffi2 {
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial_mut_ref(d: &mut D);
+        fn c_take_trivial_pin_ref(d: Pin<&D>);
+        fn c_take_trivial_pin_mut_ref(d: Pin<&mut D>);
         fn c_take_trivial_ref_method(self: &D);
         fn c_take_trivial_mut_ref_method(self: &mut D);
         fn c_take_trivial(d: D);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 831097d..a4d8c47 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -604,6 +604,18 @@ void c_take_trivial_ref(const D &d) {
   }
 }
 
+void c_take_trivial_mut_ref(D &d) {
+  (void)d;
+}
+
+void c_take_trivial_pin_ref(const D &d) {
+  (void)d;
+}
+
+void c_take_trivial_pin_mut_ref(D &d) {
+  (void)d;
+}
+
 void D::c_take_trivial_ref_method() const {
   if (d == 30) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index eaa4361..a5d8bc0 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -184,6 +184,9 @@ size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept;
 
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D &d);
+void c_take_trivial_mut_ref(D &d);
+void c_take_trivial_pin_ref(const D &d);
+void c_take_trivial_pin_mut_ref(D &d);
 void c_take_trivial(D d);
 
 void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g);

From 796e5954a3260f86a45c18adf0f6ed8e96510ec9 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:08:53 +0000
Subject: [PATCH 2219/2232] Handle pinned reference argument pointing to improper ctype


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 042fdcb..1ffd44f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -506,10 +506,18 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     false => quote!(::cxx::private::RustVec::from_ref(#var)),
                     true => quote!(::cxx::private::RustVec::from_mut(#var)),
                 },
-                inner if types.is_considered_improper_ctype(inner) => match ty.mutable {
-                    false => quote!(#var as *const #inner as *const ::std::ffi::c_void),
-                    true => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
-                },
+                inner if types.is_considered_improper_ctype(inner) => {
+                    let var = match ty.pinned {
+                        false => quote!(#var),
+                        true => quote!(::std::pin::Pin::into_inner_unchecked(#var)),
+                    };
+                    match ty.mutable {
+                        false => {
+                            quote!(#var as *const #inner as *const ::std::ffi::c_void)
+                        }
+                        true => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
+                    }
+                }
                 _ => quote!(#var),
             },
             Type::Ptr(ty) => {

From a84ad1365d36462dfdf12c400b39df863cc3448e Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:14:57 +0000
Subject: [PATCH 2220/2232] Merge pull request #785 from dtolnay/pinctype


Handle pinned reference argument pointing to improper ctype
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 042fdcb..1ffd44f 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -506,10 +506,18 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
                     false => quote!(::cxx::private::RustVec::from_ref(#var)),
                     true => quote!(::cxx::private::RustVec::from_mut(#var)),
                 },
-                inner if types.is_considered_improper_ctype(inner) => match ty.mutable {
-                    false => quote!(#var as *const #inner as *const ::std::ffi::c_void),
-                    true => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
-                },
+                inner if types.is_considered_improper_ctype(inner) => {
+                    let var = match ty.pinned {
+                        false => quote!(#var),
+                        true => quote!(::std::pin::Pin::into_inner_unchecked(#var)),
+                    };
+                    match ty.mutable {
+                        false => {
+                            quote!(#var as *const #inner as *const ::std::ffi::c_void)
+                        }
+                        true => quote!(#var as *mut #inner as *mut ::std::ffi::c_void),
+                    }
+                }
                 _ => quote!(#var),
             },
             Type::Ptr(ty) => {
diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs
index cd9fc2b..089a5c5 100644
--- a/tests/ffi/module.rs
+++ b/tests/ffi/module.rs
@@ -32,6 +32,9 @@ pub mod ffi2 {
 
         fn c_take_trivial_ptr(d: UniquePtr<D>);
         fn c_take_trivial_ref(d: &D);
+        fn c_take_trivial_mut_ref(d: &mut D);
+        fn c_take_trivial_pin_ref(d: Pin<&D>);
+        fn c_take_trivial_pin_mut_ref(d: Pin<&mut D>);
         fn c_take_trivial_ref_method(self: &D);
         fn c_take_trivial_mut_ref_method(self: &mut D);
         fn c_take_trivial(d: D);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index 831097d..a4d8c47 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -604,6 +604,18 @@ void c_take_trivial_ref(const D &d) {
   }
 }
 
+void c_take_trivial_mut_ref(D &d) {
+  (void)d;
+}
+
+void c_take_trivial_pin_ref(const D &d) {
+  (void)d;
+}
+
+void c_take_trivial_pin_mut_ref(D &d) {
+  (void)d;
+}
+
 void D::c_take_trivial_ref_method() const {
   if (d == 30) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index eaa4361..a5d8bc0 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -184,6 +184,9 @@ size_t c_get_use_count(const std::weak_ptr<C> &weak) noexcept;
 
 void c_take_trivial_ptr(std::unique_ptr<D> d);
 void c_take_trivial_ref(const D &d);
+void c_take_trivial_mut_ref(D &d);
+void c_take_trivial_pin_ref(const D &d);
+void c_take_trivial_pin_mut_ref(D &d);
 void c_take_trivial(D d);
 
 void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g);

From 6d3ea1fee6cc45fedfceb2ecc561368f44a16182 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:15:40 +0000
Subject: [PATCH 2221/2232] Release 1.0.38


---

diff --git a/Cargo.toml b/Cargo.toml
index d38bb11..de83efb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.37" # remember to update html_root_url
+version = "1.0.38" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.37", path = "macro" }
+cxxbridge-macro = { version = "=1.0.38", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.37", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.38", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.37", path = "gen/build" }
+cxx-build = { version = "=1.0.38", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 370420e..4fcf7e5 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.37"
+version = "1.0.38"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 71e1570..1637917 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.37"
+version = "1.0.38"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 1bb3498..88dc022 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.37"
+version = "1.0.38"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index a43e142..27dec3f 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.37"
+version = "0.7.38"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index 747553e..aa57ce8 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.37"
+version = "1.0.38"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index c1e0324..06f2ce8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.37")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.38")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index ef0723e..b137d05 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.37"
+version = "1.0.38"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.37"
+version = "1.0.38"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.37"
+version = "0.7.38"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.37"
+version = "1.0.38"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.37"
+version = "1.0.38"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.37"
+version = "1.0.38"
 dependencies = [
  "cxx",
  "proc-macro2",

From c547547b0305af5e01b1bae39fa0613e5f527984 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:23:04 +0000
Subject: [PATCH 2222/2232] Add ui test of impls on a nonlocal Rust type


---

diff --git a/tests/ui/nonlocal_rust_type.rs b/tests/ui/nonlocal_rust_type.rs
new file mode 100644
index 0000000..d8a238a
--- /dev/null
+++ b/tests/ui/nonlocal_rust_type.rs
@@ -0,0 +1,18 @@
+pub struct MyBuilder<'a> {
+    _s: &'a str,
+}
+
+type OptBuilder<'a> = Option<MyBuilder<'a>>;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type OptBuilder<'a>;
+    }
+
+    struct MyBuilder<'a> {
+        rs: Box<OptBuilder<'a>>,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr
new file mode 100644
index 0000000..584090a
--- /dev/null
+++ b/tests/ui/nonlocal_rust_type.stderr
@@ -0,0 +1,27 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/nonlocal_rust_type.rs:10:9
+   |
+10 |         type OptBuilder<'a>;
+   |         ^^^^^--------------
+   |         |    |
+   |         |    `Option` is not defined in the current crate
+   |         impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/nonlocal_rust_type.rs:7:1
+   |
+7  |   #[cxx::bridge]
+   |   ^^^^^^^^^^^^^^ impl doesn't use only types from inside the current crate
+...
+10 |           type OptBuilder<'a>;
+   |  ___________________________-
+11 | |     }
+12 | |
+13 | |     struct MyBuilder<'a> {
+14 | |         rs: Box<OptBuilder<'a>>,
+   | |__________________________- `Option` is not defined in the current crate
+   |
+   = note: define and implement a trait or new type instead
+   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 795e7b478f573581f26215b8f59fe412a42354e0 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:23:04 +0000
Subject: [PATCH 2223/2232] Factor out impl/ty generic splitting to module


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1ffd44f..700958c 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,4 +1,3 @@
-use crate::derive;
 use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
@@ -11,6 +10,7 @@ use crate::syntax::{
     Struct, Trait, Type, TypeAlias, Types,
 };
 use crate::type_id::Crate;
+use crate::{derive, generics};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
@@ -1137,11 +1137,7 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1189,11 +1185,7 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1252,11 +1244,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1348,11 +1336,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1430,11 +1414,7 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1507,11 +1487,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
diff --git a/macro/src/generics.rs b/macro/src/generics.rs
new file mode 100644
index 0000000..039dddd
--- /dev/null
+++ b/macro/src/generics.rs
@@ -0,0 +1,49 @@
+use crate::syntax::resolve::Resolution;
+use crate::syntax::Impl;
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+
+pub struct ImplGenerics<'a> {
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+}
+
+pub struct TyGenerics<'a> {
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+}
+
+pub fn split_for_impl<'a>(
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+) -> (ImplGenerics<'a>, TyGenerics<'a>) {
+    let impl_generics = ImplGenerics {
+        explicit_impl,
+        resolve,
+    };
+    let ty_generics = TyGenerics {
+        explicit_impl,
+        resolve,
+    };
+    (impl_generics, ty_generics)
+}
+
+impl<'a> ToTokens for ImplGenerics<'a> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(imp) = self.explicit_impl {
+            imp.impl_generics.to_tokens(tokens);
+        } else {
+            self.resolve.generics.to_tokens(tokens);
+        }
+    }
+}
+
+impl<'a> ToTokens for TyGenerics<'a> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(imp) = self.explicit_impl {
+            imp.ty_generics.to_tokens(tokens);
+        } else {
+            self.resolve.generics.to_tokens(tokens);
+        }
+    }
+}
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index c24a607..f8e7903 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -32,6 +32,7 @@ extern crate proc_macro;
 
 mod derive;
 mod expand;
+mod generics;
 mod syntax;
 mod type_id;
 
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 5422681..3d56293 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,7 +20,7 @@ mod parse;
 mod pod;
 pub mod qualified;
 pub mod report;
-mod resolve;
+pub mod resolve;
 pub mod set;
 pub mod symbol;
 mod tokens;

From dde630235b22e47936d34b88fa2c9d1a9a64407a Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:23:04 +0000
Subject: [PATCH 2224/2232] Track the angle brackets attached to generic implicit impls


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7b0b49b..406018a 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,7 @@ use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::instantiate::ImplKey;
+use crate::syntax::instantiate::{ImplKey, NamedImplKey};
 use crate::syntax::map::UnorderedMap as Map;
 use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
@@ -1349,7 +1349,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::ExternC);
     for impl_key in out.types.impls.keys() {
         out.next_section();
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
             ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
             ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
@@ -1363,7 +1363,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for impl_key in out.types.impls.keys() {
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
             ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
             _ => {}
@@ -1373,7 +1373,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
+fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) {
+    let ident = key.rust;
     let resolve = out.types.resolve(ident);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
@@ -1395,7 +1396,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1438,7 +1440,8 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     );
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
+fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) {
+    let ident = key.rust;
     let resolve = out.types.resolve(ident);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
@@ -1470,7 +1473,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1547,8 +1551,8 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
-    let ty = UniquePtr::Ident(ident);
+fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let ty = UniquePtr::Ident(key.rust);
     write_unique_ptr_common(out, ty);
 }
 
@@ -1663,7 +1667,8 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
+fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let ident = key.rust;
     let resolve = out.types.resolve(ident);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
@@ -1735,7 +1740,8 @@ fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
+fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let ident = key.rust;
     let resolve = out.types.resolve(ident);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
@@ -1794,7 +1800,8 @@ fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &Ident) {
+fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 700958c..c68c13d 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,7 +1,7 @@
 use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
-use crate::syntax::instantiate::ImplKey;
+use crate::syntax::instantiate::{ImplKey, NamedImplKey};
 use crate::syntax::qualified::QualifiedName;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
@@ -85,7 +85,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
     }
 
     for (impl_key, &explicit_impl) in &types.impls {
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => {
                 hidden.extend(expand_rust_box(ident, types, explicit_impl));
             }
@@ -1125,7 +1125,8 @@ fn type_id(name: &Pair) -> TokenStream {
     crate::type_id::expand(Crate::Cxx, qualified)
 }
 
-fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let ident = key.rust;
     let resolve = types.resolve(ident);
     let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
@@ -1165,7 +1166,8 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     }
 }
 
-fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let elem = key.rust;
     let resolve = types.resolve(elem);
     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
     let link_new = format!("{}new", link_prefix);
@@ -1233,7 +1235,12 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     }
 }
 
-fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_unique_ptr(
+    key: NamedImplKey,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
@@ -1326,7 +1333,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     }
 }
 
-fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_shared_ptr(
+    key: NamedImplKey,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
@@ -1404,7 +1416,8 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     }
 }
 
-fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
@@ -1471,7 +1484,12 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     }
 }
 
-fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
+fn expand_cxx_vector(
+    key: NamedImplKey,
+    explicit_impl: Option<&Impl>,
+    types: &Types,
+) -> TokenStream {
+    let elem = key.rust;
     let name = elem.to_string();
     let resolve = types.resolve(elem);
     let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
index e9c6f29..c2a5af0 100644
--- a/syntax/instantiate.rs
+++ b/syntax/instantiate.rs
@@ -1,43 +1,76 @@
-use crate::syntax::Type;
+use crate::syntax::{NamedType, Type};
 use proc_macro2::Ident;
+use std::hash::{Hash, Hasher};
+use syn::Token;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImplKey<'a> {
-    RustBox(&'a Ident),
-    RustVec(&'a Ident),
-    UniquePtr(&'a Ident),
-    SharedPtr(&'a Ident),
-    WeakPtr(&'a Ident),
-    CxxVector(&'a Ident),
+    RustBox(NamedImplKey<'a>),
+    RustVec(NamedImplKey<'a>),
+    UniquePtr(NamedImplKey<'a>),
+    SharedPtr(NamedImplKey<'a>),
+    WeakPtr(NamedImplKey<'a>),
+    CxxVector(NamedImplKey<'a>),
+}
+
+#[derive(Copy, Clone)]
+pub struct NamedImplKey<'a> {
+    pub rust: &'a Ident,
+    pub lt_token: Option<Token![<]>,
+    pub gt_token: Option<Token![>]>,
 }
 
 impl Type {
     pub(crate) fn impl_key(&self) -> Option<ImplKey> {
         if let Type::RustBox(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustBox(&ident.rust));
+                return Some(ImplKey::RustBox(NamedImplKey::from(ident)));
             }
         } else if let Type::RustVec(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustVec(&ident.rust));
+                return Some(ImplKey::RustVec(NamedImplKey::from(ident)));
             }
         } else if let Type::UniquePtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::UniquePtr(&ident.rust));
+                return Some(ImplKey::UniquePtr(NamedImplKey::from(ident)));
             }
         } else if let Type::SharedPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::SharedPtr(&ident.rust));
+                return Some(ImplKey::SharedPtr(NamedImplKey::from(ident)));
             }
         } else if let Type::WeakPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::WeakPtr(&ident.rust));
+                return Some(ImplKey::WeakPtr(NamedImplKey::from(ident)));
             }
         } else if let Type::CxxVector(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::CxxVector(&ident.rust));
+                return Some(ImplKey::CxxVector(NamedImplKey::from(ident)));
             }
         }
         None
     }
 }
+
+impl<'a> PartialEq for NamedImplKey<'a> {
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(self.rust, other.rust)
+    }
+}
+
+impl<'a> Eq for NamedImplKey<'a> {}
+
+impl<'a> Hash for NamedImplKey<'a> {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        self.rust.hash(hasher);
+    }
+}
+
+impl<'a> From<&'a NamedType> for NamedImplKey<'a> {
+    fn from(ty: &'a NamedType) -> Self {
+        NamedImplKey {
+            rust: &ty.rust,
+            lt_token: ty.generics.lt_token,
+            gt_token: ty.generics.gt_token,
+        }
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 196a1db..af7916d 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -171,7 +171,7 @@ impl<'a> Types<'a> {
                 | ImplKey::SharedPtr(ident)
                 | ImplKey::WeakPtr(ident)
                 | ImplKey::CxxVector(ident) => {
-                    Atom::from(ident).is_none() && !aliases.contains_key(ident)
+                    Atom::from(ident.rust).is_none() && !aliases.contains_key(ident.rust)
                 }
             };
             if implicit_impl && !impls.contains_key(&impl_key) {

From fedc63bfb734b533f50849fb13c821cbc9fc35bb Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:23:04 +0000
Subject: [PATCH 2225/2232] Simplify type resolution of named impl keys


---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 406018a..9f9c039 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1374,8 +1374,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
 }
 
 fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) {
-    let ident = key.rust;
-    let resolve = out.types.resolve(ident);
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
@@ -1441,8 +1440,7 @@ fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
 }
 
 fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) {
-    let ident = key.rust;
-    let resolve = out.types.resolve(ident);
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
@@ -1741,8 +1739,7 @@ fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) {
 }
 
 fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) {
-    let ident = key.rust;
-    let resolve = out.types.resolve(ident);
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
index 08fcf16..821f542 100644
--- a/syntax/resolve.rs
+++ b/syntax/resolve.rs
@@ -1,3 +1,4 @@
+use crate::syntax::instantiate::NamedImplKey;
 use crate::syntax::{Lifetimes, NamedType, Pair, Types};
 use proc_macro2::Ident;
 
@@ -31,3 +32,9 @@ impl UnresolvedName for NamedType {
         &self.rust
     }
 }
+
+impl<'a> UnresolvedName for NamedImplKey<'a> {
+    fn ident(&self) -> &Ident {
+        self.rust
+    }
+}

From eb55cee41e23109283f87dd1100ca044b1ab2693 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:23:04 +0000
Subject: [PATCH 2226/2232] Improve span of errors on impls of type with lifetimes


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c68c13d..d979bea 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1138,7 +1138,7 @@ fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1187,7 +1187,7 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1251,7 +1251,7 @@ fn expand_unique_ptr(
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1348,7 +1348,7 @@ fn expand_shared_ptr(
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1427,7 +1427,7 @@ fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
     let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
@@ -1505,7 +1505,7 @@ fn expand_cxx_vector(
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
-    let (impl_generics, ty_generics) = generics::split_for_impl(explicit_impl, resolve);
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let begin_span =
         explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
diff --git a/macro/src/generics.rs b/macro/src/generics.rs
index 039dddd..6c391fc 100644
--- a/macro/src/generics.rs
+++ b/macro/src/generics.rs
@@ -1,3 +1,4 @@
+use crate::syntax::instantiate::NamedImplKey;
 use crate::syntax::resolve::Resolution;
 use crate::syntax::Impl;
 use proc_macro2::TokenStream;
@@ -9,11 +10,13 @@ pub struct ImplGenerics<'a> {
 }
 
 pub struct TyGenerics<'a> {
+    key: NamedImplKey<'a>,
     explicit_impl: Option<&'a Impl>,
     resolve: Resolution<'a>,
 }
 
 pub fn split_for_impl<'a>(
+    key: NamedImplKey<'a>,
     explicit_impl: Option<&'a Impl>,
     resolve: Resolution<'a>,
 ) -> (ImplGenerics<'a>, TyGenerics<'a>) {
@@ -22,6 +25,7 @@ pub fn split_for_impl<'a>(
         resolve,
     };
     let ty_generics = TyGenerics {
+        key,
         explicit_impl,
         resolve,
     };
@@ -43,7 +47,9 @@ impl<'a> ToTokens for TyGenerics<'a> {
         if let Some(imp) = self.explicit_impl {
             imp.ty_generics.to_tokens(tokens);
         } else {
-            self.resolve.generics.to_tokens(tokens);
+            self.key.lt_token.to_tokens(tokens);
+            self.resolve.generics.lifetimes.to_tokens(tokens);
+            self.key.gt_token.to_tokens(tokens);
         }
     }
 }
diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr
index 584090a..7310509 100644
--- a/tests/ui/nonlocal_rust_type.stderr
+++ b/tests/ui/nonlocal_rust_type.stderr
@@ -12,16 +12,11 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/nonlocal_rust_type.rs:7:1
    |
-7  |   #[cxx::bridge]
-   |   ^^^^^^^^^^^^^^ impl doesn't use only types from inside the current crate
+7  | #[cxx::bridge]
+   | ^^^^^^^^^^^^^^ impl doesn't use only types from inside the current crate
 ...
-10 |           type OptBuilder<'a>;
-   |  ___________________________-
-11 | |     }
-12 | |
-13 | |     struct MyBuilder<'a> {
-14 | |         rs: Box<OptBuilder<'a>>,
-   | |__________________________- `Option` is not defined in the current crate
+14 |         rs: Box<OptBuilder<'a>>,
+   |                 --------------- `Option` is not defined in the current crate
    |
    = note: define and implement a trait or new type instead
    = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From 9dab9d8e3859d03a0b1c7fd1a60b0eb38eeea411 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:51:08 +0000
Subject: [PATCH 2227/2232] Track the outer type's spans too for implicit impls


---

diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
index c2a5af0..b6cbf24 100644
--- a/syntax/instantiate.rs
+++ b/syntax/instantiate.rs
@@ -1,5 +1,5 @@
-use crate::syntax::{NamedType, Type};
-use proc_macro2::Ident;
+use crate::syntax::{NamedType, Ty1, Type};
+use proc_macro2::{Ident, Span};
 use std::hash::{Hash, Hasher};
 use syn::Token;
 
@@ -15,36 +15,38 @@ pub enum ImplKey<'a> {
 
 #[derive(Copy, Clone)]
 pub struct NamedImplKey<'a> {
+    pub begin_span: Span,
     pub rust: &'a Ident,
     pub lt_token: Option<Token![<]>,
     pub gt_token: Option<Token![>]>,
+    pub end_span: Span,
 }
 
 impl Type {
     pub(crate) fn impl_key(&self) -> Option<ImplKey> {
         if let Type::RustBox(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustBox(NamedImplKey::from(ident)));
+                return Some(ImplKey::RustBox(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::RustVec(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustVec(NamedImplKey::from(ident)));
+                return Some(ImplKey::RustVec(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::UniquePtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::UniquePtr(NamedImplKey::from(ident)));
+                return Some(ImplKey::UniquePtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::SharedPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::SharedPtr(NamedImplKey::from(ident)));
+                return Some(ImplKey::SharedPtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::WeakPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::WeakPtr(NamedImplKey::from(ident)));
+                return Some(ImplKey::WeakPtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::CxxVector(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::CxxVector(NamedImplKey::from(ident)));
+                return Some(ImplKey::CxxVector(NamedImplKey::new(ty, ident)));
             }
         }
         None
@@ -65,12 +67,14 @@ impl<'a> Hash for NamedImplKey<'a> {
     }
 }
 
-impl<'a> From<&'a NamedType> for NamedImplKey<'a> {
-    fn from(ty: &'a NamedType) -> Self {
+impl<'a> NamedImplKey<'a> {
+    fn new(outer: &Ty1, inner: &'a NamedType) -> Self {
         NamedImplKey {
-            rust: &ty.rust,
-            lt_token: ty.generics.lt_token,
-            gt_token: ty.generics.gt_token,
+            begin_span: outer.name.span(),
+            rust: &inner.rust,
+            lt_token: inner.generics.lt_token,
+            gt_token: inner.generics.gt_token,
+            end_span: outer.rangle.span,
         }
     }
 }

From 933ab95200f29a5da57bc162cfbb521a2ed1234d Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 05:57:19 +0000
Subject: [PATCH 2228/2232] Further improve span of errors within implicit impls


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index d979bea..32f9b92 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1140,9 +1140,8 @@ fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
 
     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1189,9 +1188,8 @@ fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
 
     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1273,9 +1271,8 @@ fn expand_unique_ptr(
         None
     };
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1368,9 +1365,8 @@ fn expand_shared_ptr(
         None
     };
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1429,9 +1425,8 @@ fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
 
     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1507,9 +1502,8 @@ fn expand_cxx_vector(
 
     let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr
index 7310509..d266353 100644
--- a/tests/ui/nonlocal_rust_type.stderr
+++ b/tests/ui/nonlocal_rust_type.stderr
@@ -10,13 +10,12 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
    = note: define and implement a trait or new type instead
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/nonlocal_rust_type.rs:7:1
+  --> $DIR/nonlocal_rust_type.rs:14:13
    |
-7  | #[cxx::bridge]
-   | ^^^^^^^^^^^^^^ impl doesn't use only types from inside the current crate
-...
 14 |         rs: Box<OptBuilder<'a>>,
-   |                 --------------- `Option` is not defined in the current crate
+   |             ^^^^---------------
+   |             |   |
+   |             |   `Option` is not defined in the current crate
+   |             impl doesn't use only types from inside the current crate
    |
    = note: define and implement a trait or new type instead
-   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

From b1efdae73dd5a2164673e5c4e978074d201aee1b Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 06:10:42 +0000
Subject: [PATCH 2229/2232] Merge pull request #786 from dtolnay/spanimplicit


Improve span of errors on implicitly generated shim impls
---

diff --git a/gen/src/write.rs b/gen/src/write.rs
index 7b0b49b..9f9c039 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -3,7 +3,7 @@ use crate::gen::nested::NamespaceEntries;
 use crate::gen::out::OutFile;
 use crate::gen::{builtin, include, Opt};
 use crate::syntax::atom::Atom::{self, *};
-use crate::syntax::instantiate::ImplKey;
+use crate::syntax::instantiate::{ImplKey, NamedImplKey};
 use crate::syntax::map::UnorderedMap as Map;
 use crate::syntax::set::UnorderedSet;
 use crate::syntax::symbol::Symbol;
@@ -1349,7 +1349,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::ExternC);
     for impl_key in out.types.impls.keys() {
         out.next_section();
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => write_rust_box_extern(out, ident),
             ImplKey::RustVec(ident) => write_rust_vec_extern(out, ident),
             ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
@@ -1363,7 +1363,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.begin_block(Block::Namespace("rust"));
     out.begin_block(Block::InlineNamespace("cxxbridge1"));
     for impl_key in out.types.impls.keys() {
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => write_rust_box_impl(out, ident),
             ImplKey::RustVec(ident) => write_rust_vec_impl(out, ident),
             _ => {}
@@ -1373,8 +1373,8 @@ fn write_generic_instantiations(out: &mut OutFile) {
     out.end_block(Block::Namespace("rust"));
 }
 
-fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
-    let resolve = out.types.resolve(ident);
+fn write_rust_box_extern(out: &mut OutFile, key: NamedImplKey) {
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
@@ -1395,7 +1395,8 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
     );
 }
 
-fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_extern(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1438,8 +1439,8 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
     );
 }
 
-fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
-    let resolve = out.types.resolve(ident);
+fn write_rust_box_impl(out: &mut OutFile, key: NamedImplKey) {
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
@@ -1470,7 +1471,8 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
+fn write_rust_vec_impl(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
@@ -1547,8 +1549,8 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_unique_ptr(out: &mut OutFile, ident: &Ident) {
-    let ty = UniquePtr::Ident(ident);
+fn write_unique_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let ty = UniquePtr::Ident(key.rust);
     write_unique_ptr_common(out, ty);
 }
 
@@ -1663,7 +1665,8 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
     writeln!(out, "}}");
 }
 
-fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
+fn write_shared_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let ident = key.rust;
     let resolve = out.types.resolve(ident);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
@@ -1735,8 +1738,8 @@ fn write_shared_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
-    let resolve = out.types.resolve(ident);
+fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) {
+    let resolve = out.types.resolve(&key);
     let inner = resolve.name.to_fully_qualified();
     let instance = resolve.name.to_symbol();
 
@@ -1794,7 +1797,8 @@ fn write_weak_ptr(out: &mut OutFile, ident: &Ident) {
     writeln!(out, "}}");
 }
 
-fn write_cxx_vector(out: &mut OutFile, element: &Ident) {
+fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
+    let element = key.rust;
     let inner = element.to_typename(out.types);
     let instance = element.to_mangled(out.types);
 
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 1ffd44f..32f9b92 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,8 +1,7 @@
-use crate::derive;
 use crate::syntax::atom::Atom::*;
 use crate::syntax::attrs::{self, OtherAttrs};
 use crate::syntax::file::Module;
-use crate::syntax::instantiate::ImplKey;
+use crate::syntax::instantiate::{ImplKey, NamedImplKey};
 use crate::syntax::qualified::QualifiedName;
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
@@ -11,6 +10,7 @@ use crate::syntax::{
     Struct, Trait, Type, TypeAlias, Types,
 };
 use crate::type_id::Crate;
+use crate::{derive, generics};
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
 use std::mem;
@@ -85,7 +85,7 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
     }
 
     for (impl_key, &explicit_impl) in &types.impls {
-        match impl_key {
+        match *impl_key {
             ImplKey::RustBox(ident) => {
                 hidden.extend(expand_rust_box(ident, types, explicit_impl));
             }
@@ -1125,7 +1125,8 @@ fn type_id(name: &Pair) -> TokenStream {
     crate::type_id::expand(Crate::Cxx, qualified)
 }
 
-fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_box(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let ident = key.rust;
     let resolve = types.resolve(ident);
     let link_prefix = format!("cxxbridge1$box${}$", resolve.name.to_symbol());
     let link_alloc = format!("{}alloc", link_prefix);
@@ -1137,15 +1138,10 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let local_dealloc = format_ident!("{}dealloc", local_prefix);
     let local_drop = format_ident!("{}drop", local_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1169,7 +1165,8 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     }
 }
 
-fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_rust_vec(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let elem = key.rust;
     let resolve = types.resolve(elem);
     let link_prefix = format!("cxxbridge1$rust_vec${}$", resolve.name.to_symbol());
     let link_new = format!("{}new", link_prefix);
@@ -1189,15 +1186,10 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
     let local_set_len = format_ident!("{}set_len", local_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1241,7 +1233,12 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
     }
 }
 
-fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_unique_ptr(
+    key: NamedImplKey,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$unique_ptr${}$", resolve.name.to_symbol());
@@ -1252,11 +1249,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_release = format!("{}release", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1278,9 +1271,8 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         None
     };
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1338,7 +1330,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     }
 }
 
-fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_shared_ptr(
+    key: NamedImplKey,
+    types: &Types,
+    explicit_impl: Option<&Impl>,
+) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
@@ -1348,11 +1345,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     let link_get = format!("{}get", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
     let can_construct_from_value = types.structs.contains_key(ident)
         || types.enums.contains_key(ident)
@@ -1372,9 +1365,8 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
         None
     };
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1420,7 +1412,8 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
     }
 }
 
-fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl>) -> TokenStream {
+    let ident = key.rust;
     let name = ident.to_string();
     let resolve = types.resolve(ident);
     let prefix = format!("cxxbridge1$weak_ptr${}$", resolve.name.to_symbol());
@@ -1430,15 +1423,10 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     let link_upgrade = format!("{}upgrade", prefix);
     let link_drop = format!("{}drop", prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
@@ -1491,7 +1479,12 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
     }
 }
 
-fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) -> TokenStream {
+fn expand_cxx_vector(
+    key: NamedImplKey,
+    explicit_impl: Option<&Impl>,
+    types: &Types,
+) -> TokenStream {
+    let elem = key.rust;
     let name = elem.to_string();
     let resolve = types.resolve(elem);
     let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
@@ -1507,15 +1500,10 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types) 
     let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
     let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);
 
-    let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
-        (&imp.impl_generics, &imp.ty_generics)
-    } else {
-        (resolve.generics, resolve.generics)
-    };
+    let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
 
-    let begin_span =
-        explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
-    let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
+    let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
+    let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span);
     let unsafe_token = format_ident!("unsafe", span = begin_span);
 
     quote_spanned! {end_span=>
diff --git a/macro/src/generics.rs b/macro/src/generics.rs
new file mode 100644
index 0000000..6c391fc
--- /dev/null
+++ b/macro/src/generics.rs
@@ -0,0 +1,55 @@
+use crate::syntax::instantiate::NamedImplKey;
+use crate::syntax::resolve::Resolution;
+use crate::syntax::Impl;
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+
+pub struct ImplGenerics<'a> {
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+}
+
+pub struct TyGenerics<'a> {
+    key: NamedImplKey<'a>,
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+}
+
+pub fn split_for_impl<'a>(
+    key: NamedImplKey<'a>,
+    explicit_impl: Option<&'a Impl>,
+    resolve: Resolution<'a>,
+) -> (ImplGenerics<'a>, TyGenerics<'a>) {
+    let impl_generics = ImplGenerics {
+        explicit_impl,
+        resolve,
+    };
+    let ty_generics = TyGenerics {
+        key,
+        explicit_impl,
+        resolve,
+    };
+    (impl_generics, ty_generics)
+}
+
+impl<'a> ToTokens for ImplGenerics<'a> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(imp) = self.explicit_impl {
+            imp.impl_generics.to_tokens(tokens);
+        } else {
+            self.resolve.generics.to_tokens(tokens);
+        }
+    }
+}
+
+impl<'a> ToTokens for TyGenerics<'a> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(imp) = self.explicit_impl {
+            imp.ty_generics.to_tokens(tokens);
+        } else {
+            self.key.lt_token.to_tokens(tokens);
+            self.resolve.generics.lifetimes.to_tokens(tokens);
+            self.key.gt_token.to_tokens(tokens);
+        }
+    }
+}
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index c24a607..f8e7903 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -32,6 +32,7 @@ extern crate proc_macro;
 
 mod derive;
 mod expand;
+mod generics;
 mod syntax;
 mod type_id;
 
diff --git a/syntax/instantiate.rs b/syntax/instantiate.rs
index e9c6f29..b6cbf24 100644
--- a/syntax/instantiate.rs
+++ b/syntax/instantiate.rs
@@ -1,43 +1,80 @@
-use crate::syntax::Type;
-use proc_macro2::Ident;
+use crate::syntax::{NamedType, Ty1, Type};
+use proc_macro2::{Ident, Span};
+use std::hash::{Hash, Hasher};
+use syn::Token;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImplKey<'a> {
-    RustBox(&'a Ident),
-    RustVec(&'a Ident),
-    UniquePtr(&'a Ident),
-    SharedPtr(&'a Ident),
-    WeakPtr(&'a Ident),
-    CxxVector(&'a Ident),
+    RustBox(NamedImplKey<'a>),
+    RustVec(NamedImplKey<'a>),
+    UniquePtr(NamedImplKey<'a>),
+    SharedPtr(NamedImplKey<'a>),
+    WeakPtr(NamedImplKey<'a>),
+    CxxVector(NamedImplKey<'a>),
+}
+
+#[derive(Copy, Clone)]
+pub struct NamedImplKey<'a> {
+    pub begin_span: Span,
+    pub rust: &'a Ident,
+    pub lt_token: Option<Token![<]>,
+    pub gt_token: Option<Token![>]>,
+    pub end_span: Span,
 }
 
 impl Type {
     pub(crate) fn impl_key(&self) -> Option<ImplKey> {
         if let Type::RustBox(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustBox(&ident.rust));
+                return Some(ImplKey::RustBox(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::RustVec(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::RustVec(&ident.rust));
+                return Some(ImplKey::RustVec(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::UniquePtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::UniquePtr(&ident.rust));
+                return Some(ImplKey::UniquePtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::SharedPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::SharedPtr(&ident.rust));
+                return Some(ImplKey::SharedPtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::WeakPtr(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::WeakPtr(&ident.rust));
+                return Some(ImplKey::WeakPtr(NamedImplKey::new(ty, ident)));
             }
         } else if let Type::CxxVector(ty) = self {
             if let Type::Ident(ident) = &ty.inner {
-                return Some(ImplKey::CxxVector(&ident.rust));
+                return Some(ImplKey::CxxVector(NamedImplKey::new(ty, ident)));
             }
         }
         None
     }
 }
+
+impl<'a> PartialEq for NamedImplKey<'a> {
+    fn eq(&self, other: &Self) -> bool {
+        PartialEq::eq(self.rust, other.rust)
+    }
+}
+
+impl<'a> Eq for NamedImplKey<'a> {}
+
+impl<'a> Hash for NamedImplKey<'a> {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        self.rust.hash(hasher);
+    }
+}
+
+impl<'a> NamedImplKey<'a> {
+    fn new(outer: &Ty1, inner: &'a NamedType) -> Self {
+        NamedImplKey {
+            begin_span: outer.name.span(),
+            rust: &inner.rust,
+            lt_token: inner.generics.lt_token,
+            gt_token: inner.generics.gt_token,
+            end_span: outer.rangle.span,
+        }
+    }
+}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 5422681..3d56293 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -20,7 +20,7 @@ mod parse;
 mod pod;
 pub mod qualified;
 pub mod report;
-mod resolve;
+pub mod resolve;
 pub mod set;
 pub mod symbol;
 mod tokens;
diff --git a/syntax/resolve.rs b/syntax/resolve.rs
index 08fcf16..821f542 100644
--- a/syntax/resolve.rs
+++ b/syntax/resolve.rs
@@ -1,3 +1,4 @@
+use crate::syntax::instantiate::NamedImplKey;
 use crate::syntax::{Lifetimes, NamedType, Pair, Types};
 use proc_macro2::Ident;
 
@@ -31,3 +32,9 @@ impl UnresolvedName for NamedType {
         &self.rust
     }
 }
+
+impl<'a> UnresolvedName for NamedImplKey<'a> {
+    fn ident(&self) -> &Ident {
+        self.rust
+    }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 196a1db..af7916d 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -171,7 +171,7 @@ impl<'a> Types<'a> {
                 | ImplKey::SharedPtr(ident)
                 | ImplKey::WeakPtr(ident)
                 | ImplKey::CxxVector(ident) => {
-                    Atom::from(ident).is_none() && !aliases.contains_key(ident)
+                    Atom::from(ident.rust).is_none() && !aliases.contains_key(ident.rust)
                 }
             };
             if implicit_impl && !impls.contains_key(&impl_key) {
diff --git a/tests/ui/nonlocal_rust_type.rs b/tests/ui/nonlocal_rust_type.rs
new file mode 100644
index 0000000..d8a238a
--- /dev/null
+++ b/tests/ui/nonlocal_rust_type.rs
@@ -0,0 +1,18 @@
+pub struct MyBuilder<'a> {
+    _s: &'a str,
+}
+
+type OptBuilder<'a> = Option<MyBuilder<'a>>;
+
+#[cxx::bridge]
+mod ffi {
+    extern "Rust" {
+        type OptBuilder<'a>;
+    }
+
+    struct MyBuilder<'a> {
+        rs: Box<OptBuilder<'a>>,
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/nonlocal_rust_type.stderr b/tests/ui/nonlocal_rust_type.stderr
new file mode 100644
index 0000000..d266353
--- /dev/null
+++ b/tests/ui/nonlocal_rust_type.stderr
@@ -0,0 +1,21 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/nonlocal_rust_type.rs:10:9
+   |
+10 |         type OptBuilder<'a>;
+   |         ^^^^^--------------
+   |         |    |
+   |         |    `Option` is not defined in the current crate
+   |         impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+  --> $DIR/nonlocal_rust_type.rs:14:13
+   |
+14 |         rs: Box<OptBuilder<'a>>,
+   |             ^^^^---------------
+   |             |   |
+   |             |   `Option` is not defined in the current crate
+   |             impl doesn't use only types from inside the current crate
+   |
+   = note: define and implement a trait or new type instead

From 63ad1c409617f6077bef3f01ebd80fb1b64622ed Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 06:15:40 +0000
Subject: [PATCH 2230/2232] Release 1.0.39


---

diff --git a/Cargo.toml b/Cargo.toml
index de83efb..2ce810c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx"
-version = "1.0.38" # remember to update html_root_url
+version = "1.0.39" # remember to update html_root_url
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 links = "cxxbridge1"
@@ -21,15 +21,15 @@ default = ["cxxbridge-flags/default"] # c++11
 "c++20" = ["cxxbridge-flags/c++20"]
 
 [dependencies]
-cxxbridge-macro = { version = "=1.0.38", path = "macro" }
+cxxbridge-macro = { version = "=1.0.39", path = "macro" }
 link-cplusplus = "1.0"
 
 [build-dependencies]
 cc = "1.0.49"
-cxxbridge-flags = { version = "=1.0.38", path = "flags", default-features = false }
+cxxbridge-flags = { version = "=1.0.39", path = "flags", default-features = false }
 
 [dev-dependencies]
-cxx-build = { version = "=1.0.38", path = "gen/build" }
+cxx-build = { version = "=1.0.39", path = "gen/build" }
 cxx-gen = { version = "0.7", path = "gen/lib" }
 cxx-test-suite = { version = "0", path = "tests/ffi" }
 rustversion = "1.0"
diff --git a/flags/Cargo.toml b/flags/Cargo.toml
index 4fcf7e5..edb4fa5 100644
--- a/flags/Cargo.toml
+++ b/flags/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-flags"
-version = "1.0.38"
+version = "1.0.39"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/build/Cargo.toml b/gen/build/Cargo.toml
index 1637917..5584c55 100644
--- a/gen/build/Cargo.toml
+++ b/gen/build/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-build"
-version = "1.0.38"
+version = "1.0.39"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/cmd/Cargo.toml b/gen/cmd/Cargo.toml
index 88dc022..b134a11 100644
--- a/gen/cmd/Cargo.toml
+++ b/gen/cmd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-cmd"
-version = "1.0.38"
+version = "1.0.39"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/gen/lib/Cargo.toml b/gen/lib/Cargo.toml
index 27dec3f..4032f80 100644
--- a/gen/lib/Cargo.toml
+++ b/gen/lib/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxx-gen"
-version = "0.7.38"
+version = "0.7.39"
 authors = ["Adrian Taylor <adetaylor@chromium.org>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/macro/Cargo.toml b/macro/Cargo.toml
index aa57ce8..09521c1 100644
--- a/macro/Cargo.toml
+++ b/macro/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cxxbridge-macro"
-version = "1.0.38"
+version = "1.0.39"
 authors = ["David Tolnay <dtolnay@gmail.com>"]
 edition = "2018"
 license = "MIT OR Apache-2.0"
diff --git a/src/lib.rs b/src/lib.rs
index 06f2ce8..3ee80ed 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -364,7 +364,7 @@
 //! </table>
 
 #![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.38")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.39")]
 #![deny(improper_ctypes)]
 #![allow(non_camel_case_types)]
 #![allow(
diff --git a/third-party/Cargo.lock b/third-party/Cargo.lock
index b137d05..56a15bf 100644
--- a/third-party/Cargo.lock
+++ b/third-party/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
 
 [[package]]
 name = "cxx"
-version = "1.0.38"
+version = "1.0.39"
 dependencies = [
  "cc",
  "cxx-build",
@@ -79,7 +79,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-build"
-version = "1.0.38"
+version = "1.0.39"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -94,7 +94,7 @@ dependencies = [
 
 [[package]]
 name = "cxx-gen"
-version = "0.7.38"
+version = "0.7.39"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -114,7 +114,7 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-cmd"
-version = "1.0.38"
+version = "1.0.39"
 dependencies = [
  "clap",
  "codespan-reporting",
@@ -125,11 +125,11 @@ dependencies = [
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.38"
+version = "1.0.39"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.38"
+version = "1.0.39"
 dependencies = [
  "cxx",
  "proc-macro2",

From ac3aa932b7c2140caeeb3feb8e2d848ee08884f6 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 22:30:12 +0000
Subject: [PATCH 2231/2232] Hide extern "Rust" types' RustType impl from rustdoc


---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 32f9b92..73e2edf 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -755,6 +755,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
 
     let mut impls = quote_spanned! {span=>
+        #[doc(hidden)]
         #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
     };
 

From 72b8b7e5a2cde8378dcbbb7cecadf8fcd18f16c7 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Mar 27 2021 22:36:29 +0000
Subject: [PATCH 2232/2232] Merge pull request #787 from dtolnay/rusttype


Hide extern "Rust" types' RustType impl from rustdoc
---

diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 32f9b92..73e2edf 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -755,6 +755,7 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
     let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
 
     let mut impls = quote_spanned! {span=>
+        #[doc(hidden)]
         #unsafe_impl #generics ::cxx::private::RustType for #ident #generics {}
     };
 

